User:Polygnotus/Scripts/VEinsertandparse.js
Appearance
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. |
![]() | Documentation for this user script can be added at User:Polygnotus/Scripts/VEinsertandparse. |
// Add a custom reference button to Wikipedia's Visual Editor that inserts a pre-formatted source citation
// Add this code to your common.js page on Wikipedia
// (e.g., https://en.wikipedia.org/wiki/User:YourUsername/common.js)
// Wait for the VisualEditor to be ready
mw.loader.using(['ext.visualEditor.desktopArticleTarget']).then(function() {
// Register our custom reference tool with VisualEditor
mw.hook('ve.loadModules').add(function(addPlugin) {
addPlugin(makeRefTool);
});
// Also add the button when the editor is activated
mw.hook('ve.activationComplete').add(function() {
console.log('VE activation hook fired');
// Wait a bit for the toolbar to fully initialize
setTimeout(function() {
addRefButton();
}, 1000);
// Also add the button when the surface is ready
if (typeof ve !== 'undefined' && ve.init && ve.init.target) {
ve.init.target.on('surfaceReady', function() {
console.log('Surface ready event fired');
addRefButton();
});
}
});
});
// Function to create and register the reference command and tool
function makeRefTool() {
// Create a reference with the source template
// Using Parsoid-style structure to ensure proper template parsing
var refContent = [{
type: 'mwReference',
attributes: {
mw: {
name: 'ref-' + Math.random().toString(36).substring(2, 8), // Generate a unique ID
body: {
id: 'body-' + Math.random().toString(36).substring(2, 8), // Generate a unique ID
type: 'mwReferenceContents',
// This is the key part - using proper Parsoid structure for the template
html: '<span typeof="mw:Transclusion" data-mw=\'{"parts":[{"template":{"target":{"wt":"source","href":"./Template:Source"},"params":{"url":{"wt":"https://www.atlantanewsfirst.com/2025/04/07/questions-remain-after-dead-horse-found-downtown-atlanta/"},"title":{"wt":"Questions remain after dead horse found in downtown Atlanta"},"author":{"wt":"Adam Murphy"},"date":{"wt":"April 7, 2025"},"pub":{"wt":"Atlanta News First"}},"i":0}}]}\'></span>'
}
}
}
}];
// Register the command with VisualEditor
ve.ui.commandRegistry.register(
new ve.ui.Command('myrefcommand', 'content', 'insert', {
args: [refContent, false, true],
supportedSelections: ['linear']
})
);
// Create and register tool
function RefTool() {
RefTool.parent.apply(this, arguments);
}
OO.inheritClass(RefTool, ve.ui.Tool);
RefTool.static.name = 'reftool';
RefTool.static.group = 'insert';
RefTool.static.title = 'Insert Atlanta News Reference';
RefTool.static.commandName = 'myrefcommand';
RefTool.static.icon = 'reference'; // Using built-in reference icon
ve.ui.toolFactory.register(RefTool);
}
// Function to manually add the reference button to the toolbar
function addRefButton() {
console.log('Attempting to add Reference button');
// Check if our button already exists to avoid duplicates
if ($('.oo-ui-tool-name-customRefTool').length) {
console.log('Reference button already exists');
return;
}
// Create a proper new group for our button
var $toolGroup = $('<div>')
.addClass('ve-ui-toolbar-group-reference oo-ui-widget oo-ui-toolGroup oo-ui-barToolGroup oo-ui-widget-enabled')
.attr('title', 'Reference Tools');
var $toolsContainer = $('<div>')
.addClass('oo-ui-toolGroup-tools oo-ui-barToolGroup-tools oo-ui-toolGroup-enabled-tools')
.appendTo($toolGroup);
// Create the button itself matching other buttons' structure
var $button = $('<span>')
.addClass('oo-ui-widget oo-ui-iconElement oo-ui-tool-with-icon oo-ui-tool oo-ui-tool-name-customRefTool oo-ui-widget-enabled')
.appendTo($toolsContainer);
// Create the link element
var $link = $('<a>')
.addClass('oo-ui-tool-link')
.attr('role', 'button')
.attr('tabindex', '0')
.attr('title', 'Insert Atlanta News Reference')
.appendTo($button);
// Add the icon structure
$('<span>')
.addClass('oo-ui-tool-checkIcon oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement oo-ui-iconElement-icon oo-ui-icon-check oo-ui-labelElement-invisible oo-ui-iconWidget')
.appendTo($link);
$('<span>')
.addClass('oo-ui-iconElement-icon oo-ui-icon-reference')
.appendTo($link);
$('<span>')
.addClass('oo-ui-tool-title')
.text('Atlanta Ref')
.appendTo($link);
// Add click event to insert the reference at cursor position
$button.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
// Get the current visual editor surface
var surface = ve.init.target.getSurface();
// Create reference content with the template using Parsoid structure
var refContent = [{
type: 'mwReference',
attributes: {
mw: {
name: 'ref-' + Math.random().toString(36).substring(2, 8),
body: {
id: 'body-' + Math.random().toString(36).substring(2, 8),
type: 'mwReferenceContents',
// Using proper Parsoid structure for the template
html: '<span typeof="mw:Transclusion" data-mw=\'{"parts":[{"template":{"target":{"wt":"source","href":"./Template:Source"},"params":{"url":{"wt":"https://www.atlantanewsfirst.com/2025/04/07/questions-remain-after-dead-horse-found-downtown-atlanta/"},"title":{"wt":"Questions remain after dead horse found in downtown Atlanta"},"author":{"wt":"Adam Murphy"},"date":{"wt":"April 7, 2025"},"pub":{"wt":"Atlanta News First"}},"i":0}}]}\'></span>'
}
}
}
}];
// Insert the reference at the cursor position
var fragment = surface.getModel().getFragment();
fragment.insertContent(refContent, true);
// Optionally, you can add a notification to confirm the reference was added
if (ve.init.target.showNotifications) {
ve.init.target.showNotifications([
{ type: 'success', message: 'Atlanta News reference added' }
]);
}
});
// Insert our group at an appropriate location in the toolbar
// Find the cite or insert group to add after
var $insertPosition = $('.ve-ui-toolbar-group-cite, .ve-ui-toolbar-group-insert').last();
if ($insertPosition.length) {
$toolGroup.insertAfter($insertPosition);
console.log('Reference button added successfully after', $insertPosition.attr('class'));
} else {
// Fallback: add to main toolbar
$('.oo-ui-toolbar-tools').first().append($toolGroup);
console.log('Reference button added to main toolbar');
}
}