Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3e019d5
Update patch dependencies
Mark-H May 1, 2025
22b4179
Major upgrade to Commonmark 2.6
Mark-H May 1, 2025
0b7bc80
Apply Slim4 and other major version upgrades
Mark-H May 1, 2025
d4dd169
Update github actions
Mark-H May 1, 2025
b88b79b
Fix validate
Mark-H May 1, 2025
a585df9
Add Autolink, Footnote, Smart punctuation, Strikethrough and Embed ex…
Mark-H May 1, 2025
ae4b7ff
Fix E_NOTICE if analytics id is not set
Mark-H May 1, 2025
79d8415
Add phpcs and phpcbf, implementing consistent code style
Mark-H May 1, 2025
f1cd1c4
Mute already exists errors
Mark-H May 1, 2025
9ce4aa2
Add automatically generated og/social media images with the page title
Mark-H May 1, 2025
6623fc2
Make sure we use local urls instead of canonical, and disable test mode
Mark-H May 1, 2025
e871927
Only use current page for the main title, not including the parent
Mark-H May 1, 2025
47d498a
Fix phpcs
Mark-H May 1, 2025
8c6566f
Oops, gotta fix it there too.
Mark-H May 1, 2025
9975936
Fix loading of versions and OpenCollective contributors
Mark-H May 9, 2025
9eca5e3
Rewrite db layer from sqlite to mysql for easier production deploy
Mark-H Jul 30, 2026
7bb04ff
Bump PHP requirement to 8.3 and refresh major dependencies.
Mark-H Jul 30, 2026
b803e24
Add Yoast PHPUnit polyfills and modernize the test suite.
Mark-H Jul 30, 2026
280f876
Reduce 404 noise with static discovery files and a scanner filter.
Mark-H Jul 30, 2026
9488178
Add split static sitemap generation with hreflang alternates.
Mark-H Jul 30, 2026
a62499a
Add stats:cleanup to prune old search and 404 analytics.
Mark-H Jul 30, 2026
5591385
Localize the 404 page from the URL language segment.
Mark-H Jul 30, 2026
01272e8
Hide the on-page TOC when it has fewer than two items.
Mark-H Jul 30, 2026
6a0e8a4
Add toggleable system/light/dark theme support.
Mark-H Jul 30, 2026
0965c95
Fix markdown link and image titles not rendering.
Mark-H Jul 30, 2026
9e833f1
Make /current point at the 3.x docs branch.
Mark-H Jul 30, 2026
b032b10
Include language home pages in Tree::getAllItems for indexing.
Mark-H Jul 30, 2026
c8613ee
Fix docs images 404ing after Slim 4 route change.
Mark-H Jul 30, 2026
19169e2
Tighten security around path handling and error output.
Mark-H Jul 30, 2026
f915481
Tighten content security
Mark-H Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env-dev
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ DOCS_DIRECTORY="/var/www/html/docs/"
TEMPLATE_DIRECTORY="/var/www/html/templates/"
CACHE_DIRECTORY="/var/www/html/cache"
UPDATE_SECRET="Generate secret: openssl rand -hex 38"

DB_HOST="mysql"
DB_PORT="3306"
DB_NAME="modxdocs"
DB_USER="modxdocs"
DB_PASSWORD="secret"
8 changes: 4 additions & 4 deletions .github/workflows/build-assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ jobs:

strategy:
matrix:
node-version: [15.x]
node-version: [20.x]

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Setting up node ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Cache npm modules
uses: actions/cache@v2
uses: actions/cache@v4
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
Expand Down
26 changes: 25 additions & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ on: [push, pull_request]

jobs:
validate-json:
name: 'validate json'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Validate language file
uses: docker://orrosenblatt/validate-json-action:latest
env:
Expand All @@ -17,3 +18,26 @@ jobs:
env:
INPUT_SCHEMA: ./sources.schema.json
INPUT_JSONS: ./sources.dist.json
phpcs:
name: 'phpcs + compat checker'
runs-on: ubuntu-latest
continue-on-error: true

strategy:
matrix:
php-version: ['8.3', '8.4']

steps:
- uses: actions/checkout@v4

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: pdo, pdo_mysql, zip, mysqli, gd

- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader

- name: phpcs
run: composer run phpcs -- --runtime-set testVersion ${{ matrix.php-version }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
.DS_Store
cache/*
!cache/.gitkeep
.phpunit.cache/
public/.htaccess
public/sitemap.xml
public/sitemaps/
node_modules/
.env
sources.json
Expand Down
16 changes: 9 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM node:16 AS node
FROM php:7.4-rc-apache
FROM php:8.3-apache

ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
Expand All @@ -25,14 +25,17 @@ RUN a2enmod rewrite \
&& a2dissite 000-default \
&& a2ensite docs

# Install Git
RUN apt-get update && apt-get install -y --force-yes git zlib1g-dev libicu-dev g++ \
# Install Git and PHP extensions
RUN apt-get update && apt-get install -y --no-install-recommends git zlib1g-dev libicu-dev g++ \
libzip-dev \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
zip \
&& docker-php-ext-configure intl \
&& docker-php-ext-install intl \
&& docker-php-ext-configure zip --with-libzip \
&& docker-php-ext-install zip
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install intl pdo_mysql zip gd \
&& rm -rf /var/lib/apt/lists/*

#Set final permissions
RUN mkdir /var/www/.npm && chown -R www-data:www-data /var/www/.npm
Expand All @@ -47,4 +50,3 @@ USER www-data

ENTRYPOINT ["/entrypoint.sh"]
CMD ["apache2-foreground"]

29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DocsApp for MODX

The DocsApp is a Slim application that serves up the [MODX documentation](https://github.com/modxorg/Docs) from markdown format into a fully functional site.
The DocsApp is a Slim application that serves up the [MODX documentation](https://github.com/modxorg/Docs) from markdown format into a fully functional site. It uses a light MySQL Database for indexing purposes.

Version-specific copies [of the markdown documentation](https://github.com/modxorg/Docs) go into the `/docs` directory. Then point a webserver at the `/public` directory to browse the documentation.

Expand All @@ -13,9 +13,9 @@ Version-specific copies [of the markdown documentation](https://github.com/modxo

1. Run a [composer install](https://getcomposer.org) in the root: `composer install`
2. Copy the default settings: `cp .env-dev .env`
3. Edit `.env` in your favorite file editor to fix the paths.
3. Edit `.env` in your favorite file editor to fix the paths and configure your MySQL database.
4. To run the latest version of the documentation (i.e. the version published on the modxorg/Docs repository), initialise the default documentation sources with `php docs.php sources:init`. To run a local clone of the documentation source, allowing you to immediately see your local changes inside the app, see custom sources below.
5. Point a webserver, running at least PHP 7.1, to the `/public` directory.
5. Point a webserver, running at least PHP 8.3, to the `/public` directory.
6. If you use apache, `cp public/ht.access public/.htaccess` and tweak (RewriteBase) as required. For nginx, set up the equivalent rewrites in your configuration.

### Custom Sources
Expand All @@ -39,7 +39,7 @@ For example, create it like this to have a local source for `2.x` and a separate
}
```

(Note that app treats "2.x" the same as "current", so to allow easy switching between versions in a local mirror, you'll want to call it something different. That's why in this example we called it "upstream")
(Note that the app treats "3.x" the same as "current", so to allow easy switching between versions in a local mirror, you'll want to call it something different. That's why in this example we called it "upstream")

Once you've done that, run `php docs.php sources:init` from the root of the project. (If you've run this previously, deleted the directories in the `/docs/` directory first.) You should see output like this:

Expand Down Expand Up @@ -118,12 +118,29 @@ git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"

### Searching / Indexing

To run the **search** locally, you'll first need to create the search index. Run `php docs.php index:init` to create the empty SQLite database, and then `php docs.php index:all` to populate the index. This may take a while (for 2.x + 3.x official documentation, 20-40 minutes depending on computer speed) as that will scan all files in the documentation to index possible search terms, as well as historic contributors (if the source is a git repo) for each file.
To run the **search** locally, you'll first need a MySQL database and the search index. Configure the `DB_*` environment variables in your `.env` file (see `.env-dev` for defaults), then run `php docs.php index:init` to create the database tables, and `php docs.php index:all` to populate the index. This may take a while (for 2.x + 3.x official documentation, 20-40 minutes depending on computer speed) as that will scan all files in the documentation to index possible search terms, as well as historic contributors (if the source is a git repo) for each file.

For the language switch to work, you also need to index the translations with `php docs.php index:translations`.

**These index actions are done automatically for changed files only (much faster!) as part of `php docs.php sources:update`.** Typically you'd only need to run the full indexing the first time setting up a mirror or clone.

When migrating from the previous SQLite setup, create a fresh MySQL database, run `index:init`, then rebuild the index with `index:all` and `index:translations`. Search analytics (`Searches`, `PageNotFound`) will start fresh.

### Analytics cleanup

Search queries and 404 hits are logged in the `Searches` and `PageNotFound` tables. To keep those tables from growing indefinitely, run `php docs.php stats:cleanup` on a schedule (for example daily via cron). By default this deletes records whose `last_seen` is older than 90 days; override with `--days`:

```bash
php docs.php stats:cleanup
php docs.php stats:cleanup --days=30
```

Example crontab entry (daily at 03:00):

```cron
0 3 * * * cd /path/to/app && php docs.php stats:cleanup
```

## Building assets

From the `public/template/` directory, first load the dependencies with `npm install`.
Expand All @@ -136,4 +153,4 @@ When preparing a patch for production, use `npm run release` which will build st

## Running in a Docker Container

Run `make` and `make install` or use the provided Dockerfile/docker-compose.yml. (see #3)
Run `make` and `make install` or use the provided Dockerfile/docker-compose.yml. Docker Compose includes a MySQL 8 service; the `docs` container waits for MySQL to be healthy before starting. (see #3)
43 changes: 29 additions & 14 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,55 @@
}
],
"require": {
"php": ">=7.4.0",
"php": ">=8.3.0",
"ext-json": "*",
"ext-pdo": "*",
"ext-sqlite3": "*",
"ext-pdo_mysql": "*",
"ext-fileinfo": "*",
"ext-mbstring": "*",
"slim/slim": "^3.1",
"slim/php-view": "^2.0",
"slim/twig-view": "^2.3",
"slim/slim": "^4.0",
"slim/psr7": "^1.6",
"php-di/php-di": "^7.0",
"monolog/monolog": "^3.0",
"slim/php-view": "^3.0",
"slim/twig-view": "^3.0",
"spatie/yaml-front-matter": "^2.0",
"league/commonmark": "^1.5",
"league/commonmark": "^2.6",
"caseyamcl/toc": "^3.0",
"vlucas/phpdotenv": "^3.3",
"symfony/console": "^5.2",
"symfony/process": "^5.2",
"voku/stop-words": "^2.0"
"vlucas/phpdotenv": "^5.6",
"symfony/console": "^7.0",
"symfony/process": "^7.0",
"voku/stop-words": "^2.0",
"embed/embed": "^4.4",
"ext-dom": "*",
"ext-gd": "*"
},
"require-dev": {
"ext-intl": "*"
"ext-intl": "*",
"squizlabs/php_codesniffer": "3.*",
"phpcompatibility/php-compatibility": "^9.3",
"yoast/phpunit-polyfills": "^4.0"
},
"autoload": {
"psr-4": {
"Tests\\": "tests/",
"MODXDocs\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"config": {
"process-timeout" : 0,
"platform": {
"php": "7.4.0"
"php": "8.3.0"
}
},
"scripts": {
"start": "php -S localhost:8080 -t public index.php",
"test": "phpunit"
"test": "@php vendor/bin/phpunit",
"phpcs": "vendor/bin/phpcs --standard=phpcs.xml",
"phpcbf": "vendor/bin/phpcbf --standard=phpcs.xml"
}
}
Loading
Loading