User:Arashiryuu0/common.js

/** * @namespace Personal_JS */ // jshint browser: true, devel: true, jquery: true // jshint strict: true, freeze: true, eqeqeq: true, futurehostile: true // jshint newcap: true, noarg: true, quotmark: single, shadow: outer // jshint latedef: true, undef: true, unused: true, esnext: true

/** * @typedef Ref * @property {*} current */ /** * Callback for when Fandom is ready. * @callback cb * @returns {void} */ /** * Method of the Logger object. * @callback logMethod * @returns {void} */ /* global mw, requestIdleCallback */ 'use strict';

jsScope: { if (window.UCP && window.UCP.localJS) break jsScope; const has = Object.prototype.hasOwnProperty; const slice = Array.prototype.slice; const toString = Object.prototype.toString; /**    * Creates clean objects with a Symbol.toStringTag description of the object. * @param {!string} value * @returns {object} */   const _Object = function (value) { if (arguments.length < 1) value = 'NullObject'; if (typeof value !== 'string') throw new TypeError('Description must be of a `string` value.'); const obj = Object.create(null); Object.defineProperty(obj, Symbol.toStringTag, { value: value }); // RL prevents using modern syntax, so can't simply do this: // Object.create(null, { [Symbol.toStringTag]: { value } }) return obj; };   /**     * Cache of fired hooks. */   const fired = _Object('HookCache'); /**    * Ref helper. * @param {*} initialValue * @returns {Ref} */   const useRef = function (initialValue) { // initialValue = arguments.length > 0 ? arguments[0] : null; // createRef was a hardcoded null, useRef uses the value passed in		return { current: initialValue }; };	/**	 * `at` polyfill */	const at = function (o, idx) { if (o === undefined || o === null) return undefined; if ([-Infinity, +Infinity].includes(idx)) return undefined; var i = Math.trunc(idx) || 0; i = i < 0 ? o.length + i : i;		if (i < 0 || i >= o.length) return undefined; return o[i]; };   /**     * Determines if something is undefined or null. * Accounting for `document.all` and other potential weirdness version. */   const isNil = function (anything) { return anything === undefined || anything === null; };   /**     * Simple polyfill for the nullish coalescing operator (??) * @alias ifNull * @description if `expected` is null or undefined, return the `fallback` value. * @param {*} expected * @param {*} fallback * @returns {*} */   const ifNull = function (expected, fallback) { return isNil(expected) ? fallback : expected; };   /**     * Safely traverses an object. */   const getProp = function (obj, path) { return path.split(/\s?\.\s?/).reduce(function (o, prop) {			return o && o[prop];		}, obj); };   /**	 * Gets a more accurate description of an object than `typeof`. * @name typeOf * @param {*} item * @returns {!string} */	const typeOf = function (item) { return toString .call(item) .replace(/\[object (\w+)\]/i, '$1') .toLowerCase; };   /**     * Checks whether something is a Node instance. * @name isNode * @param {*} tester * @returns {!boolean} */   const isNode = function (tester) { return tester instanceof Node; };   /**     * Self-binds to all methods on an object. * @param {object} obj */   const applyBinds = function (obj) { if (isNil(obj)) return; const methods = Object.getOwnPropertyNames(obj).filter(function (name) {			return typeof obj[name] === 'function';		}); if (!methods.length) return; const counter = useRef(0); while (counter.current < methods.length) { const method = methods[counter.current++]; obj[method] = obj[method].bind(obj); }   };    /**     * Create Logger object. */   const Logger = _Object('Logger'); loggerScope: { const counter = useRef(0); /**		 * @type {!string[]} */		const levels = ['log', 'dir', 'info', 'warn', 'debug', 'error']; /**		 * Retrieves label data for logging methods. * @param {!string} name * @returns {!string[]} */		const getParts = function (name) { return [ '%c[' + name + ']%c \u2014 %s', 'color: #82AAFF;', 'color: #F78C6A;', new Date.toUTCString ];		};		/**        * Creates log methods. * @name makeLog * @param {!string} level * @param {!string} name * @returns {!logMethod} */       const makeLog = function (level, name) { return function { console.groupCollapsed.apply(null, getParts(name)); console[level].apply(null, arguments); console.groupEnd; };       };        while (counter.current < levels.length) { const level = levels[counter.current++]; Logger[level] = makeLog(level, 'User:Arashiryuu0/common.js'); }       applyBinds(Logger); Object.freeze(Logger); }   /**     * Create Utils object. */   const Utils = _Object('Utils'); utilsScope: { Object.assign(Utils, {			at: at,			type: typeOf,			isNil: isNil,			ifNull: ifNull,			isNode: isNode,			useRef: useRef,			getProp: getProp		}); applyBinds(Utils); Object.freeze(Utils); }   /**     * @param {!string} type * @param {?object} props * @returns {!HTMLElement} */   const createElement = function (type, props) { if (typeof type !== 'string') return; const element = document.createElement(type); const children = slice.call(arguments, 2); if (!isNil(props)) { Object.assign(element, props); if (has.call(props, 'style')) { try { Object.assign(element.style, props.style); } catch (error) { Logger.error(error); }			}			if (has.call(props, 'children')) { if (!Array.isArray(props.children)) props.children = [props.children]; element.append.apply(element, props.children); } else if (children.length) { element.append.apply(element, children); }			if (has.call(props, 'htmlFor')) element.setAttribute('for', props.htmlFor); } else if (isNil(props) && children.length) { element.append.apply(element, children); }		return element; };   /**     * @type {cb} */   const loaded = function  { if (fired.loaded) return; /**        * Loading scripts through the ResourceLoader via mw.loader */       scriptsScope: { const sUri = 'https://reds-test.fandom.com/wiki/User:Arashiryuu0/sandbox'; const sQuery = '?ctype=text/javascript&action=raw'; const queries = [ sUri + sQuery, sUri + '.javascript' + sQuery ];           const load = function (url) { if (typeof url !== 'string') return; mw.loader.load(url); };           queries.forEach(load); }       bannersScope: { const bannerItems = [ document.querySelector('.wds-global-navigation__logo') ].concat(slice.call(document.querySelectorAll('.wds-global-navigation__link'))); bannerItems.forEach(function (item) {				if (!item) return;				item.setAttribute('tabindex', '-1');			}); }		buttonsScope: { if (fired.buttons) break buttonsScope; const wdsButtons = document.querySelectorAll('.wiki-tools.wds-button-group'); if (!wdsButtons.length) break buttonsScope; const clone = function (button) { return button.cloneNode(true); };			const firstName = at(wdsButtons, 0).firstElementChild.className; const buttons = [ createElement('a', {					className: firstName.replace('wiki-tools__search', 'wiki-tools__user-js'),					textContent: 'JS',					href: '/wiki/User:Arashiryuu0/common.js'				}), createElement('a', {					className: firstName.replace('wiki-tools__search', 'wiki-tools__user-css'),					textContent: 'CSS',					href: '/wiki/User:Arashiryuu0/common.css'				}), createElement('a', {					className: firstName.replace('wiki-tools__search', 'wiki-tools__random'),					textContent: '?',					href: '/wiki/Special:Random'				}) ];			const frag = document.createDocumentFragment; const counter = useRef(0); while (counter.current < wdsButtons.length) { const wds = wdsButtons[counter.current++]; const cloned = buttons.map(clone); frag.append.apply(frag, cloned); wds.appendChild(frag); /**				 * fix button positioning * layout should be: * search, discussions, recent changes, theme, my buttons, dropdown */				wds.appendChild(wds.querySelector('.wds-dropdown')); }			fired.buttons = true; }		mw.hook('dev.highlight').add(function (hljs) {			const ref = useRef;			const disableOuterTheme = function {				const n = document.querySelector('link[href$=".min.css"]');				if (!n) {					ref.current = requestAnimationFrame(disableOuterTheme);					return;				}				n.setAttribute('disabled', '');				ref.current = null;			};			ref.current = requestAnimationFrame(disableOuterTheme);			hljs.loadAllLanguages				.then(function  { requestAnimationFrame(function {						hljs.useTheme('atom-one-dark');					}); }, Logger.error);			window.UCP.__rafRef = ref;		}); fired.loaded = true; };	window.UCP = window.UCP || {}; window.UCP.localJS = fired; window.UCP.Logger = Logger; window.UCP.Utils = Utils; window.importArticles.apply(null, [		{			type: 'script',			articles: [				'u:dev:MediaWiki:Preact.js',				'u:dev:MediaWiki:Highlight-js.js'			]		}	]); requestIdleCallback(loaded); } /*@end@*/