User:C.Ezra.M/staffhl.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/** * A script to highlight staff members' usernames. * This only does the job of applying attributes, there are no enforced colors. * This is for a11y purposes, but most importantly, to crack down on use of `!important`. * * @author C.Ezra.M */ /** Settings for this script */ window.staffhlSettings = { /** * If `true`, `fetch()` is used. If `false`, `mw.Api` is used instead. */ fetch: true, /** * Name of the variable for staffhl.js cache. Set to `null` to disable caching. * @type string|null * @ignore Not yet implemented! */ localStorageVar: 'staffhlCache', // TODO /** * The `maxage` parameter for caching. * @type number */ maxage: 1800, // 30 minutes /** * The group hierarchy. Also, only the users in these usergroups will ever be * found with the query. * @type string[] */ groupHierarchy: [ "editboard", "bureaucrat", "sysop", "jr-admin", "bot", ], /** * Groups to exclude from the resulting attribute value. * @type string[] */ exclude: [ "*", "user", "autoconfirmed", "emailconfirmed", ], /** The name of the attribute to store the user group information in. * Should be in form of a space-separated token list to allow querying * with CSS using the `[attr-name~="..."]` syntax. * @type string */ attr: "data-sthl-ugroups", /** The prefix regex for user page links. This check happens after * URL-decoding the page title. */ linkPrefix: /^User:/, /** Limit of users fetched in one request */ reqLimit: 50, /** Attempt to skip the limit with recursion? */ skipLimit: true, /** The condition for the highlighting to happen */ condition() { return mw.config.get('wgNamespaceNumber') === -1 || mw.config.get('wgAction') === 'history' }, /** The function passed into the map method of the jQuery object to parse links. This must return a username with underscores replaced by spaces. */ linkMapper(element, index) { const linkPart = element.href.split('/').at(-1) if (element.href.split('/').at(-2) === 'w') { const params = new URLSearchParams(linkPart) const pageName = params.get('title') // URL decoding happens under the hood if (pageName !== null) { return pageName.split('/')[0].replace(this.linkPrefix, '') } } else { return linkPart.split('?')[0].split('/')[0].replace(this.linkPrefix, '').replace("_", " ") } }, /** * Converts a date into a compact timestamp. For now, supports precision down to * the hour. * @param date {Date} the `Date` object * @returns string */ toTimestamp(date) { return [ [date.getUTCFullYear(), 4], [date.getUTCMonth(), 2], [date.getUTCDate(), 2], [date.getUTCHours(), 2], ] .map(e => e[0].toString().padStart(e[1], '0')) .join('') }, /** * Converts a compact timestamp to a Date object. * @param timestamp {string} the timestamp * @returns Date */ fromTimestamp(timestamp) { const year = timestamp.slice(0, 4) const month = timestamp.slice(4, 6) const date = timestamp.slice(6, 8) const hours = timestamp.slice(8, 10) return new Date(year, month, date, hours) }, getData_fetch(w = {}) { const params = new URLSearchParams({ action: 'query', list: 'allusers', format: 'json', augroup: this.groupHierarchy.join("|"), auprop: 'groups', aulimit: this.reqLimit, maxage: this.maxage, ...w, }) const url = mw.config.get("wgServer") + "/w/api.php?" + params.toString() console.log(url) return fetch(url) }, getData_mwApi(w = {}) { return (new mw.Api()).get({ action: 'query', list: 'allusers', format: 'json', augroup: this.groupHierarchy, auprop: 'groups', aulimit: this.reqLimit, maxage: this.maxage, ...w, }) }, addAttrs($content, w = {}) { const settings = window.staffhlSettings; // https://bulbapedia.bulbagarden.net/w/api.php?action=query&list=allusers&format=json&augroup=sysop|editboard|jr-admin|sr-admin|retired-staff|bureaucrat&auprop=groups settings.getData(w).then(async data => { if (settings.fetch) { data = await data.json(); } console.log(data.query.allusers); if (settings.skipLimit && data['continue']) { settings.addAttrs($content, { ...w, aufrom: data['continue'].aufrom }) } const links = $('.mw-body a.mw-userlink').get() console.log(links) links.map((e, i) => [e, settings.linkMapper(e, i)]).forEach(([e, n]) => { const users = data.query.allusers const userObj = users.find(u => u.name === n) if (userObj !== undefined) { const groups = userObj.groups.filter(gp => settings.groupHierarchy.includes(gp) && !settings.exclude.includes(gp)) $(e).attr(settings.attr, groups.join(' ')) } }) }) } /* linkMapper(index, element) { const linkPart = element.href.split('/').at(-1) if (element.href.split('/').at(-2) === 'w') { const params = new URLSearchParams(linkPart) const pageName = params.get('title') // URL decoding happens under the hood if (pageName !== null) { return pageName.split('/')[0].replace(this.linkPrefix, '') } } else { return linkPart.split('?')[0].split('/')[0].replace(this.linkPrefix, '') } } */ } if (window.staffhlSettings.condition()) { if (window.staffhlSettings.fetch) { window.staffhlSettings.getData = window.staffhlSettings.getData_fetch } else { window.staffhlSettings.getData = window.staffhlSettings.getData_mwApi } mw.hook('wikipage.content').add(window.staffhlSettings.addAttrs) //window.staffhlSettings.addAttrs($content) }