Jump to content
Wikipedia The Free Encyclopedia

User:Polygnotus/Scripts/WikiTextExpander.js

From Wikipedia, the free encyclopedia
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Polygnotus/Scripts/WikiTextExpander.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
 // 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 [[WP:COI|the conflict of interest guideline]]
 // - Regular phrases are expanded without wiki links

 // Default configuration
 vartextExpanderConfig={
 // 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{
 varsavedConfig=localStorage.getItem('textExpanderConfig');
 if(savedConfig){
 varparsedConfig=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
 functionsaveTextExpanderConfig(){
 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
 functiongetExpansionRegex(){
 varescapedKeys=Object.keys(textExpanderConfig.expansionMap).map(function(key){
 returnkey.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');// Escape special characters
 });

 // Pattern to match both plain text and those inside wiki brackets
 returnnewRegExp(
 '(?<!\\[)\\b('+escapedKeys.join('|')+')\\b(?!\\])'+'|'+
 '\\[\\[('+escapedKeys.join('|')+')(?:\\|[^\\]]*?)?\\]\\]',
 'g'
 );
 }

 // Function to determine if a key should be formatted as a wiki link
 functionshouldFormatAsWikiLink(key){
 returnkey.indexOf(':')>-1;
 }

 // Function to expand all text in the selected text
 functionexpandAllText(){
 // Get the active editor input element
 varactiveElement=document.activeElement;

 // Check if we're in an editable field
 if(activeElement&&(
 activeElement.isContentEditable||
 activeElement.tagName==='TEXTAREA'||
 (activeElement.tagName==='INPUT'&&activeElement.type==='text')
 )){
 varselectedText='';
 varexpandedCount=0;

 // Handle different editor types
 if(activeElement.isContentEditable){
 // Visual editor
 varselection=window.getSelection();
 if(selection.rangeCount>0){
 varrange=selection.getRangeAt(0);
 selectedText=selection.toString();

 // Only proceed if there's selected text
 if(selectedText){
 // Create a document fragment for the new content
 varnewContent=selectedText;
 varexpansionRegex=getExpansionRegex();

 // Replace all expandable text in the selected text
 newContent=newContent.replace(expansionRegex,function(match,plainText,bracketedText){
 expandedCount++;

 if(plainText){
 // This is plain text
 varexpansion=textExpanderConfig.expansionMap[plainText];
 if(shouldFormatAsWikiLink(plainText)){
 // Format as wiki link
 return'[['+plainText+'|'+expansion+']]';
 }else{
 // Just replace with the expansion
 returnexpansion;
 }
 }elseif(bracketedText){
 // This is already in brackets
 if(match.indexOf('|')>-1){
 // Already has a pipe, don't modify
 returnmatch;
 }else{
 // Add the expansion
 varexpansion=textExpanderConfig.expansionMap[bracketedText];
 return'[['+bracketedText+'|'+expansion+']]';
 }
 }
 returnmatch;
 });

 // Replace the selected text with the expanded text
 if(expandedCount>0){
 document.execCommand('insertText',false,newContent);
 returnexpandedCount;
 }
 }
 }
 }else{
 // Source editor (textarea or input)
 varselStart=activeElement.selectionStart;
 varselEnd=activeElement.selectionEnd;
 selectedText=activeElement.value.substring(selStart,selEnd);

 // Only proceed if there's selected text
 if(selectedText){
 varexpansionRegex=getExpansionRegex();

 // Replace all expandable text in the selected text
 varnewContent=selectedText.replace(expansionRegex,function(match,plainText,bracketedText){
 expandedCount++;

 if(plainText){
 // This is plain text
 varexpansion=textExpanderConfig.expansionMap[plainText];
 if(shouldFormatAsWikiLink(plainText)){
 // Format as wiki link
 return'[['+plainText+'|'+expansion+']]';
 }else{
 // Just replace with the expansion
 returnexpansion;
 }
 }elseif(bracketedText){
 // This is already in brackets
 if(match.indexOf('|')>-1){
 // Already has a pipe, don't modify
 returnmatch;
 }else{
 // Add the expansion
 varexpansion=textExpanderConfig.expansionMap[bracketedText];
 return'[['+bracketedText+'|'+expansion+']]';
 }
 }
 returnmatch;
 });

 // 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);
 returnexpandedCount;
 }
 }
 }
 }

 // If we get here, no expansion happened
 if(selectedText&&expandedCount===0){
 mw.notify('No expandable text found in the selection',{type:'info'});
 }elseif(!selectedText){
 mw.notify('Please select text to expand',{type:'info'});
 }

 return0;
 }

 // Add keydown event listener for the hotkey
 $(document).on('keydown',function(e){
 varconfig=textExpanderConfig.hotkey;

 if(
 e.ctrlKey===config.ctrlKey&&
 e.shiftKey===config.shiftKey&&
 e.altKey===config.altKey&&
 e.key.toLowerCase()===config.key.toLowerCase()
 ){
 varexpandedCount=expandAllText();
 if(expandedCount>0){
 e.preventDefault();
 mw.notify('Expanded '+expandedCount+' item'+(expandedCount>1?'s':''),{type:'success'});
 }
 }
 });

 // Create the settings dialog
 functioncreateSettingsDialog(){
 var$dialog=$('<div>')
 .attr('id','text-settings-dialog')
 .attr('title','WikiTextExpander Settings')
 .css({
 'display':'none'
 });

 // Create the dialog content
 var$content=$('<div>');

 // Create tabs
 var$tabs=$('<div>').addClass('mw-widget-aeTabs');
 var$tabList=$('<ul>');

 $tabList.append($('<li>').append($('<a>').attr('href','#expansion-tab').text('Expansions')));
 $tabList.append($('<li>').append($('<a>').attr('href','#hotkey-tab').text('Hotkey')));
 $tabs.append($tabList);

 // Expansions tab
 var$expansionTab=$('<div>').attr('id','expansion-tab');

 $expansionTab.append($('<p>').text('Edit your shorthand text and their expansions:'));

 var$expansionTable=$('<table>').addClass('wikitable').css('width','100%');

 // Table header
 var$tableHeader=$('<tr>');
 $tableHeader.append($('<th>').text('Shorthand'));
 $tableHeader.append($('<th>').text('Expansion'));
 $tableHeader.append($('<th>').text('Type'));
 $tableHeader.append($('<th>').text('Actions'));
 $expansionTable.append($tableHeader);

 // Add rows for each expansion
 $.each(textExpanderConfig.expansionMap,function(key,expansion){
 addExpansionRow($expansionTable,key,expansion);
 });

 // Add new row button
 var$addButton=$('<button>')
 .text('Add New Expansion')
 .click(function(){
 addExpansionRow($expansionTable,'','');
 });

 // Import/Export area
 var$importExportArea=$('<div>').css('margin-top','15px');

 var$exportButton=$('<button>')
 .text('Export to JSON')
 .css('margin-right','10px')
 .click(function(){
 varcurrentMap={};
 $expansionTable.find('tr').each(function(index){
 if(index===0)return;// Skip header row

 var$row=$(this);
 varkey=$row.find('input.shorthand').val();
 varexpansion=$row.find('input.expansion').val();

 if(key&&expansion){
 currentMap[key]=expansion;
 }
 });

 varjsonData=JSON.stringify(currentMap,null,2);
 var$textarea=$('<textarea>')
 .val(jsonData)
 .css({
 'width':'100%',
 'height':'100px',
 'margin-top':'10px',
 'font-family':'monospace'
 });

 $importExportArea.find('textarea').remove();
 $importExportArea.append($textarea);
 $textarea.select();
 });

 var$importButton=$('<button>')
 .text('Import from JSON')
 .click(function(){
 var$textarea=$('<textarea>')
 .css({
 'width':'100%',
 'height':'100px',
 'margin-top':'10px',
 'font-family':'monospace'
 })
 .attr('placeholder','{"WP:ABC": "example expansion", "thanks": "Thank you for your contribution"}');

 var$importConfirm=$('<button>')
 .text('Process Import')
 .css('margin-top','5px')
 .click(function(){
 try{
 varimportedData=JSON.parse($textarea.val());

 // Clear existing rows (except header)
 $expansionTable.find('tr:gt(0)').remove();

 // Add new rows
 $.each(importedData,function(key,expansion){
 addExpansionRow($expansionTable,key,expansion);
 });

 // Remove the import UI
 $textarea.remove();
 $importConfirm.remove();

 mw.notify('Expansions imported successfully',{type:'success'});
 }catch(e){
 mw.notify('Error parsing JSON: '+e.message,{type:'error'});
 }
 });

 $importExportArea.find('textarea, button:not(:first-child)').remove();
 $importExportArea.append($textarea);
 $importExportArea.append($importConfirm);
 });

 $importExportArea.append($exportButton);
 $importExportArea.append($importButton);

 $expansionTab.append($expansionTable);
 $expansionTab.append($('<div>').css('margin-top','10px').append($addButton));
 $expansionTab.append($importExportArea);

 // Hotkey tab
 var$hotkeyTab=$('<div>').attr('id','hotkey-tab');

 $hotkeyTab.append($('<p>').text('Configure the hotkey for expanding text:'));

 var$hotkeyForm=$('<div>').addClass('mw-widget-aeInputs');

 // Checkboxes for modifier keys
 var$modifiers=$('<div>').css('margin-bottom','10px');

 var$ctrlLabel=$('<label>').css('margin-right','10px');
 var$ctrlCheck=$('<input>').attr('type','checkbox').prop('checked',textExpanderConfig.hotkey.ctrlKey);
 $ctrlLabel.append($ctrlCheck).append(' Ctrl');

 var$shiftLabel=$('<label>').css('margin-right','10px');
 var$shiftCheck=$('<input>').attr('type','checkbox').prop('checked',textExpanderConfig.hotkey.shiftKey);
 $shiftLabel.append($shiftCheck).append(' Shift');

 var$altLabel=$('<label>').css('margin-right','10px');
 var$altCheck=$('<input>').attr('type','checkbox').prop('checked',textExpanderConfig.hotkey.altKey);
 $altLabel.append($altCheck).append(' Alt');

 $modifiers.append($ctrlLabel).append($shiftLabel).append($altLabel);

 // Key input
 var$keyLabel=$('<label>').css('display','block').css('margin-bottom','5px').text('Key:');
 var$keyInput=$('<input>')
 .attr('type','text')
 .css('width','50px')
 .val(textExpanderConfig.hotkey.key)
 .on('keydown',function(e){
 e.preventDefault();
 $(this).val(e.key.toLowerCase());
 });

 $hotkeyForm.append($modifiers);
 $hotkeyForm.append($keyLabel);
 $hotkeyForm.append($keyInput);

 // Current hotkey display
 var$currentHotkey=$('<div>').css('margin-top','15px');
 functionupdateCurrentHotkey(){
 varhotkeyText=[];
 if($ctrlCheck.prop('checked'))hotkeyText.push('Ctrl');
 if($shiftCheck.prop('checked'))hotkeyText.push('Shift');
 if($altCheck.prop('checked'))hotkeyText.push('Alt');
 hotkeyText.push($keyInput.val().toUpperCase());

 $currentHotkey.html('<strong>Current Hotkey:</strong> '+hotkeyText.join('+'));
 }

 // Update on any change
 $ctrlCheck.on('change',updateCurrentHotkey);
 $shiftCheck.on('change',updateCurrentHotkey);
 $altCheck.on('change',updateCurrentHotkey);
 $keyInput.on('input',updateCurrentHotkey);
 updateCurrentHotkey();// Initial update

 $hotkeyTab.append($hotkeyForm);
 $hotkeyTab.append($currentHotkey);

 // Add the tabs to the content
 $tabs.append($expansionTab);
 $tabs.append($hotkeyTab);
 $content.append($tabs);

 // Save button
 var$saveButton=$('<button>')
 .text('Save Settings')
 .css('margin-top','15px')
 .click(function(){
 // Save expansions
 varnewExpansionMap={};
 $expansionTable.find('tr').each(function(index){
 if(index===0)return;// Skip header row

 var$row=$(this);
 varkey=$row.find('input.shorthand').val();
 varexpansion=$row.find('input.expansion').val();

 if(key&&expansion){
 newExpansionMap[key]=expansion;
 }
 });

 // Save hotkey configuration
 varnewHotkey={
 ctrlKey:$ctrlCheck.prop('checked'),
 shiftKey:$shiftCheck.prop('checked'),
 altKey:$altCheck.prop('checked'),
 key:$keyInput.val().toLowerCase()
 };

 // Update the configuration
 textExpanderConfig.expansionMap=newExpansionMap;
 textExpanderConfig.hotkey=newHotkey;

 // Save to localStorage
 saveTextExpanderConfig();

 // Close the dialog
 $dialog.dialog('close');

 // Notify the user
 mw.notify('WikiTextExpander settings saved',{type:'success'});
 });

 $content.append($saveButton);

 // Append the content to the dialog
 $dialog.append($content);

 // Add to the body and initialize as a jQuery UI dialog
 $('body').append($dialog);

 $dialog.dialog({
 autoOpen:false,
 width:600,
 height:500,
 modal:true,
 title:'WikiTextExpander settings',
 close:function(){
 // Cleanup the dialog on close
 $(this).dialog('destroy');
 $(this).remove();
 }
 });

 // Initialize tabs
 $tabs.tabs();

 return$dialog;
 }

 // Function to add a row to the expansions table
 functionaddExpansionRow($table,key,expansion){
 var$row=$('<tr>');

 var$keyCell=$('<td>');
 var$keyInput=$('<input>')
 .addClass('shorthand')
 .attr('type','text')
 .val(key)
 .css('width','100%');
 $keyCell.append($keyInput);

 var$expansionCell=$('<td>');
 var$expansionInput=$('<input>')
 .addClass('expansion')
 .attr('type','text')
 .val(expansion)
 .css('width','100%');
 $expansionCell.append($expansionInput);

 var$typeCell=$('<td>').css('text-align','center');
 vartypeText=shouldFormatAsWikiLink(key)?'Wiki Link':'Plain Text';
 $typeCell.text(typeText);

 // Update type display when key changes
 $keyInput.on('input',function(){
 varnewKey=$(this).val();
 varnewType=shouldFormatAsWikiLink(newKey)?'Wiki Link':'Plain Text';
 $typeCell.text(newType);
 });

 var$actionsCell=$('<td>').css('text-align','center');
 var$deleteButton=$('<button>')
 .text('Delete')
 .click(function(){
 $(this).closest('tr').remove();
 });
 $actionsCell.append($deleteButton);

 $row.append($keyCell);
 $row.append($expansionCell);
 $row.append($typeCell);
 $row.append($actionsCell);

 $table.append($row);
 }

 // Add the settings item to the "More" menu
 mw.hook('wikipage.content').add(function(){
 // For the modern Vector skin and other skins with a "More" menu
 if($('#p-cactions').length){
 // Make sure we don't add it twice
 if(!$('#ca-text-expander').length){
 var$moreList=$('#p-cactions ul');

 var$settingsItem=$('<li>')
 .attr('id','ca-text-expander')
 .addClass('mw-list-item mw-list-item-js')
 .append(
 $('<a>')
 .attr('href','#')
 .text('WikiTextExpander settings')
 .click(function(e){
 e.preventDefault();
 createSettingsDialog().dialog('open');
 })
 );

 $moreList.append($settingsItem);
 }
 }
 });

 // Add a notification about the hotkey when in edit mode
 mw.hook('ve.activationComplete').add(function(){
 // For Visual Editor
 varhotkeyText=[];
 varconfig=textExpanderConfig.hotkey;
 if(config.ctrlKey)hotkeyText.push('Ctrl');
 if(config.shiftKey)hotkeyText.push('Shift');
 if(config.altKey)hotkeyText.push('Alt');
 hotkeyText.push(config.key.toUpperCase());

 //mw.notify('Text Expander activated. Use ' + hotkeyText.join('+') + ' to expand selected text.', {type: 'info'});
 });

 // Also show notification in wikitext editor
 $(document).ready(function(){
 if(mw.config.get('wgAction')==='edit'||mw.config.get('wgAction')==='submit'){
 varhotkeyText=[];
 varconfig=textExpanderConfig.hotkey;
 if(config.ctrlKey)hotkeyText.push('Ctrl');
 if(config.shiftKey)hotkeyText.push('Shift');
 if(config.altKey)hotkeyText.push('Alt');
 hotkeyText.push(config.key.toUpperCase());

 //mw.notify('Text Expander activated. Use ' + hotkeyText.join('+') + ' to expand selected text.', {type: 'info'});
 }
 });

AltStyle によって変換されたページ (->オリジナル) /