1212 * - Interwiki links: `[[[wikipedia:Article]]]` (for known prefixes)
1313 *
1414 * Special syntax:
15- * - `[[[*page]]]` -- `*` prefix is treated as a label prefix (ignored in target)
15+ * - `[[[*target]]]` -- `*` prefix is stripped from target; for external URLs,
16+ * adds `target="_blank"` (new tab)
1617 * - `[[[*|label]]]` -- links to root `/` with the given label
1718 * - `[[[page|]]]` -- empty label after pipe defaults to the page name
1819 *
@@ -86,7 +87,7 @@ function hasClosingLinkMarker(ctx: ParseContext, startPos: number): boolean {
8687 * - Empty target with pipe (`[[[|text]]]`) is invalid
8788 * - Multiple consecutive `#` in the target (`[[[page##anchor]]]`) is invalid
8889 * - `[[[*|label]]]` links to root `/`
89- * - `[[[*page ]]]` strips the `*` prefix from the target
90+ * - `[[[*target ]]]` strips `*`; adds `target="_blank"` for external URLs
9091 * - Category pages show only the text after the colon when no label is given
9192 */
9293export const linkTripleRule : InlineRule = {
@@ -174,13 +175,11 @@ export const linkTripleRule: InlineRule = {
174175 } ;
175176 }
176177
177- // Special case: [[[*|label]]] means link to root "/" with label
178+ // `*` prefix: stripped from target; sets target="_blank" for external URLs
178179 let finalTarget = trimmedTarget ;
179- if ( trimmedTarget === "*" && foundPipe ) {
180- finalTarget = "" ;
181- }
182- // Special case: [[[*page]]] - * is a label prefix, page is the target
183- if ( trimmedTarget . startsWith ( "*" ) && ! foundPipe ) {
180+ let hasStar = false ;
181+ if ( trimmedTarget . startsWith ( "*" ) ) {
182+ hasStar = true ;
184183 finalTarget = trimmedTarget . slice ( 1 ) ;
185184 }
186185
@@ -194,8 +193,9 @@ export const linkTripleRule: InlineRule = {
194193 displayText = trimmedLabel || finalTarget ;
195194 } else {
196195 // For category pages (system:Recent Changes), use only the part after colon
196+ // Use trimmedTarget (preserves * prefix) for display when no pipe
197197 const colonIdx = trimmedTarget . indexOf ( ":" ) ;
198- if ( colonIdx !== - 1 && ! trimmedTarget . startsWith ( "http" ) ) {
198+ if ( colonIdx !== - 1 && ! trimmedTarget . startsWith ( "http" ) && ! trimmedTarget . startsWith ( "*" ) ) {
199199 displayText = trimmedTarget . slice ( colonIdx + 1 ) . trim ( ) ;
200200 } else {
201201 displayText = trimmedTarget ;
@@ -214,7 +214,7 @@ export const linkTripleRule: InlineRule = {
214214 link,
215215 extra : null ,
216216 label,
217- target : null ,
217+ target : hasStar && linkType === "direct" ? "new-tab" : null ,
218218 } ,
219219 } ,
220220 ] ,
0 commit comments