Jump to content

User:Polygnotus/Scripts/VEinsertandparse.js

From Wikipedia, the free encyclopedia
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.
// 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');
  }
}