User:Andrybak/Vectron.js

// <nowiki>(function() {'use strict';const USERSCRIPT_NAME = 'Vectron';const config = {wikipage: '[[:en:User:Andrybak/${USERSCRIPT_NAME}|${USERSCRIPT_NAME}]]',version: '5'};const LOG_PREFIX = `[${USERSCRIPT_NAME} v${config.version}]:`;const mw = window.mw; // a hack to trick my JS editor into believing that `mw` exists// TODO: Not sure if still need to support the toggle button. Keep it for now.const TOGGLE_BUTTON_SELECTOR = '#p-dock-bottom button.vector-limited-width-toggle';const STANDARD_WIDTH_RADIO_BUTTON_SELECTOR = '#skin-client-pref-vector-feature-limited-width-value-1';const WIDE_WIDTH_RADIO_BUTTON_SELECTOR = '#skin-client-pref-vector-feature-limited-width-value-0';const ANY_CONTROL_SELECTOR = `${TOGGLE_BUTTON_SELECTOR}, ${STANDARD_WIDTH_RADIO_BUTTON_SELECTOR}, ${WIDE_WIDTH_RADIO_BUTTON_SELECTOR}`;/* * MediaWiki has automatic scrolling to (and highlighting of) messages * with mentions. This hash disappears quickly from document.location, * so we have to remember it separately from function maybeShowHashTarget(). */let mentionHash = null;function error(...toLog) {console.error(LOG_PREFIX, ...toLog);}function warn(...toLog) {console.warn(LOG_PREFIX, ...toLog);}function info(...toLog) {console.info(LOG_PREFIX, ...toLog);}function debug(...toLog) {console.debug(LOG_PREFIX, ...toLog);}function getLimitedWidthToggleButton() {return document.querySelector(TOGGLE_BUTTON_SELECTOR);}function isWideVector() {return document.querySelector('html').classList.contains('vector-feature-limited-width-clientpref-0');}function isNarrowVector() {return !isWideVector();}/* * Because we are messing with the layout of the page * on the fly, we need to ensure that the user sees * the linked section or linked mention on a discussion page. */function maybeShowHashTarget() {/* * These aren't regular #Section_heading anchors, but rather special * tags used by MediaWiki to highlight mentions. */if (mentionHash !== null) {/* * MediaWiki adds an empty <span> at the _start_ of a message with the * corresponding `id`. * This id also corresponds to the attribute `data-mw-thread-id` stored * in an empty <span> at the _end_ of the same message after the "Reply" * button ([[mw:Extension:DiscussionTools]]), right after the signature. */const maybeMentionMessage = document.getElementById(mentionHash.slice(1));/* * `null` will be returned in following cases: *   - when the message was removed (e.g. into an archive) *   - when the timestamp in the signature was re-generated (e.g. [[:en:Special:Diff/1222421941]]) */if (maybeMentionMessage !== null) {maybeMentionMessage.scrollIntoView();return;}}/* * If a mention wasn't highlighted, try to scroll to a regular * anchor of a section. */if (document.location.hash === "") {return;}const targetId = document.location.hash.slice(1).replaceAll(' ', '_');document.getElementById(targetId)?.scrollIntoView();}function ensureNeededWidth(checkFn, adjective, verb, controlClass) {if (checkFn()) {debug(`Already ${adjective}.`);return;}info(verb);const control = document.querySelector(controlClass);control.click();maybeShowHashTarget();}function ensureWide() {ensureNeededWidth(isWideVector,'wide','Widening.',`${WIDE_WIDTH_RADIO_BUTTON_SELECTOR}, ${TOGGLE_BUTTON_SELECTOR}`);}function ensureNarrow() {ensureNeededWidth(isNarrowVector,'narrow','Narrowing.',`${STANDARD_WIDTH_RADIO_BUTTON_SELECTOR}, ${TOGGLE_BUTTON_SELECTOR}`);}/* * The main function of the script. */function runScript() {/* * Reference documentation about keys and values in mw.config: * https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config */if (!mw.config.get('wgIsArticle')) { // This variable is badly named -- it is not related to a page being a main namespace "article".info('Not a wiki page.');ensureWide();return;}if (mw.config.get('wgDiffNewId') != null || mw.config.get('wgDiffOldId') != null) {info('Diff view.');ensureWide();return;}const namespaceNumber = mw.config.get('wgNamespaceNumber');if (namespaceNumber === -1) {info('This is a "Special:" page.');ensureWide();return;}const contentModel = mw.config.get("wgPageContentModel");// ['javascript', 'css', 'sanitized-css', 'Scribunto'].includes(contentModel)if (contentModel !== 'wikitext') {info('Content model of the page is for source code (Lua, JS, CSS, etc).');ensureWide();return;}info('Assuming wiki page.');ensureNarrow();}function wait(message) {info(message);setTimeout(lazyLoadVectron, 200);}function rememberMentionHash() {const params = new URLSearchParams(document.location.search);if (params.get('markasread') !== null) {mentionHash = document.location.hash;info('Remembered comment hash:', mentionHash);}}/* * Infrastructure to ensure the script can run. */function lazyLoadVectron() {debug('Loading...');const skinId = mw.config.get("skin");if (skinId === null) {wait('Skin is not loaded yet. Waiting...');return;}if (skinId !== 'vector-2022') {warn(`Skin ${skinId} is not supported by the script. Aborting.`);return;}const anyControl = document.querySelector(ANY_CONTROL_SELECTOR);if (anyControl === null) {wait('The UI controls are not loaded yet. Waiting...');return;}const button = getLimitedWidthToggleButton();if (button !== null) {const theAttribute = button.getAttribute('data-event-name');if (theAttribute === null) {wait('Attribute "data-event-name" of the toggle button is not loaded yet. Waiting...');return;}}runScript();}rememberMentionHash();if (document.readyState !== 'loading') {lazyLoadVectron();} else {warn('Cannot load yet. Setting up a listener...');document.addEventListener('DOMContentLoaded', lazyLoadVectron);}})();// </nowiki>