From 86516b33a52b25dec092b43ba2c263f43510af06 Mon Sep 17 00:00:00 2001 From: Alex <13487305+aavanian@users.noreply.github.com> Date: Fri, 28 Aug 2026 18:49:19 +0800 Subject: [PATCH] fix(route/wikipedia): parse current events top/bottom template form (#23122) The daily pages used to pass the items as the `content=` argument of a single {{Current events}} call; they now sit between a top=yes and a bottom=yes call. The parser only matched the old form, so it returned null for every day and the route failed with "this route is empty". Match the top/bottom pair. Co-authored-by: Claude Opus 5 --- lib/routes/wikipedia/current-events.ts | 29 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/routes/wikipedia/current-events.ts b/lib/routes/wikipedia/current-events.ts index 4bd23c32ce..24e4b5b44d 100644 --- a/lib/routes/wikipedia/current-events.ts +++ b/lib/routes/wikipedia/current-events.ts @@ -33,7 +33,14 @@ Notes: - strip css and possibly class/id - if the result is in wikitext, it needs to be converted to html -4. is the fastest and current implementation. */ +4. is the fastest and current implementation. + +A daily page's wikitext is shaped as: + {{Current events|year=YYYY|month=MM|day=D|top=yes}} + + ...items, as nested wikitext bullet lists under ''' section headings'''... + + {{Current events|year=YYYY|month=MM|day=D|bottom=yes}} */ function getCurrentEventsDatePath(date: Date): string { const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; @@ -45,20 +52,30 @@ function getCurrentEventsDatePath(date: Date): string { return `Portal:Current_events/${year}_${month}_${day}`; } +// The day's items sit between a {{Current events|...|top=yes}} and a +// {{Current events|...|bottom=yes}} call. Neither call nests braces, so [^{}] is enough to bound them. +const TOP_TEMPLATE = /\{\{\s*Current events\s*\|[^{}]*\btop\s*=\s*yes[^{}]*\}\}/i; +const BOTTOM_TEMPLATE = /\{\{\s*Current events\s*\|[^{}]*\bbottom\s*=\s*yes[^{}]*\}\}/i; + // Simple MediaWiki template parser for {{Current events}} template function parseCurrentEventsTemplate(wikitext: string): string | null { if (!wikitext) { return null; } - // Look for {{Current events|content=...}} template - // The closing }} is always at the end of wikitext - const contentMatch = wikitext.match(/\{\{Current events\s*\|[\s\S]*?content(?=(\s*=))\1\s*((?:\S[\s\S]*)?)\}\}$/); - if (!contentMatch) { + const top = wikitext.match(TOP_TEMPLATE); + if (!top) { return null; } - let content = contentMatch[2].trim(); + let content = wikitext.slice(top.index! + top[0].length); + + const bottom = content.match(BOTTOM_TEMPLATE); + if (bottom) { + content = content.slice(0, bottom.index); + } + + content = content.trim(); // Strip comments to detect empty content content = stripComments(content);