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..812e919
--- /dev/null
+++ b/conf/themes/silverstripe/404.twig
@@ -0,0 +1,40 @@
+
+
+
+ {# 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);
+ }
+}