User:Polygnotus/Scripts/WikiTextExpander.js

// WikiTextExpander

// This script allows you to expand acronyms and shorthand phrases using a configurable hotkey

// - Acronyms with colons (e.g. "WP:COI" and "WP:COI") are expanded as wiki links the conflict of interest guideline

// - Regular phrases are expanded without wiki links

// Default configuration

var textExpanderConfig = {

// Define your acronyms and phrases with their expansions here

expansionMap: {

// Wiki acronyms (will be expanded with format)

"WP:COI": "the conflict of interest guideline",

"WP:NPOV": "the neutral point of view policy",

"WP:RS": "the reliable sources guideline",

"WP:V": "the verifiability policy",

"WP:NOR": "the no original research policy",

"WP:BLP": "the biographies of living persons policy",

"WP:CITE": "the citation needed guideline",

"WP:N": "the notability guideline",

"MOS:LAYOUT": "the layout guideline",

"WP:TALK": "the talk page guideline",

// Regular phrases (will be expanded without wiki formatting)

"dupe": "This appears to be a duplicate of a previous submission. Please check the existing entries before submitting.",

"notref": "This is not a reliable reference according to our guidelines. Please provide a source that meets our reliability criteria.",

"format": "Please format your submission according to our style guide before resubmitting.",

"thanks": "Thank you for your contribution. I've reviewed it and made some minor edits for clarity.",

"sorry": "I apologize for the confusion. Let me clarify what I meant in my previous comment."

// Add more phrases as needed

},

// Default hotkey configuration: Ctrl+Shift+Z

hotkey: {

ctrlKey: true,

shiftKey: true,

altKey: false,

key: 'z'

}

};

// Try to load user configuration from localStorage if it exists

try {

var savedConfig = localStorage.getItem('textExpanderConfig');

if (savedConfig) {

var parsedConfig = JSON.parse(savedConfig);

// Merge saved configuration with defaults

if (parsedConfig.expansionMap) {

textExpanderConfig.expansionMap = parsedConfig.expansionMap;

}

if (parsedConfig.hotkey) {

textExpanderConfig.hotkey = parsedConfig.hotkey;

}

}

} catch (e) {

console.error('Error loading text expander config:', e);

}

// Function to save the configuration

function saveTextExpanderConfig() {

try {

localStorage.setItem('textExpanderConfig', JSON.stringify(textExpanderConfig));

} catch (e) {

console.error('Error saving text expander config:', e);

}

}

// Function to create a regular expression pattern for all expandable text

function getExpansionRegex() {

var escapedKeys = Object.keys(textExpanderConfig.expansionMap).map(function(key) {

return key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special characters

});

// Pattern to match both plain text and those inside wiki brackets

return new RegExp(

'(?

'\\[\\[(' + escapedKeys.join('|') + ')(?:\\|[^\\]]*?)?\\]\\]',

'g'

);

}

// Function to determine if a key should be formatted as a wiki link

function shouldFormatAsWikiLink(key) {

return key.indexOf(':') > -1;

}

// Function to expand all text in the selected text

function expandAllText() {

// Get the active editor input element

var activeElement = document.activeElement;

// Check if we're in an editable field

if (activeElement && (

activeElement.isContentEditable ||

activeElement.tagName === 'TEXTAREA' ||

(activeElement.tagName === 'INPUT' && activeElement.type === 'text')

)) {

var selectedText = '';

var expandedCount = 0;

// Handle different editor types

if (activeElement.isContentEditable) {

// Visual editor

var selection = window.getSelection();

if (selection.rangeCount > 0) {

var range = selection.getRangeAt(0);

selectedText = selection.toString();

// Only proceed if there's selected text

if (selectedText) {

// Create a document fragment for the new content

var newContent = selectedText;

var expansionRegex = getExpansionRegex();

// Replace all expandable text in the selected text

newContent = newContent.replace(expansionRegex, function(match, plainText, bracketedText) {

expandedCount++;

if (plainText) {

// This is plain text

var expansion = textExpanderConfig.expansionMap[plainText];

if (shouldFormatAsWikiLink(plainText)) {

// Format as wiki link

return '' + expansion + '';

} else {

// Just replace with the expansion

return expansion;

}

} else if (bracketedText) {

// This is already in brackets

if (match.indexOf('|') > -1) {

// Already has a pipe, don't modify

return match;

} else {

// Add the expansion

var expansion = textExpanderConfig.expansionMap[bracketedText];

return '' + expansion + '';

}

}

return match;

});

// Replace the selected text with the expanded text

if (expandedCount > 0) {

document.execCommand('insertText', false, newContent);

return expandedCount;

}

}

}

} else {

// Source editor (textarea or input)

var selStart = activeElement.selectionStart;

var selEnd = activeElement.selectionEnd;

selectedText = activeElement.value.substring(selStart, selEnd);

// Only proceed if there's selected text

if (selectedText) {

var expansionRegex = getExpansionRegex();

// Replace all expandable text in the selected text

var newContent = selectedText.replace(expansionRegex, function(match, plainText, bracketedText) {

expandedCount++;

if (plainText) {

// This is plain text

var expansion = textExpanderConfig.expansionMap[plainText];

if (shouldFormatAsWikiLink(plainText)) {

// Format as wiki link

return '' + expansion + '';

} else {

// Just replace with the expansion

return expansion;

}

} else if (bracketedText) {

// This is already in brackets

if (match.indexOf('|') > -1) {

// Already has a pipe, don't modify

return match;

} else {

// Add the expansion

var expansion = textExpanderConfig.expansionMap[bracketedText];

return '' + expansion + '';

}

}

return match;

});

// Replace the selected text with the expanded text

if (expandedCount > 0) {

activeElement.value =

activeElement.value.substring(0, selStart) +

newContent +

activeElement.value.substring(selEnd);

// Position cursor after the expansion

activeElement.setSelectionRange(selStart + newContent.length, selStart + newContent.length);

return expandedCount;

}

}

}

}

// If we get here, no expansion happened

if (selectedText && expandedCount === 0) {

mw.notify('No expandable text found in the selection', {type: 'info'});

} else if (!selectedText) {

mw.notify('Please select text to expand', {type: 'info'});

}

return 0;

}

// Add keydown event listener for the hotkey

$(document).on('keydown', function(e) {

var config = textExpanderConfig.hotkey;

if (

e.ctrlKey === config.ctrlKey &&

e.shiftKey === config.shiftKey &&

e.altKey === config.altKey &&

e.key.toLowerCase() === config.key.toLowerCase()

) {

var expandedCount = expandAllText();

if (expandedCount > 0) {

e.preventDefault();

mw.notify('Expanded ' + expandedCount + ' item' + (expandedCount > 1 ? 's' : ''), {type: 'success'});

}

}

});

// Create the settings dialog

function createSettingsDialog() {

var $dialog = $('

')

.attr('id', 'text-settings-dialog')

.attr('title', 'WikiTextExpander Settings')

.css({

'display': 'none'

});

// Create the dialog content

var $content = $('

');

// Create tabs

var $tabs = $('

').addClass('mw-widget-aeTabs');

var $tabList = $('