Fix bugs in link generation

* Use mw.Title so that template links work for templates outside
template namespace, and so that titles are normalized.
* Use recursion instead of while loop so that both the segments before
and after the inserted link are searched for further linking
possibilities. Among other cases, this fixes the case where a template
link before a wikilink (on the same line) was not working. This also
avoids infinite iteration if mw.Title.newFromText() failed to create a
valid Title object.

Bug: T368166
Bug: T374693
Change-Id: I4d485340928b81df26ca035874422fdb5930710f
This commit is contained in:
Siddharth VP 2024-09-14 22:29:28 +05:30
parent 16538948ae
commit 341cd2bc37

View file

@ -8,53 +8,59 @@ $( () => {
// by John Gruber, from https://daringfireball.net/2010/07/improved_regex_for_matching_urls
const URLRegExp = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()[\]{};:'".,<>?«»“”‘’]))/i;
function processComment( node ) {
let wikilinkMatch, templateMatch, URLMatch;
const textNode = node.firstChild; // always a text node.
const wikilinkRegExp = /\[\[([^|{}[\]\n]+)?(?:\|.*?)?]]/;
const templateRegExp = /\{\{([^|{}[\]\n#]+)(?=\||}})/;
while (
( wikilinkMatch = /\[\[([^|{}[\]\n]+)?(?:\|.*?)?]]/.exec( textNode.data ) ) ||
( templateMatch = /\{\{([^|{}[\]\n#]+)(?=\||}})/i.exec( textNode.data ) ) ||
function processComment( textNode, node ) {
let wikilinkMatch, templateMatch, URLMatch;
if (
( wikilinkMatch = wikilinkRegExp.exec( textNode.data ) ) ||
( templateMatch = templateRegExp.exec( textNode.data ) ) ||
( URLMatch = URLRegExp.exec( textNode.data ) )
) {
const link = document.createElement( 'a' );
let start = ( wikilinkMatch || templateMatch || URLMatch ).index;
let linkText;
let linkText, title;
link.classList.add( 'code-link' );
if ( URLMatch ) {
const URL = URLMatch[ 0 ];
link.href = URL;
linkText = URL;
} else {
let fullPageName;
if ( wikilinkMatch ) {
linkText = wikilinkMatch[ 0 ];
fullPageName = wikilinkMatch[ 1 ];
} else if ( templateMatch ) {
const pageName = templateMatch[ 1 ];
linkText = pageName;
fullPageName = mw.config.get( 'wgFormattedNamespaces' )[ 10 ] + ':' + pageName;
link.title = fullPageName;
start += 2; // opening braces "{{"
}
link.href = mw.util.getUrl( fullPageName );
} else if ( wikilinkMatch ) {
linkText = wikilinkMatch[ 0 ];
title = mw.Title.newFromText( wikilinkMatch[ 1 ] );
} else if ( templateMatch ) {
const pageName = templateMatch[ 1 ];
start += 2; // opening braces "{{"
linkText = pageName;
title = mw.Title.newFromText( pageName, 10 );
}
if ( title ) {
link.href = mw.util.getUrl( title.toText() );
link.title = title.toText();
}
if ( link.href ) {
const textBeforeLink = textNode.data.slice( 0, Math.max( 0, start ) ),
textAfterLink = textNode.data.slice( Math.max( 0, start + linkText.length ) );
const beforeLink = textNode.data.slice( 0, Math.max( 0, start ) ),
afterLink = textNode.data.slice( Math.max( 0, start + linkText.length ) );
textNode.data = afterLink;
link.appendChild( document.createTextNode( linkText ) );
node.insertBefore( link, textNode );
node.insertBefore( document.createTextNode( beforeLink ), link );
textNode.data = textAfterLink;
link.appendChild( document.createTextNode( linkText ) );
node.insertBefore( link, textNode );
const beforeTextNode = node.insertBefore( document.createTextNode( textBeforeLink ), link );
processComment( beforeTextNode, node );
processComment( textNode, node );
}
}
}
const commentClasses = [ 'c', 'c1', 'cm' ];
Array.from( document.getElementsByClassName( 'mw-highlight' ) ).forEach( ( codeBlock ) => {
commentClasses.forEach( ( commentClass ) => {
Array.from( codeBlock.getElementsByClassName( commentClass ) ).forEach( processComment );
Array.from( codeBlock.getElementsByClassName( commentClass ) ).forEach( ( node ) => {
processComment( node.firstChild, node );
} );
} );
} );