User:HaeB/WRN import adjustments.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// To be used on a page imported from enwiki, for converting internal links to interwiki links pointing back to the originally linked page (excluding File: and Media: links). Adds a button in source editing mode (only for "Research:Newsletter" pages) that triggers the conversion and opens "Show changes", for the user to review and save the result.
// By [[User:HaeB]] (using ChatGPT o1-preview and Claude 3.5 Sonnet (new))
(function () {
'use strict';
let interwikiPrefixes = []; // To store the fetched interwiki prefixes
// The interwiki prefix to be added to (formerly) internal wikilinks (e.g., :w: for Wikipedia):
const targetInterwikiPrefix = ':w:';
// Interwiki prefixes that point to the (new) current wiki:
const sourceInterwikiPrefixes = ['m', 'meta'];
// todo: consistent use with/without colons
// Load the necessary modules
mw.loader.using(['oojs-ui', 'mediawiki.util', 'mediawiki.api']).then(function () {
// Check if the page title starts with "Research:Newsletter" and we're in editing mode
const pageTitle = mw.config.get('wgPageName');
if (!pageTitle.startsWith('Research:Newsletter') || mw.config.get('wgAction') !== 'edit') return;
// Fetch interwiki prefixes from the API
fetchInterwikiPrefixes().then(function () {
// Create a button in the toolbar once prefixes are fetched
const button = new OO.ui.ButtonWidget({
label: 'Convert links and templates',
icon: 'edit',
flags: ['progressive']
});
button.on('click', function () {
performConversions();
});
// Add the button to the toolbar in the edit page
$('#wpTextbox1').before(button.$element);
});
});
// Function to fetch interwiki prefixes from the API
function fetchInterwikiPrefixes() {
const api = new mw.Api();
return api.get({
action: 'query',
meta: 'siteinfo',
siprop: 'interwikimap'
}).then(function (data) {
// Filter out the 'wikipedia' prefix to avoid conflicts with the Wikipedia namespace
interwikiPrefixes = data.query.interwikimap
.map(entry => entry.prefix.toLowerCase())
.filter(prefix => prefix !== 'wikipedia');
});
}
// Helper function to parse template parameters while respecting nested structures
function parseTemplateParams(paramsString) {
const params = {};
let currentKey = '';
let currentValue = '';
let inValue = false;
let nestLevel = 0; // Track nesting level of [[...]] and {{...}}
let captureBuffer = '';
// Helper to add completed parameter to params object
function addParam() {
if (currentKey) {
const key = currentKey.trim();
const value = currentValue.trim();
if (key && value) {
params[key] = value;
}
}
currentKey = '';
currentValue = '';
inValue = false;
}
// Process character by character
for (let i = 0; i < paramsString.length; i++) {
const char = paramsString[i];
const nextChar = paramsString[i + 1] || '';
// Handle nested structures
if (char === '[' && nextChar === '[') {
nestLevel++;
captureBuffer += '[[';
i++; // Skip next [
continue;
}
if (char === ']' && nextChar === ']') {
nestLevel--;
captureBuffer += ']]';
i++; // Skip next ]
continue;
}
if (char === '{' && nextChar === '{') {
nestLevel++;
captureBuffer += '{{';
i++; // Skip next {
continue;
}
if (char === '}' && nextChar === '}') {
nestLevel--;
captureBuffer += '}}';
i++; // Skip next }
continue;
}
// Only process pipes and equals when not in nested structure
if (nestLevel === 0) {
if (char === '|') {
if (inValue) {
currentValue += captureBuffer;
} else {
currentKey = captureBuffer;
}
captureBuffer = '';
addParam();
continue;
}
if (char === '=' && !inValue) {
currentKey = captureBuffer;
captureBuffer = '';
inValue = true;
continue;
}
}
captureBuffer += char;
}
// Add final parameter
if (captureBuffer) {
if (inValue) {
currentValue = captureBuffer;
} else {
currentKey = captureBuffer;
}
addParam();
}
return params;
}
// Function to convert image templates to File syntax
function convertImageTemplates(content) {
// Regular expressions for both template types
const templateRegexes = [
/\{\{Wikipedia:Wikipedia Signpost\/Templates\/Inline image\s*\|((?:[^{}]|\{\{[^{}]*\}\})*)\}\}/g,
/\{\{Wikipedia:Wikipedia Signpost\/Templates\/Filler image-v2\s*\n?\s*\|((?:[^{}]|\{\{[^{}]*\}\})*)\}\}/g
];
let newContent = content;
// Process each template type
templateRegexes.forEach(regex => {
newContent = newContent.replace(regex, function(match, params) {
// Parse parameters using the new parser
const paramMap = parseTemplateParams(params);
// Construct File syntax
let fileString = '[[File:';
// Add image name
if (paramMap.image) {
fileString += paramMap.image.replace(/^(?:File:|Media:)/i, '');
}
// Add standard parameters
fileString += '|thumb';
if (paramMap.size) {
fileString += '|' + paramMap.size;
}
if (paramMap.align) {
fileString += '|' + paramMap.align;
}
if (paramMap.alt) {
fileString += '|alt=' + paramMap.alt;
}
if (paramMap.caption) {
fileString += '|' + paramMap.caption;
}
fileString += ']]';
return fileString;
});
});
return newContent;
}
// Function to perform all conversions
function performConversions() {
const editor = document.getElementById('wpTextbox1');
if (!editor) return;
// Define interwiki regex dynamically based on fetched prefixes
const interwikiRegex = new RegExp(`^\\s*:?(${interwikiPrefixes.join('|')}):`, 'i');
// Regular expression to match wikilinks,
// excluding File:, Media: and within-page section (anchor) links
const linkRegex = /\[\[(?!\s*(?:File|Media):|\s*#)([^\]|]+)(\|[^\]]+)?\]\]/g;
// Regular expression to match and remove interwiki prefixes pointing to the (new) source wiki
const sourcePrefixesPattern = sourceInterwikiPrefixes.join('|');
const currentWikiInterwikiPrefixRegex = new RegExp(`(\\[\\[\\s*):?(?:${sourcePrefixesPattern}):`, 'gi');
// Get content and perform both conversions
let newContent = editor.value;
// First convert the templates
newContent = convertImageTemplates(newContent);
// Then convert internal links to interwiki links
newContent = newContent.replace(linkRegex, function (match, p1, p2) {
// Trim whitespace from the link target
const linkTarget = p1.trim();
// If the link already has an interwiki prefix, skip it
if (interwikiRegex.test(linkTarget)) {
return match;
}
// Construct the new link
if (p2) {
// Piped link: [[Target|Display]]
return `[[${targetInterwikiPrefix}${linkTarget}${p2}]]`;
} else {
// Unpiped link: [[Target]]
return `[[${targetInterwikiPrefix}${linkTarget}|]]`;
}
});
// Lastly, remove interwiki prefixes pointing to the (new) source wiki,
// converting those interwiki links into internal wikilinks
newContent = newContent.replace(currentWikiInterwikiPrefixRegex, '$1');
editor.value = newContent;
// Click the "Show changes" button to preview changes
document.getElementById('wpDiff').click();
}
})();