Skip to content

Add maintenance script to convert existing pages to the markdown content model#44

Merged
JeroenDeDauw merged 1 commit into
masterfrom
add-convert-to-markdown-model-script
Jul 17, 2026
Merged

Add maintenance script to convert existing pages to the markdown content model#44
JeroenDeDauw merged 1 commit into
masterfrom
add-convert-to-markdown-model-script

Conversation

@JeroenDeDauw

@JeroenDeDauw JeroenDeDauw commented Jul 17, 2026

Copy link
Copy Markdown
Member

Fixes #40

The activation settings ($wgNativeMarkdownSuffixDetection, $wgNativeMarkdownNamespaces) only default new
pages to the Markdown content model; pages that already exist keep their stored model. This adds the
retroactive counterpart: a maintenance script that selects existing wikitext pages the same way those
settings select new ones and switches them to Markdown. Run it as
php maintenance/run.php NativeMarkdown:ConvertToMarkdownModel, with --dry-run and --batch-size supported.

Two combinable selectors pick the pages, at least one required. --md-suffix mirrors live .md suffix
detection (titles ending in .md, outside the Template and MediaWiki namespaces, Talk included), and
--namespace <id> mirrors $wgNativeMarkdownNamespaces (every page in that namespace, any namespace, since an
explicit namespace is a deliberate choice). Both build MarkdownDefaultPolicy directly, the same policy the
creation-time hook uses, so the script and the live behaviour cannot drift, and they are independent of the
wiki's own configuration. Given together the selectors intersect to the .md-titled pages within that one
namespace, so --md-suffix --namespace 10 converts the .md pages in the Template namespace that
--md-suffix alone deliberately skips. The alternative, intersecting the suffix policy's own namespace rules,
was rejected because it would make that combination select nothing.

Only pages whose resolved current model is wikitext are ever converted, checked in PHP via
Title::getContentModel() rather than trusting page_content_model, which core stores as NULL whenever a page's
model equals its namespace default. Such NULL-model pages are candidates, while a NULL that resolves to a
css/js/json code model is correctly left alone. Redirects are skipped: the Markdown model reads the same
#REDIRECT [[Target]] syntax, so converting one would only add a revision without changing how it behaves.

Each conversion goes through core's ContentModelChange service, which writes a new revision with the text
unchanged plus a contentmodel log entry, attributed to the maintenance system user, which satisfies the
issue's attribution requirement. The class name is UpperCamel (ConvertToMarkdownModel), not the issue's
convertToMarkdownModel example, because run.php resolves extension scripts by directory name and
case-sensitive filename and expects the filename to match the class for clean PSR-4 autoloading; CirrusSearch
and AbuseFilter follow the same convention.

Note that MediaWiki 1.43 does not ship maintenance/changeContentModel.php (the stopgap the issue mentions),
so this script is the only command-line path for a bulk model change; Special:ChangeContentModel remains the
per-page, two-way tool.

AI-authored — Claude Code, Opus 4.8 (max); executed autonomously from a detailed implementation plan prepared in a separate Fable session at @JeroenDeDauw's request; diff not yet human-reviewed; verified locally (18 new PHPUnit integration tests plus the full extension suite, phpstan, psalm, phpcs, and an end-to-end dev-wiki smoke test); all CI checks green.

…ent model

Fixes #40

The activation settings ($wgNativeMarkdownSuffixDetection, $wgNativeMarkdownNamespaces) only default new
pages to the Markdown content model; pages that already exist keep their stored model. This adds the
retroactive counterpart: a maintenance script that selects existing wikitext pages the same way those
settings select new ones and switches them to Markdown. Run it as
`php maintenance/run.php NativeMarkdown:ConvertToMarkdownModel`, with `--dry-run` and `--batch-size` supported.

Two combinable selectors pick the pages, at least one required. `--md-suffix` mirrors live `.md` suffix
detection (titles ending in `.md`, outside the Template and MediaWiki namespaces, Talk included), and
`--namespace <id>` mirrors $wgNativeMarkdownNamespaces (every page in that namespace, any namespace, since an
explicit namespace is a deliberate choice). Both build MarkdownDefaultPolicy directly, the same policy the
creation-time hook uses, so the script and the live behaviour cannot drift, and they are independent of the
wiki's own configuration. Given together the selectors intersect to the `.md`-titled pages within that one
namespace, so `--md-suffix --namespace 10` converts the `.md` pages in the Template namespace that
`--md-suffix` alone deliberately skips. The alternative, intersecting the suffix policy's own namespace rules,
was rejected because it would make that combination select nothing.

Only pages whose resolved current model is wikitext are ever converted, checked in PHP via
Title::getContentModel() rather than trusting page_content_model, which core stores as NULL whenever a page's
model equals its namespace default. Such NULL-model pages are candidates, while a NULL that resolves to a
css/js/json code model is correctly left alone. Redirects are skipped: the Markdown model reads the same
`#REDIRECT [[Target]]` syntax, so converting one would only add a revision without changing how it behaves.

Each conversion goes through core's ContentModelChange service, which writes a new revision with the text
unchanged plus a `contentmodel` log entry, attributed to the maintenance system user, which satisfies the
issue's attribution requirement. The class name is UpperCamel (ConvertToMarkdownModel), not the issue's
`convertToMarkdownModel` example, because run.php resolves extension scripts by directory name and
case-sensitive filename and expects the filename to match the class for clean PSR-4 autoloading; CirrusSearch
and AbuseFilter follow the same convention.

Note that MediaWiki 1.43 does not ship maintenance/changeContentModel.php (the stopgap the issue mentions),
so this script is the only command-line path for a bulk model change; Special:ChangeContentModel remains the
per-page, two-way tool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.34%. Comparing base (a8f833a) to head (e271d86).

Additional details and impacted files
@@            Coverage Diff            @@
##             master      #44   +/-   ##
=========================================
  Coverage     83.34%   83.34%           
  Complexity      417      417           
=========================================
  Files            40       40           
  Lines          1069     1069           
=========================================
  Hits            891      891           
  Misses          178      178           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JeroenDeDauw
JeroenDeDauw marked this pull request as ready for review July 17, 2026 01:23
@JeroenDeDauw
JeroenDeDauw merged commit 8612d51 into master Jul 17, 2026
12 checks passed
@JeroenDeDauw
JeroenDeDauw deleted the add-convert-to-markdown-model-script branch July 17, 2026 01:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a maintenance script to convert existing pages to the markdown content model

2 participants