Jump to content
Wikipedia The Free Encyclopedia

User:Polygnotus/Scripts/WikiBlame3.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.
Documentation for this user script can be added at User:Polygnotus/Scripts/WikiBlame3.
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.
 (function(){
 'use strict';

 // Only run in mainspace
 if(!mw.config.get('wgIsArticle')){
 return;
 }

 constDEFAULT_HOTKEY='ctrl+shift+w';
 letcurrentHotkeyBinding=null;

 // Storage functions
 functiongetStoredHotkey(){
 try{
 returnlocalStorage.getItem('wikiblame-hotkey')||DEFAULT_HOTKEY;
 }catch(e){
 returnDEFAULT_HOTKEY;
 }
 }

 functionstoreHotkey(hotkey){
 try{
 localStorage.setItem('wikiblame-hotkey',hotkey);
 }catch(e){
 console.warn('Could not store hotkey:',e);
 }
 }

 // WikiBlame search function
 functionperformWikiBlameSearch(){
 constselectedText=window.getSelection().toString().trim();

 if(!selectedText){
 alert('Please select text first, then use WikiBlame search.');
 return;
 }

 constlang=mw.config.get('wgContentLanguage');
 constarticleTitle=mw.config.get('wgPageName');
 constencodedNeedle=encodeURIComponent(selectedText);

 constwikiblameUrl=`https://wikipedia.ramselehof.de/wikiblame.php?user_lang=${lang}&lang=${lang}&project=wikipedia&tld=org&article=${articleTitle}&needle=${encodedNeedle}`;

 window.open(wikiblameUrl,'_blank');
 }

 // Load Mousetrap library
 functionloadMousetrap(){
 returnnewPromise((resolve,reject)=>{
 if(window.Mousetrap){
 resolve();
 return;
 }

 constscript=document.createElement('script');
 script.src='https://cdnjs.cloudflare.com/ajax/libs/mousetrap/1.6.5/mousetrap.min.js';
 script.onload=()=>{
 if(window.Mousetrap){
 resolve();
 }else{
 reject(newError('Mousetrap failed to load'));
 }
 };
 script.onerror=()=>reject(newError('Failed to load Mousetrap'));
 document.head.appendChild(script);
 });
 }

 // Register hotkey with Mousetrap
 functionregisterHotkey(hotkey){
 if(!window.Mousetrap)return;

 // Unbind previous hotkey
 if(currentHotkeyBinding){
 window.Mousetrap.unbind(currentHotkeyBinding);
 }

 try{
 // Ensure we're working with a clean string format
 constcleanHotkey=typeofhotkey==='string'?hotkey:hotkey.toString();

 // Normalize the hotkey format for Mousetrap
 constnormalizedHotkey=cleanHotkey.toLowerCase()
 .replace(/\s+/g,'')// Remove spaces
 .replace(/\+/g,'+')
 .replace(/ctrl/g,'ctrl')
 .replace(/alt/g,'alt')
 .replace(/shift/g,'shift')
 .replace(/meta/g,'meta');

 window.Mousetrap.bind(normalizedHotkey,function(e){
 // Prevent default browser behavior
 if(e.preventDefault){
 e.preventDefault();
 }else{
 e.returnValue=false;
 }

 performWikiBlameSearch();
 returnfalse;
 });

 currentHotkeyBinding=normalizedHotkey;
 console.log('WikiBlame hotkey registered:',normalizedHotkey);
 }catch(e){
 console.error('Failed to register hotkey:',hotkey,e);
 throwe;
 }
 }

 // Validate hotkey format
 functionisValidHotkey(hotkey){
 // Basic validation for Mousetrap format
 constvalidPattern=/^(ctrl\+|alt\+|shift\+|meta\+)*[a-z0-9]$/i;
 constnormalizedHotkey=hotkey.toLowerCase().replace(/\s+/g,'');

 // Don't allow problematic combinations
 constproblematicKeys=['f12','ctrl+shift+i','ctrl+u','ctrl+r','ctrl+f','ctrl+s','ctrl+p'];
 if(problematicKeys.includes(normalizedHotkey)){
 returnfalse;
 }

 returnvalidPattern.test(normalizedHotkey)||/^[f][1-9]$|^[f][1][0-2]$/.test(normalizedHotkey);
 }

 // Create configuration popup
 functionshowConfigPopup(){
 // Remove existing popup if any
 constexistingPopup=document.getElementById('wikiblame-config-popup');
 if(existingPopup){
 existingPopup.remove();
 }

 constoverlay=document.createElement('div');
 overlay.id='wikiblame-config-popup';
 overlay.innerHTML=`
  <div class="wikiblame-overlay"></div>
  <div class="wikiblame-popup">
  <h3>Configure WikiBlame Hotkey</h3>
  <p>Current hotkey: <strong>${getStoredHotkey()}</strong></p>
  <div class="form-group">
  <label for="hotkey-input">New Hotkey:</label>
  <input type="text" id="hotkey-input" placeholder="e.g., ctrl+shift+w" value="${getStoredHotkey()}">
  <div class="help-text">
  Examples: ctrl+shift+w, alt+b, ctrl+alt+w, shift+f1<br>
  <strong>Avoid:</strong> F12, Ctrl+Shift+I, Ctrl+U, Ctrl+R, Ctrl+F, Ctrl+S, Ctrl+P
  </div>
  </div>
  <div class="button-group">
  <button id="hotkey-cancel">Cancel</button>
  <button id="hotkey-save">Save</button>
  </div>
  </div>
  `;

 // Add styles
 conststyle=document.createElement('style');
 style.textContent=`
  #wikiblame-config-popup {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10000;
  }
  .wikiblame-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  }
  .wikiblame-popup {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  border: 2px solid #a2a9b1;
  border-radius: 8px;
  padding: 20px;
  min-width: 400px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
  }
  .wikiblame-popup h3 {
  margin: 0 0 15px 0;
  color: #000;
  font-size: 16px;
  }
  .wikiblame-popup p {
  margin: 0 0 15px 0;
  color: #54595d;
  }
  .form-group {
  margin-bottom: 20px;
  }
  .form-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
  color: #000;
  }
  .form-group input {
  width: 100%;
  padding: 8px;
  border: 1px solid #a2a9b1;
  border-radius: 4px;
  box-sizing: border-box;
  font-size: 14px;
  }
  .help-text {
  font-size: 12px;
  color: #72777d;
  margin-top: 5px;
  line-height: 1.4;
  }
  .button-group {
  text-align: right;
  }
  .button-group button {
  margin-left: 10px;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  }
  #hotkey-cancel {
  border: 1px solid #a2a9b1;
  background: white;
  color: #000;
  }
  #hotkey-save {
  border: none;
  background: #0645ad;
  color: white;
  }
  #hotkey-cancel:hover {
  background: #f8f9fa;
  }
  #hotkey-save:hover {
  background: #0b57d0;
  }
  `;

 document.head.appendChild(style);
 document.body.appendChild(overlay);

 constinput=document.getElementById('hotkey-input');
 constsaveBtn=document.getElementById('hotkey-save');
 constcancelBtn=document.getElementById('hotkey-cancel');
 constoverlayEl=document.querySelector('.wikiblame-overlay');

 input.focus();
 input.select();

 functionclosePopup(){
 constpopup=document.getElementById('wikiblame-config-popup');
 if(popup)popup.remove();
 if(style.parentNode)style.parentNode.removeChild(style);
 }

 functionsaveHotkey(){
 constnewHotkey=input.value.trim().toLowerCase();
 if(!newHotkey){
 alert('Please enter a hotkey combination.');
 return;
 }

 if(!isValidHotkey(newHotkey)){
 alert('Invalid hotkey format or conflicts with browser shortcuts.\nUse format like "ctrl+shift+w" and avoid F12, Ctrl+Shift+I, etc.');
 return;
 }

 try{
 registerHotkey(newHotkey);
 storeHotkey(newHotkey);

 // Update tooltip
 consttoolsLink=document.getElementById('t-wikiblame');
 if(toolsLink){
 toolsLink.title=`Find the edit that added the selected text (${newHotkey})`;
 }

 alert(`Hotkey updated to: ${newHotkey}`);
 closePopup();
 }catch(e){
 alert('Failed to register hotkey. Please try a different combination.');
 }
 }

 saveBtn.addEventListener('click',saveHotkey);
 cancelBtn.addEventListener('click',closePopup);
 overlayEl.addEventListener('click',closePopup);

 input.addEventListener('keydown',(e)=>{
 if(e.key==='Enter'){
 saveHotkey();
 }elseif(e.key==='Escape'){
 closePopup();
 }
 });
 }

 // Initialize
 mw.loader.using(['mediawiki.util']).then(()=>{
 conststoredHotkey=getStoredHotkey();

 // Add tools menu link
 consttoolsLink=mw.util.addPortletLink(
 'p-tb',
 '#',
 'WikiBlame search',
 't-wikiblame',
 `Find the edit that added the selected text (${storedHotkey})`
 );

 if(toolsLink){
 toolsLink.addEventListener('click',(e)=>{
 e.preventDefault();
 performWikiBlameSearch();
 });
 }

 // Add configuration link to More menu
 constconfigLink=mw.util.addPortletLink(
 'p-cactions',
 '#',
 'WikiBlame Settings',
 't-wikiblame-config',
 'Configure WikiBlame hotkey'
 );

 if(configLink){
 configLink.addEventListener('click',(e)=>{
 e.preventDefault();
 showConfigPopup();
 });
 }

 // Load Mousetrap library and register hotkey
 loadMousetrap()
 .then(()=>{
 registerHotkey(storedHotkey);
 })
 .catch((error)=>{
 console.warn('WikiBlame: Could not load Mousetrap library:',error);
 });
 });
 })();

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