![]() |
VOOZH | about |
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 key and click the Reload toolbar button.
For details and instructions about other browsers, see Wikipedia:Bypass your cache.
constwikis=Object.freeze(require('./global.json').wikis); constwikiList=Object.freeze(Object.values(wikis)); functionlocalization(i18nData){ consti18n={}; mw.language.getFallbackLanguageChain().forEach(function(lang){ if(!i18nData.hasOwnProperty(lang))return; getAllKeys(i18nData[lang],i18n); }); returni18n; } functiongetAllKeys(data,target){ Object.keys(data).forEach(function(key){ if(!data.hasOwnProperty(key))return; if(target.hasOwnProperty(key)){ if(typeoftarget[key]==='object'&&!Array.isArray(target[key])&&target[key]!==null &&typeofdata[key]==='object'&&!Array.isArray(data[key])&&data[key]!==null){ getAllKeys(data[key],target[key]); } return; } target[key]=structuredClone(data[key]); }); } classMessageParser{ constructor(i18nData,resolved){ this.map=newmw.Map(); if(resolved)this.map.set(i18nData); elsethis.map.set(localization(i18nData)); } message(key,...parameters){ returnnewmw.Message(this.map,key,parameters); } msg(key,...parameters){ returnthis.message(key,...parameters).text(); } } if(mw.config.get('skin')==='vector'){ // Modified from https://github.com/wikimedia/mediawiki/blob/744bc53c355b1f73b522d7b3401f83ec90b08cb2/resources/src/mediawiki.util/util.js#L566-L641 // and https://github.com/wikimedia/mediawiki-skins-Vector/blob/e564247dfa861180ab741079efdde54ad3bde413/resources/skins.vector.legacy.js/portlets.js /** * Creates a detached portlet Element in the skin with no elements. * * @example * // Create a portlet with 2 menu items that is styled as a dropdown in certain skins. * mw.util.addPortlet( 'p-myportlet', 'My label', '#p-cactions' ); * mw.util.addPortletLink( 'p-myportlet', '#', 'Link 1' ); * mw.util.addPortletLink( 'p-myportlet', '#', 'Link 2' ); * * @param {string} id ID of the new portlet. * @param {string} [label] Label of the new portlet. * @param {string} [selectorHint] Selector of the element the new portlet would like to * be inserted near. Typically the portlet will be inserted after this selector, but in some * skins, the skin may relocate the element to another available space. * * When provided, skins can use the parameter to infer information about how the user intended * the menu to be rendered. For example, in vector and vector-2022 targeting `#p-cactions` will * result in the creation of a dropdown menu. * * If this argument is not passed, then the caller is responsible for appending the element * to the DOM before using addPortletLink. * * To add a portlet in an exact position do not rely on this parameter, instead assign the returned * element to a variable, and use `yourTarget.appendChild( portlet );` * @fires Hooks~'util.addPortlet' * @return {HTMLElement|null} will be null if it was not possible to create an portlet with * the required information e.g. the selector given in `selectorHint` parameter could not be resolved * to an existing element in the page. */ mw.util.addPortlet=function(id,label,selectorHint){ constportlet=document.createElement('nav'); // These classes should be kept in sync with includes/skins/components/SkinComponentMenu.php. // eslint-disable-next-line mediawiki/class-doc portlet.classList.add('mw-portlet','mw-portlet-'+id.replace(/^p-/,''),'emptyPortlet','vector-menu', // Additional class is added to allow skins to track portlets added via this mechanism. 'mw-portlet-js' ); portlet.id=id; if(label){ constlabelId=id+'-label'; constlabelNode=document.createElement('h3'); labelNode.id=labelId; labelNode.classList.add('vector-menu-heading'); constlabelSpan=document.createElement('span'); labelSpan.classList.add('vector-menu-heading-label'); labelSpan.textContent=label; labelNode.appendChild(labelSpan); portlet.appendChild(labelNode); portlet.setAttribute('aria-labelledby',labelId); portlet.setAttribute('role','navigation'); } constlistWrapper=document.createElement('div'); listWrapper.classList.add('vector-menu-content'); constlist=document.createElement('ul'); list.classList.add('vector-menu-content-list'); listWrapper.appendChild(list); portlet.appendChild(listWrapper); if(selectorHint){ letreferenceNode; try{ referenceNode=document.querySelector(selectorHint); }catch(e){ // CSS selector not supported by browser. } if(referenceNode){ referenceNode.after(portlet); }else{ returnnull; } } if(portlet.closest('.vector-legacy-sidebar')){ portlet.classList.add('vector-menu-portal'); } /** * Fires when a portlet is successfully created. * * @event ~'util.addPortlet' * @memberof Hooks * @param {HTMLElement} portlet the portlet that was created. * @param {string|null} selectorHint the css selector used to append to the DOM. * * @example * mw.hook( 'util.addPortlet' ).add( ( p ) => { * p.style.border = 'solid 1px black'; * } ); */ mw.hook('util.addPortlet').fire(portlet,selectorHint); returnportlet; }; } module.exports={ wikis, wikiList, localization, MessageParser };