260
edits
No edit summary |
No edit summary |
||
| Line 783: | Line 783: | ||
( function () { | ( function () { | ||
function | function smartSingleQuotes(text) { | ||
// | // Handle apostrophes in contractions or possessives first (like John's, it's) | ||
text = text.replace(/( | text = text.replace(/(\w)'(\w)/g, "$1’$2"); | ||
// | |||
text = text.replace(/( | // Then handle opening quotes (at start or after space/open punctuation) | ||
// | text = text.replace(/(^|[\s\(\[\{\"‘“])/g, function(match) { | ||
return match; // just return the same, will handle in next step | |||
return | }); | ||
// Now process alternation: alternate between opening ‘ and closing ’ | |||
let result = ""; | |||
let isOpen = true; | |||
for (let char of text) { | |||
if (char === "'") { | |||
result += isOpen ? "‘" : "’"; | |||
isOpen = !isOpen; | |||
} else { | |||
result += char; | |||
} | |||
} | |||
return result; | |||
} | } | ||
function walkAndReplace(root) { | function walkAndReplace(root) { | ||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); | |||
const blacklist = new Set(["CODE", "PRE", "SCRIPT", "STYLE", "TEXTAREA", "NOSCRIPT", "MATH"]); | |||
while (node = walker.nextNode()) { | let node; | ||
while ((node = walker.nextNode())) { | |||
if (!parent | let parent = node.parentNode; | ||
if (!parent || blacklist.has(parent.nodeName)) continue; | |||
let newText = smartSingleQuotes(node.nodeValue); | |||
if (newText !== node.nodeValue) node.nodeValue = newText; | if (newText !== node.nodeValue) node.nodeValue = newText; | ||
} | } | ||
} | } | ||
mw.hook("wikipage.content").add(function ($content) { | |||
mw.hook( | |||
walkAndReplace($content[0]); | walkAndReplace($content[0]); | ||
}); | }); | ||
document.addEventListener( | |||
document.addEventListener("DOMContentLoaded", function () { | |||
walkAndReplace(document.body); | walkAndReplace(document.body); | ||
}); | }); | ||
}( | })(); | ||