diff --git a/.github/workflows/deploy-gh-pages.yml b/.github/workflows/deploy-gh-pages.yml new file mode 100644 index 0000000..36a9cb2 --- /dev/null +++ b/.github/workflows/deploy-gh-pages.yml @@ -0,0 +1,61 @@ +name: Deploy to GitHub pages + +on: + push: + branches: [ "master" ] + workflow_dispatch: + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "gh-pages" + cancel-in-progress: false + +permissions: {} + +jobs: + build: + name: Build site + runs-on: ubuntu-latest + if: github.repository_owner == 'silverstripe' + permissions: + contents: read + steps: + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup GH pages + id: pages + uses: actions/configure-pages@v5 + + - name: Build static files + shell: bash + run: | + composer install + ./makedoc.sh + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: "htdocs/" + + deploy: + name: Deploy site + needs: build + runs-on: ubuntu-latest + if: github.repository_owner == 'silverstripe' + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{steps.deployment.outputs.page_url}} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.htaccess b/.htaccess deleted file mode 100644 index d27fe4d..0000000 --- a/.htaccess +++ /dev/null @@ -1,59 +0,0 @@ - - SetEnv HTTP_MOD_REWRITE On - RewriteEngine On - - - ### =============== Legacy redirects =============== - - # Packages no longer exist - RewriteCond %{REQUEST_URI} ^(.*)en/.*/package-.*\.html [NC] - RewriteRule ^(.*)$ %1 [L,R=302] - - # 2.x no longer exists - RewriteCond %{REQUEST_URI} ^(.*)en/2[.] [NC] - RewriteRule ^(.*)$ %1 [L,R=302] - - # Redirect non-languaged minor versions to major version, e.g. /3.1/DataObject.html to /3/DataObject.html - RewriteCond %{REQUEST_URI} ^(.*)(\d)[.]\d/(.*)$ [NC] - RewriteRule ^(\d)\.\d/(.*)$ %1%2/%3 [L,R=302] - - # Redirect language minor version to major version, e.g. /en/3.1/File.html to /3/File.html - RewriteCond %{REQUEST_URI} ^(.*)en/([\d]+)[.][\w.]+/(.*)$ [NC] - RewriteRule ^(.*)$ %1%2/%3 [L,R=302] - - # Class redirect. E.g. - # /4/class-SilverStripe.AssetAdmin.Forms.FileSearchFormFactory.html - # /4/SilverStripe/AssetAdmin/Forms/FileSearchFormFactory.html - RewriteCond %{REQUEST_URI} ^(.*)([\w.]+)/class-([\w]+)\.html [NC] - RewriteRule ^(.*)$ %1%2/%3.html [L,R=302] - RewriteCond %{REQUEST_URI} ^(.*)([\w.]+)/class-([\w]+)\.([\w]+)\.html [NC] - RewriteRule ^(.*)$ %1%2/%3/%4.html [L,R=302] - RewriteCond %{REQUEST_URI} ^(.*)([\w.]+)/class-([\w]+)\.([\w]+)\.([\w]+)\.html [NC] - RewriteRule ^(.*)$ %1%2/%3/%4/%5.html [L,R=302] - RewriteCond %{REQUEST_URI} ^(.*)([\w.]+)/class-([\w]+)\.([\w]+)\.([\w]+)\.([\w]+)\.html [NC] - RewriteRule ^(.*)$ %1%2/%3/%4/%5/%6.html [L,R=302] - RewriteCond %{REQUEST_URI} ^(.*)([\w.]+)/class-([\w]+)\.([\w]+)\.([\w]+)\.([\w]+)\.([\w]+)\.html [NC] - RewriteRule ^(.*)$ %1%2/%3/%4/%5/%6/%7.html [L,R=302] - RewriteCond %{REQUEST_URI} ^(.*)([\w.]+)/class-([\w]+)\.([\w]+)\.([\w]+)\.([\w]+)\.([\w]+)\.([\w]+)\.html [NC] - RewriteRule ^(.*)$ %1%2/%3/%4/%5/%6/%7/%8.html [L,R=302] - - ### ============= End Legacy redirects ============= - - # Lookup script (used to be a SS app, now just a simple script) - # E.g. http://api.silverstripe.org.loc/search/lookup/?q=SilverStripe\ORM\HasManyList&version=4&module=framework - RewriteCond %{REQUEST_URI} ^(.*)search/lookup [NC] - RewriteRule ^/?search/lookup(/|$) %1search/lookup.php [L,R=302,QSA] - - # Symlink to 5 index.html - default major version - RewriteCond %{REQUEST_URI} ^(.*)$ [NC] - RewriteRule ^/?$ %15/index.html [R=302,L] - - # Serve docs in htdocs - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_URI} .* [NC] - RewriteRule ^(.*)$ htdocs/$1 - - # 404 handling - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule .* errors/404.html - diff --git a/.platform.yml b/.platform.yml deleted file mode 100644 index c66e599..0000000 --- a/.platform.yml +++ /dev/null @@ -1,17 +0,0 @@ -infrastructure: ^3 -php_settings: - version: 8.1 - cli: - max_execution_time: 0 -shared_dirs: - mysite: - data: {} - htdocs: {} -crons: - mytask: - time: "0 3 * * *" - command: "/var/www/mysite/www/makedoc.sh | logger -t SilverStripe_cron" - vhost: "mysite" -url_rules: - mysite: - - '^.*': 'apache' diff --git a/browserconfig.xml b/browserconfig.xml deleted file mode 100644 index 83b318f..0000000 --- a/browserconfig.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - #005b94 - - - diff --git a/conf/doctum.json b/conf/doctum.json index bf9d5c6..33f8eb9 100644 --- a/conf/doctum.json +++ b/conf/doctum.json @@ -8,6 +8,7 @@ "4": "4.x", "3": "3.x" }, + "default_version": "5", "paths": { "www": "htdocs", "cache": "data/cache", diff --git a/conf/doctum.php b/conf/doctum.php index 7051914..e16a1a7 100644 --- a/conf/doctum.php +++ b/conf/doctum.php @@ -2,13 +2,13 @@ use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; -use Doctum\Project; use Doctum\Doctum; use SilverStripe\ApiDocs\Data\ApiJsonStore; use SilverStripe\ApiDocs\Data\Config; use SilverStripe\ApiDocs\Inspections\RecipeFinder; use SilverStripe\ApiDocs\Inspections\RecipeVersionCollection; use SilverStripe\ApiDocs\RemoteRepository\SilverStripeRemoteRepository; +use SilverStripe\ApiDocs\SilverstripeProject; // Get config $config = Config::getConfig(); @@ -70,7 +70,7 @@ // Override project unset($doctum['project']); $doctum['project'] = function ($sc) { - $project = new Project($sc['store'], $sc['_versions'], array( + $project = new SilverstripeProject($sc['store'], $sc['_versions'], array( 'build_dir' => $sc['build_dir'], 'cache_dir' => $sc['cache_dir'], 'remote_repository' => $sc['remote_repository'], @@ -82,6 +82,7 @@ 'source_dir' => $sc['source_dir'], 'insert_todos' => $sc['insert_todos'], 'base_url' => $sc['base_url'], + 'favicon' => 'favicon.ico', 'footer_link' => [ 'href' => 'https://github.com/silverstripe/api.silverstripe.org', 'rel' => 'noreferrer noopener', diff --git a/conf/themes/silverstripe/404.twig b/conf/themes/silverstripe/404.twig new file mode 100644 index 0000000..4dc2788 --- /dev/null +++ b/conf/themes/silverstripe/404.twig @@ -0,0 +1,41 @@ + + + + {# NOTE: Do not put this file into the manifest.yml, as that would render it per version rather than in the base dir #} + Not Found | {{ project.config('title') }} + + + + {% if project.config('favicon') %} + + {%- endif %} + + + + +
+
+
+

Whoa 404, either we broke something or you had a typing mishap :-/

+

Let's go back home.

+
+
+ + diff --git a/errors/error-styles.css b/conf/themes/silverstripe/css/error-styles.css similarity index 88% rename from errors/error-styles.css rename to conf/themes/silverstripe/css/error-styles.css index ca56053..a46eb4b 100644 --- a/errors/error-styles.css +++ b/conf/themes/silverstripe/css/error-styles.css @@ -1,5 +1,5 @@ .gif_holder { - background-image: url('https://www.silverstripe.com/themes/ssv3/img/banners/page-not-found.gif'); + background-image: url('/images/page-not-found.gif'); position: relative; z-index: 807; -webkit-background-size: cover; @@ -52,5 +52,5 @@ a:hover { body { padding: 0; - margin: 0;" -} \ No newline at end of file + margin: 0; +} diff --git a/conf/themes/silverstripe/images/favicon.ico b/conf/themes/silverstripe/images/favicon.ico new file mode 100644 index 0000000..f5d53b6 Binary files /dev/null and b/conf/themes/silverstripe/images/favicon.ico differ diff --git a/conf/themes/silverstripe/images/page-not-found.gif b/conf/themes/silverstripe/images/page-not-found.gif new file mode 100644 index 0000000..ebd084b Binary files /dev/null and b/conf/themes/silverstripe/images/page-not-found.gif differ diff --git a/conf/themes/silverstripe/main_index.twig b/conf/themes/silverstripe/main_index.twig new file mode 100644 index 0000000..a498649 --- /dev/null +++ b/conf/themes/silverstripe/main_index.twig @@ -0,0 +1,16 @@ + + + + {# NOTE: Do not put this file into the manifest.yml, as that would render it per version rather than as the main index file #} + Redirecting... + + + + {% if project.config('favicon') %} + + {%- endif %} + + +

Redirecting... if you aren't redirected automatically, click here

+ + diff --git a/conf/themes/silverstripe/main_search.twig b/conf/themes/silverstripe/main_search.twig new file mode 100644 index 0000000..d819029 --- /dev/null +++ b/conf/themes/silverstripe/main_search.twig @@ -0,0 +1,68 @@ + + + + {# NOTE: Do not put this file into the manifest.yml, as that would render it per version rather than in the base dir #} + Redirecting... + + + {% if project.config('favicon') %} + + {%- endif %} + + + + {# Fall back to just sending users to the default search page if the redirect fails for some reason #} +

Redirecting... if you aren't redirected automatically, click here

+ + diff --git a/conf/themes/silverstripe/manifest.yml b/conf/themes/silverstripe/manifest.yml index 1ddacca..05c8267 100644 --- a/conf/themes/silverstripe/manifest.yml +++ b/conf/themes/silverstripe/manifest.yml @@ -1,6 +1,11 @@ name: silverstripe parent: default +static: + 'images/favicon.ico': 'favicon.ico' + 'images/page-not-found.gif': 'images/page-not-found.gif' + 'css/error-styles.css': 'css/error-styles.css' + global: 'doctum.js.twig': 'doctum.js' diff --git a/errors/404.html b/errors/404.html deleted file mode 100644 index 92bab30..0000000 --- a/errors/404.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - Page not found » SilverStripe API docs - - - -
-
-
-

Whoa 404, either we broke something or you had a typing mishap :-/

-

Let's go back home.

-
-
- - diff --git a/manifest.json b/manifest.json deleted file mode 100644 index d73b243..0000000 --- a/manifest.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "SilverStripe", - "icons": [ - { - "src": "\/android-chrome-36x36.png", - "sizes": "36x36", - "type": "image\/png", - "density": "0.75" - }, - { - "src": "\/android-chrome-48x48.png", - "sizes": "48x48", - "type": "image\/png", - "density": "1.0" - }, - { - "src": "\/android-chrome-72x72.png", - "sizes": "72x72", - "type": "image\/png", - "density": "1.5" - }, - { - "src": "\/android-chrome-96x96.png", - "sizes": "96x96", - "type": "image\/png", - "density": "2.0" - }, - { - "src": "\/android-chrome-144x144.png", - "sizes": "144x144", - "type": "image\/png", - "density": "3.0" - }, - { - "src": "\/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image\/png", - "density": "4.0" - } - ] -} diff --git a/search/lookup.php b/search/lookup.php deleted file mode 100644 index 209fac3..0000000 --- a/search/lookup.php +++ /dev/null @@ -1,14 +0,0 @@ -setVersionMap(array( - '/^(\d+)[.].*$/' => '$1', -)); - -$lookup->handle(); diff --git a/src/Lookup.php b/src/Lookup.php deleted file mode 100644 index 719d63b..0000000 --- a/src/Lookup.php +++ /dev/null @@ -1,190 +0,0 @@ -args = $args; - } - - /** - * @return string[] - */ - public function getArgs() - { - return $this->args; - } - - /** - * Return an argument from the array - * - * @param string $key - * @return string - */ - public function getArg($key) - { - if (array_key_exists($key, $this->args)) { - return $this->args[$key]; - } - return null; - } - - /** - * Redirect the user to where they need to go. - * E.g. http://api.silverstripe.org/search/lookup/?q=SilverStripe\ORM\HasManyList&version=4&module=framework - * redirects to /4/SilverStripe/ORM/HasManyList.html - * - * @param bool $return When true, the redirect URL will be returned instead of a header issued - * @return string|null - */ - public function handle($return = false) - { - $url = $this->getURL(); - if ($return) { - return $url; - } - header('Location: ' . $url); - return null; - } - - /** - * Allow setting the "version mapping" that can be used to convert "4" to "master", etc - * - * Useful in the event that modules have strange branching strategies - * - * @param array $map - * @return $this - */ - public function setVersionMap($map) - { - $this->versionMap = $map; - return $this; - } - - /** - * Get the version from the URL, check for manually set version mapping - * - * @return string - */ - public function getVersion() - { - $version = $this->getArg('version') ?: self::DEFAULT_BRANCH; - foreach ($this->versionMap as $rule => $substitution) { - // Check regular expression rule - if (strpos($rule, '/') === 0 && preg_match($rule, $version)) { - return preg_replace($rule, $substitution, $version); - } - // Check exact rule - if (strpos($rule, '/') === false && $rule === $version) { - return $substitution; - } - } - return $version; - } - - /** - * Base dir - * - * @return string - */ - public function getBaseDir() - { - return __DIR__ . '/..'; - } - - /** - * Set the server name to use for API reference links - * - * @param string $name - * @return $this - */ - public function setServerName($name) - { - $this->serverName = $name; - return $this; - } - - /** - * Given a config determine the URL to navigate to - * - * @param array $searchConfig - * @return string - */ - protected function getURLForClass(array $searchConfig): string - { - $searchPath = '/' . $this->getVersion() . '/' . str_replace('\\', '/', $searchConfig['class']) . '.html'; - - // If file doesn't exist, redirect to search - if (!file_exists($this->getBaseDir() . '/htdocs' . $searchPath)) { - return '/' . $this->getVersion() . '/search.html?search=' . urlencode($searchConfig['class']); - } - - // Add hash-link on end - if ($searchConfig['property'] && $searchConfig['type']) { - $searchPath .= '#' . $searchConfig['type'] . '_' . $searchConfig['property']; - } - - return $searchPath; - } - - /** - * Get url for this search - * - * @return string - */ - protected function getURL(): string - { - // Search - $searchOrig = $this->getArg('q'); - if (!$searchOrig) { - return '/'; // Just go to home - } - - $search = str_replace(array('()', '$'), '', $searchOrig); - $searchParts = preg_split('/(::|\->)/', $search); - $searchConfig = array(); - if (count($searchParts) == 2) { - $searchConfig['class'] = $searchParts[0]; - $searchConfig['property'] = $searchParts[1]; - $searchConfig['type'] = (strpos($searchOrig, '()') !== false) ? 'method' : 'property'; - } else { - $searchConfig['class'] = $search; - $searchConfig['property'] = ''; - $searchConfig['type'] = 'class'; - } - - return $this->getURLForClass($searchConfig); - } -} diff --git a/src/SilverstripeProject.php b/src/SilverstripeProject.php new file mode 100644 index 0000000..5214b79 --- /dev/null +++ b/src/SilverstripeProject.php @@ -0,0 +1,47 @@ +renderMainPages(); + } + + public function render($callback = null, $force = false): void + { + parent::render($callback, $force); + $this->renderMainPages(); + } + + /** + * Renders pages that are not version dependent such as the main index.html + */ + private function renderMainPages() + { + $this->version = ''; + $this->initialize(); + $config = Config::getConfig(); + $variables = [ + // Get array of strings of major version numbers + 'versions' => array_map(fn($version) => (string)$version, array_keys($config['versions'])), + 'default_version' => $config['default_version'], + ]; + $this->renderer->save($this, 'index.html', 'main_index.twig', $variables); + $this->renderer->save($this, 'search.html', 'main_search.twig', $variables); + $this->renderer->save($this, '404.html', '404.twig', $variables); + } + + protected function replaceVars(string $pattern): string + { + if (!$this->version) { + $pattern = str_replace('%version%/', '', $pattern); + } + return parent::replaceVars($pattern); + } +}