From e4b6b784764f4f45f2e69d8c949880698b7d6e70 Mon Sep 17 00:00:00 2001 From: Typpi <20943337+Nick2bad4u@users.noreply.github.com> Date: Fri, 1 Nov 2024 18:57:47 -0400 Subject: [PATCH 01/35] Update magic-userjs.user.js added // @connect githubusercontent.com to fix errors when the url is redirected from github Signed-off-by: Typpi <20943337+Nick2bad4u@users.noreply.github.com> --- dist/magic-userjs.user.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index 604696e..36a60f2 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -40,6 +40,7 @@ // @connect greasyfork.org // @connect sleazyfork.org // @connect github.com +// @connect githubusercontent.com // @connect openuserjs.org // @grant GM_addElement // @grant GM_info @@ -5074,4 +5075,4 @@ const init = async () => { }; init(); -})(); \ No newline at end of file +})(); From 5479baff9b59621221ba9f934eb573a4c3d54d65 Mon Sep 17 00:00:00 2001 From: Magic Date: Thu, 6 Feb 2025 13:54:51 -0800 Subject: [PATCH 02/35] v7.1.0 Signed-off-by: Magic --- CHANGELOG.user.md | 26 +- README.md | 2 +- dist/magic-userjs.meta.js | 2 +- dist/magic-userjs.user.js | 320 ++++--- package.json | 43 +- pnpm-lock.yaml | 1751 +++++++++++++++++++----------------- src/UserJS/main.js | 318 ++++--- src/typings/UserJS.d.ts | 26 +- src/typings/scheduler.d.ts | 131 +++ src/typings/types.d.ts | 2 - 10 files changed, 1491 insertions(+), 1130 deletions(-) create mode 100644 src/typings/scheduler.d.ts diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index be5372b..cf60e4a 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,4 +1,26 @@ -# What's New +# What's New (v7.1.0) + +* Implemented [Task Scheduling API](https://developer.mozilla.org/en-US/docs/Web/API/Prioritized_Task_Scheduling_API) + * Limited availability, see [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Scheduler#browser_compatibility) + * I added basic polyfills so hopefully there won't be issues. +* Improved error handling +* _Be sure to look in your console if the UserScript stops working for some reason!_ + +## Known Issues + +* "Filter out other languages" may not filter _every_ userscript that is not in your language. +* SVG elements don't load on every webpage, _can be blocked by the page._ + +## TODO + +* Add [GreasyFork Bullshit Filter](https://greasyfork.org/scripts/12179) into list +* Merge https://github.com/magicoflolis/Userscript-Plus/pull/59 +* Add sorting to the following: "Total installs", "Ratings", "Created date" +* Improve design of blacklist section + +--- + +# What's New (v7.0.0) * Ability to change the URL of each engine * **Please reset your config if updating!** @@ -25,3 +47,5 @@ * Add sorting to the following: "Total installs", "Ratings", "Created date" * Improve design of blacklist section + +--- diff --git a/README.md b/README.md index ef1741a..5f3c5bd 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * Try again on another webpage [[Test Page](https://youtube.com)] * Default timeout is 10000ms before the count disappears -* If issue persists, see [View UserScript Logs](#view-userscript-logs) or submit a [New Issue](https://github.com/magicoflolis/Userscript-Plus/issues/new/choose) +* If issue persists, see [View Console Logs](#view-console-logs) or submit a [New Issue](https://github.com/magicoflolis/Userscript-Plus/issues/new/choose) **(UserScript) Error occurred while injecting Container:** diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index 5852785..65a9e86 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.0.0 +// @version 7.1.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index 604696e..e4ff1da 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.0.0 +// @version 7.1.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -1511,9 +1511,16 @@ const err = (...msg) => { 'color: rgb(249, 24, 128);', ...msg ); + const a = typeof alert !== 'undefined' && alert; for (const ex of msg) { - if (typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined') { - alert(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); + // typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined' + // const isE = Object.prototype.toString.call(ex).includes('Error'); + // if (isE && 'cause' in ex && a) { + // a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); + // } + // const isO = Object.prototype.toString.call(ex).includes('Object'); + if (typeof ex === 'object' && 'cause' in ex && a) { + a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); } } }; @@ -1541,14 +1548,34 @@ const log = (...msg) => { * @type { import("../typings/types.d.ts").config } */ let cfg = {}; -// let ghMsg = null; + +/** + * https://github.com/zloirock/core-js/blob/master/packages/core-js/internals/global-this.js + * @returns {typeof globalThis} + */ +function globalWin() { + const check = function (it) { + return it && it.Math === Math && it; + }; + return ( + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + check(typeof self == 'object' && self) || + check(typeof this == 'object' && this) || + (function () { + return this; + })() || + Function('return this')() + ); +} /** @type { import("../typings/UserJS.d.ts").safeSelf } */ function safeSelf() { if (userjs.safeSelf) { return userjs.safeSelf; } - const g = globalThis; + const g = globalWin(); + /** @type { import("../typings/UserJS.d.ts").safeHandles } */ const safe = { XMLHttpRequest: g.XMLHttpRequest, createElement: g.document.createElement.bind(g.document), @@ -1556,17 +1583,49 @@ function safeSelf() { createTextNode: g.document.createTextNode.bind(g.document), setTimeout: g.setTimeout, clearTimeout: g.clearTimeout, - trustedTypes: g.trustedTypes + navigator: g.navigator, + scheduler: { + postTask(callback, options) { + if ('scheduler' in g && 'postTask' in g.scheduler) { + return g.scheduler.postTask(callback, options); + } + + options = Object.assign({}, options); + + if (options.delay === undefined) options.delay = 0; + options.delay = Number(options.delay); + if (options.delay < 0) { + return Promise.reject(new TypeError('"delay" must be a positive number.')); + } + return new Promise((resolve) => { + g.setTimeout(() => { + resolve(callback()); + }, options.delay); + }); + }, + yield() { + if ('scheduler' in g && 'yield' in g.scheduler) { + scheduler.yield(); + return g.scheduler.yield(); + } + return new Promise((resolve) => { + g.setTimeout(resolve, 0); + }); + } + } }; userjs.safeSelf = safe; - return safe; + return userjs.safeSelf; } const BLANK_PAGE = 'about:blank'; // Lets highlight me :) const authorID = 166061; -// Some UserJS I personally enjoy +/** + * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{{id}}` + */ const goodUserJS = [ + 12179, 423001, 376510, 23840, @@ -1576,10 +1635,10 @@ const goodUserJS = [ 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' ]; -// Remove UserJS from banned accounts -const badUserJS = [ - 478597, // Authors have been banned from GreasyFork -]; +/** + * Remove UserJS from banned accounts + */ +const badUserJS = [478597]; // Unsupport webpages for each engine const engineUnsupported = { greasyfork: ['pornhub.com'], @@ -1588,18 +1647,28 @@ const engineUnsupported = { github: [] }; const getUAData = () => { - if (typeof userjs.isMobile !== 'undefined') { + if (userjs.isMobile !== undefined) { return userjs.isMobile; } + // if (typeof userjs.isMobile !== 'undefined') { + // return userjs.isMobile; + // } try { - const { platform, mobile } = navigator.userAgentData ?? {}; - userjs.isMobile = - /Mobile|Tablet/.test(navigator.userAgent ?? '') || - mobile || - /Android|Apple/.test(platform ?? ''); + const { navigator } = safeSelf(); + if (navigator) { + const { userAgent, userAgentData } = navigator; + const { platform, mobile } = userAgentData ? Object(userAgentData) : {}; + userjs.isMobile = + /Mobile|Tablet/.test(userAgent ? String(userAgent) : '') || + Boolean(mobile) || + /Android|Apple/.test(platform ? String(platform) : ''); + } else { + userjs.isMobile = false; + } } catch (ex) { - err({ cause: 'getUAData', message: ex.message }); userjs.isMobile = false; + ex.cause = 'getUAData'; + err(ex); } return userjs.isMobile; }; @@ -1630,23 +1699,25 @@ const DEFAULT_CONFIG = { { enabled: true, name: 'greasyfork', - query: encodeURIComponent('https://greasyfork.org/scripts/by-site/{host}.json?language=all'), + query: encodeURIComponent('https://greasyfork.org/scripts/by-site/{host}.json?language=all') }, { enabled: false, name: 'sleazyfork', - query: encodeURIComponent('https://sleazyfork.org/scripts/by-site/{host}.json?language=all'), + query: encodeURIComponent('https://sleazyfork.org/scripts/by-site/{host}.json?language=all') }, { enabled: false, name: 'openuserjs', - query: encodeURIComponent('https://openuserjs.org/?q={host}'), + query: encodeURIComponent('https://openuserjs.org/?q={host}') }, { enabled: false, name: 'github', token: '', - query: encodeURIComponent('https://api.github.com/search/code?q="// ==UserScript=="+{host}+ "// ==/UserScript=="+in:file+language:js&per_page=30') + query: encodeURIComponent( + 'https://api.github.com/search/code?q="// ==UserScript=="+{host}+ "// ==/UserScript=="+in:file+language:js&per_page=30' + ) } ], theme: { @@ -1681,12 +1752,11 @@ const DEFAULT_CONFIG = { //#region i18n class i18nHandler { constructor() { - /** - * @type { string[] } - */ + /** @type { string[] } */ this.cache = []; - const languages = navigator.languages ?? []; + const { navigator } = safeSelf(); + const { languages } = navigator; for (const nlang of languages) { const lg = nlang.split('-')[0]; if (this.cache.indexOf(lg) === -1) { @@ -1700,12 +1770,15 @@ class i18nHandler { } } toDate(str = '') { + const { navigator } = safeSelf(); return new Intl.DateTimeFormat(navigator.language).format(new Date(str)); } toNumber(number) { + const { navigator } = safeSelf(); return new Intl.NumberFormat(navigator.language).format(number); } i18n$(...keys) { + const { navigator } = safeSelf(); const current = navigator.language.split('-')[0] ?? 'en'; const list = translations[cfg.language] ?? translations[current]; const arr = []; @@ -1719,6 +1792,7 @@ const language = new i18nHandler(); const { i18n$ } = language; //#endregion // #region Utilities +const union = (...arr) => [...new Set(arr.flat())]; /** * @type { import("../typings/types.d.ts").qs } */ @@ -1741,21 +1815,10 @@ const qsA = (selectors, root) => { } return []; }; -/** - * @type { import("../typings/types.d.ts").hasOwn } - */ -const hasOwn = (o, v) => { - if (typeof Object.hasOwn !== 'undefined') { - return Object.hasOwn(o, v); - } - return Object.prototype.hasOwnProperty.call(o, v); -}; /** * @type { import("../typings/types.d.ts").objToStr } */ -const objToStr = (obj) => { - return Object.prototype.toString.call(obj); -}; +const objToStr = (obj) => Object.prototype.toString.call(obj); /** * @type { import("../typings/types.d.ts").strToURL } */ @@ -1765,7 +1828,8 @@ const strToURL = (str) => { str = str ?? WIN_LOCATION; return objToStr(str).includes('URL') ? str : new URL(str); } catch (ex) { - err({ cause: 'strToURL', message: ex.message }); + ex.cause = 'strToURL'; + err(ex); } return WIN_LOCATION; }; @@ -1887,8 +1951,8 @@ const formAttrs = (elem, attr = {}) => { const make = (tagName, cname, attrs) => { let el; try { - const safe = safeSelf(); - el = safe.createElement(tagName); + const { createElement } = safeSelf(); + el = createElement(tagName); if (!isEmpty(cname)) { if (typeof cname === 'string') { el.className = cname; @@ -1904,6 +1968,7 @@ const make = (tagName, cname, attrs) => { } } } catch (ex) { + ex.cause = 'make'; err(ex); } return el; @@ -2108,8 +2173,8 @@ const iconSVG = { html: '' }, load(type, container) { - const safe = safeSelf(); - const svgElem = safe.createElementNS('http://www.w3.org/2000/svg', 'svg'); + const { createElementNS } = safeSelf(); + const svgElem = createElementNS('http://www.w3.org/2000/svg', 'svg'); for (const [k, v] of Object.entries(iconSVG[type])) { if (k === 'html') { continue; @@ -2179,6 +2244,7 @@ const StorageSystem = { : def; } catch (ex) { err(ex); + return def; } } }; @@ -2207,10 +2273,11 @@ const Command = { * @type { import("../typings/UserJS.d.ts").Network } */ const Network = { - async req(url, method = 'GET', responseType = 'json', data = {}, useFetch = false) { + async req(url, method = 'GET', responseType = 'json', data, useFetch = false) { if (isEmpty(url)) { throw new Error('"url" parameter is empty'); } + data = Object.assign({}, data); method = this.bscStr(method, false); responseType = this.bscStr(responseType); const params = { @@ -2235,13 +2302,15 @@ const Network = { } else if (params.onprogress) { delete params.onprogress; } - return await new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { if (isGM && !useFetch) { Network.xmlRequest({ url, responseType, ...params, - onerror: reject, + onerror: (r_1) => { + reject(new Error(`${r_1.status} ${url}`)); + }, onload: (r_1) => { if (r_1.status !== 200) reject(new Error(`${r_1.status} ${url}`)); if (responseType.match(/basic/)) resolve(r_1); @@ -2304,8 +2373,8 @@ const Network = { } } return await new Promise((resolve, reject) => { - const safe = safeSelf(); - const req = new safe.XMLHttpRequest(); + const { XMLHttpRequest } = safeSelf(); + const req = new XMLHttpRequest(); let method = 'GET'; let url = BLANK_PAGE; let body; @@ -2423,6 +2492,7 @@ class Container { this.updateCounter = this.updateCounter.bind(this); this.updateCounters = this.updateCounters.bind(this); this.showError = this.showError.bind(this); + this.webpage = strToURL(url); this.host = this.getHost(this.webpage.host); this.domain = this.getDomain(this.webpage.host); @@ -2513,7 +2583,7 @@ class Container { window.addEventListener('beforeunload', this.remove); } /** - * @param { Function } callback + * @param { function(): * } callback * @param { Document } doc */ async inject(callback, doc) { @@ -2528,6 +2598,7 @@ class Container { if (doc === null) { return; } + while (this.ready === false) { await new Promise((resolve) => requestAnimationFrame(resolve)); } @@ -2989,7 +3060,6 @@ class Container { } catch (ex) { err(ex); } - return null; } checkBlacklist(str) { str = str || this.host; @@ -3029,7 +3099,7 @@ class Container { } } this.isBlacklisted = blacklisted; - return blacklisted; + return this.isBlacklisted; } getInfo(url) { const webpage = strToURL(url || this.webpage); @@ -3110,8 +3180,9 @@ class Container { } this.promptElem.append(el); } - makeError(...ex) { - const safe = safeSelf(); + showError(...ex) { + err(...ex); + const { createTextNode } = safeSelf(); const error = make('mu-js', 'error'); let str = ''; for (const e of ex) { @@ -3122,13 +3193,9 @@ class Container { } } } - error.appendChild(safe.createTextNode(str)); + error.appendChild(createTextNode(str)); this.footer.append(error); } - showError(...ex) { - err(...ex); - this.makeError(...ex); - } updateCounter(count, engine) { this.counters[engine.name] += count; this.counters.total += count; @@ -3139,8 +3206,9 @@ class Container { if (k === 'total') { continue; } - if (qs(`count-frame[data-counter="${k}"]`, this.countframe)) { - dom.text(qs(`count-frame[data-counter="${k}"]`, this.countframe), v); + const c = qs(`count-frame[data-counter="${k}"]`, this.countframe); + if (c) { + dom.text(c, v); } } dom.text(this.mainbtn, this.counters.total); @@ -3162,6 +3230,7 @@ const container = new Container(); // #region Primary Function function primaryFN() { try { + const { scheduler } = safeSelf(); const { mainframe, urlBar, @@ -3314,11 +3383,6 @@ function primaryFN() { dom.cl.remove(mainframe, 'hidden'); timeoutFrame(); } else if (cmd === 'save') { - // if (!isNull(ghMsg)) { - // ghMsg = null; - // container.rebuild = true; - // dom.prop(rateContainer, 'innerHTML', ''); - // } container.rebuild = true; dom.prop(rateContainer, 'innerHTML', ''); if (!dom.prop(target, 'disabled')) { @@ -3811,6 +3875,9 @@ function primaryFN() { } return false; } + // intersect(a, ...arr) { + // return [...new Set(a)].filter((v) => arr.every((b) => b.includes(v))); + // } } const mergeTemplate = (obj = {}) => { const template = { @@ -3837,6 +3904,12 @@ function primaryFN() { } ] }; + /** @type {ObjectConstructor["hasOwn"]} */ + const hasOwn = + Object.hasOwn || + function hasOwn(it, key) { + return Object.prototype.hasOwnProperty.call(it, key); + }; for (const key in template) { if (hasOwn(obj, key)) continue; obj[key] = template[key]; @@ -3910,17 +3983,20 @@ function primaryFN() { } } }; + /** + * @param {number} [time] + */ const timeoutFrame = async (time) => { - time = time ?? cfg.time; frameTimeout.clear(...frameTimeout.ids); if (dom.cl.has(mainframe, 'hidden')) { return; } + time = time ?? cfg.time ?? DEFAULT_CONFIG.time; + let n = 10000; if (typeof time === 'number' && !Number.isNaN(time)) { - await frameTimeout.set(container.isBlacklisted ? time / 2 : time); - } else { - await frameTimeout.set(10000); + n = container.isBlacklisted ? time / 2 : time; } + await frameTimeout.set(n); container.remove(); return frameTimeout.clear(...frameTimeout.ids); }; @@ -4136,15 +4212,14 @@ function primaryFN() { return tr; }; // #endregion - // #region Build List + // #region List class List { engines; cache; intHost; constructor(host = undefined) { - if (isEmpty(host)) { - host = container.host; - } + this.build = this.build.bind(this); + if (isEmpty(host)) host = container.host; this.engines = cfg.engines; this.cache = container.cache.get(host); this.host = host; @@ -4181,20 +4256,14 @@ function primaryFN() { }; this.engines = cfg.engines.filter((e) => e.enabled && isSupported(e.name)); this.cache = container.cache.get(hostname); - // if (!isNull(ghMsg)) { - // const txt = make('mujs-row', 'legacy-config', { - // textContent: ghMsg - // }); - // rateContainer.append(txt); - // return; - // } } get host() { return this.intHost; } - async build() { + // #region Builder + build() { try { container.refresh(); if (this.blacklisted) { @@ -4207,8 +4276,9 @@ function primaryFN() { } info(' Building list', { cache: this.cache, engines: this.engines }); const customRecords = []; - const arr = []; const host = this.host; + const arr = []; + for (const engine of this.engines) { const cEngine = this.cache[`${engine.name}`]; if (!isEmpty(cEngine)) { @@ -4220,6 +4290,13 @@ function primaryFN() { updateCounter(cEngine.length, engine); continue; } + const respError = (error) => { + if (error.message.startsWith('429')) { + showError(`Engine: "${engine.name}" Too many requests...`); + return; + } + showError(`Engine: "${engine.name}"`, error.message); + }; const _mujs = (d) => { const obj = { ...d, @@ -4347,7 +4424,7 @@ function primaryFN() { : Array.isArray(dataQ.query) ? dataQ.query : []; - const dataA = dq.filter((d) => !d.deleted); + const dataA = dq.filter(Boolean).filter((d) => !d.deleted); if (isBlank(dataA)) { return; } @@ -4379,7 +4456,7 @@ function primaryFN() { hds.push(ujs); } } - finalList = [...new Set([...hds, ...filterLang])]; + finalList = union(hds, filterLang); for (const ujs of finalList) { if (cfg.codePreview && !ujs._mujs.code.data) { @@ -4486,7 +4563,9 @@ function primaryFN() { continue; } netFN = Network.req( - toQuery(`${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30`), + toQuery( + `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` + ), 'GET', 'json', { @@ -4514,27 +4593,25 @@ function primaryFN() { rateContainer.append(txt); } }) - .catch(showError); - }) - .catch(showError); - } else if (/openuserjs/gi.test(engine.name)) { - netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document') - .then(openuserjs) - .catch((error) => { - showError(`Engine: "${engine.name}"`, error); + .catch(respError); }); + } else if (/openuserjs/gi.test(engine.name)) { + netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document').then( + openuserjs + ); } else { - netFN = Network.req(toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`)) - .then(forkFN) - .catch(showError); + netFN = Network.req( + toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) + ).then(forkFN); } if (netFN) { - arr.push(netFN); + arr.push(netFN.catch(respError)); } } urlBar.placeholder = i18n$('search_placeholder'); urlBar.value = ''; + Promise.allSettled(arr).then(() => { tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); @@ -4543,6 +4620,7 @@ function primaryFN() { showError(ex); } } + // #endregion } const MUList = new List(); // #endregion @@ -4600,7 +4678,7 @@ function primaryFN() { }); if (engine.query) { - const d = DEFAULT_CONFIG.engines.find(e => e.name === engine.name); + const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); const urlInp = make('input', '', { type: 'text', defaultValue: '', @@ -4641,7 +4719,6 @@ function primaryFN() { cfgMap.set('github-token', ghToken); } } - } else { inp.checked = cfg[nm]; ael(inp, 'change', (evt) => { @@ -4689,22 +4766,6 @@ function primaryFN() { makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); makerow('Open UserJS', 'checkbox', 'openuserjs'); makerow('GitHub API', 'checkbox', 'github'); - // const ghAPI = cfg.engines.find((c) => c.name === 'github'); - // const ghToken = makerow('GitHub API (Token)', 'text', 'github', { - // defaultValue: '', - // value: ghAPI.token ?? '', - // placeholder: 'Paste Access Token', - // onchange(evt) { - // container.unsaved = true; - // container.rebuild = true; - // ghAPI.token = evt.target.value; - // // if (isNull(ghMsg)) { - // // ghAPI.token = evt.target.value; - // // } - // } - // }); - // ghToken.dataset.engine = 'github-token'; - // cfgMap.set('github-token', ghToken); makerow(`${i18n$('dtime')} (ms)`, 'number', 'time', { defaultValue: 10000, value: cfg.time, @@ -4856,7 +4917,7 @@ function primaryFN() { if (!dom.cl.has(cfgpage, 'hidden')) { const reg = new RegExp(val, 'gi'); for (const elem of qsA('mujs-section[data-name]', cfgpage)) { - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -4879,7 +4940,7 @@ function primaryFN() { const reg = new RegExp(q_value, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -4901,7 +4962,7 @@ function primaryFN() { const reg = new RegExp(q_value, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -4934,7 +4995,7 @@ function primaryFN() { const reg = new RegExp(q_value, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -4952,7 +5013,7 @@ function primaryFN() { const reg = new RegExp(val, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -5014,8 +5075,8 @@ function primaryFN() { return; } }); - makecfg(); - MUList.build().then(timeoutFrame); + scheduler.postTask(makecfg, { priority: 'user-visible' }); + scheduler.postTask(MUList.build, { priority: 'background' }).then(timeoutFrame); dbg('Container', container); } catch (ex) { err(ex); @@ -5025,16 +5086,17 @@ function primaryFN() { // #endregion /** * @template { Function } F - * @param { (this: F, doc: Document) => any } onDomReady + * @param { (this: F, doc: Document) => * } onDomReady */ const loadDOM = (onDomReady) => { if (!isFN(onDomReady)) { return; } if (document.readyState === 'interactive' || document.readyState === 'complete') { - onDomReady.call({}, document); + onDomReady(document); + return; } - document.addEventListener('DOMContentLoaded', (evt) => onDomReady.call({}, evt.target), { + document.addEventListener('DOMContentLoaded', (evt) => onDomReady(evt.target), { once: true }); }; @@ -5049,18 +5111,20 @@ const init = async () => { loadDOM((doc) => { try { if (window.location === null) { - throw new Error('"window.location" is null, reload the webpage or use a different one'); + throw new Error('"window.location" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); } if (doc === null) { - throw new Error('"doc" is null, reload the webpage or use a different one'); + throw new Error('"doc" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); } if (window.trustedTypes && window.trustedTypes.createPolicy) { window.trustedTypes.createPolicy('default', { createHTML: (string) => string }); } + sleazyRedirect(); container.inject(primaryFN, doc); + Command.register(i18n$('userjs_inject'), () => { container.inject(primaryFN, doc); }); diff --git a/package.json b/package.json index e1429c5..da80506 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/magicoflolis/Userscript-Plus/issues" }, "userJS": { - "version": "7.0.0", + "version": "7.1.0", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", @@ -105,37 +105,37 @@ "web-run:firefox-android": "web-ext run --config=./tools/web-ext.js -t firefox-android --firefox-apk org.mozilla.firefox" }, "devDependencies": { - "@swc/cli": "^0.4.0", - "@swc/core": "^1.7.39", - "@types/chrome": "0.0.279", + "@swc/cli": "^0.6.0", + "@swc/core": "^1.10.12", + "@types/chrome": "0.0.300", "@types/firefox-webext-browser": "120.0.4", "@types/greasemonkey": "4.0.7", - "@types/node": "^22.7.9", - "@types/tampermonkey": "^5.0.3", + "@types/node": "^22.13.0", + "@types/tampermonkey": "^5.0.4", "@types/webpack": "^5.28.5", "@violentmonkey/types": "0.2.0", - "browserslist": "^4.24.2", - "concurrently": "^9.0.1", + "browserslist": "^4.24.4", + "concurrently": "^9.1.2", "copy-webpack-plugin": "^12.0.2", "crx3": "^1.1.3", "css-loader": "^7.1.2", - "dotenv": "^16.4.5", - "eslint": "^9.13.0", - "eslint-config-prettier": "^9.1.0", - "globals": "^15.11.0", + "dotenv": "^16.4.7", + "eslint": "^9.19.0", + "eslint-config-prettier": "^10.0.1", + "globals": "^15.14.0", "http-server": "^14.1.1", - "mini-css-extract-plugin": "^2.9.1", + "mini-css-extract-plugin": "^2.9.2", "path-browserify": "^1.0.1", - "prettier": "^3.3.3", - "sass-embedded": "^1.80.4", - "sass-loader": "^16.0.2", + "prettier": "^3.4.2", + "sass-embedded": "^1.83.4", + "sass-loader": "^16.0.4", "swc-loader": "^0.2.6", - "terser-webpack-plugin": "^5.3.10", - "typescript": "^5.6.3", + "terser-webpack-plugin": "^5.3.11", + "typescript": "^5.7.3", "watchpack": "^2.4.2", "web-ext": "^8.3.0", - "webpack": "^5.95.0", - "webpack-cli": "^5.1.4", + "webpack": "^5.97.1", + "webpack-cli": "^6.0.1", "webpack-merge": "^6.0.1" }, "repository": { @@ -156,9 +156,6 @@ "sourceDir": "./build/firefox/", "artifactsDir": "./build" }, - "browserslist": [ - "defaults" - ], "engines": { "node": ">=20" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 449d7c6..4307bb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,14 +9,14 @@ importers: .: devDependencies: '@swc/cli': - specifier: ^0.4.0 - version: 0.4.0(@swc/core@1.7.39) + specifier: ^0.6.0 + version: 0.6.0(@swc/core@1.10.12) '@swc/core': - specifier: ^1.7.39 - version: 1.7.39 + specifier: ^1.10.12 + version: 1.10.12 '@types/chrome': - specifier: 0.0.279 - version: 0.0.279 + specifier: 0.0.300 + version: 0.0.300 '@types/firefox-webext-browser': specifier: 120.0.4 version: 120.0.4 @@ -24,71 +24,71 @@ importers: specifier: 4.0.7 version: 4.0.7 '@types/node': - specifier: ^22.7.9 - version: 22.7.9 + specifier: ^22.13.0 + version: 22.13.0 '@types/tampermonkey': - specifier: ^5.0.3 - version: 5.0.3 + specifier: ^5.0.4 + version: 5.0.4 '@types/webpack': specifier: ^5.28.5 - version: 5.28.5(@swc/core@1.7.39)(webpack-cli@5.1.4) + version: 5.28.5(@swc/core@1.10.12)(webpack-cli@6.0.1) '@violentmonkey/types': specifier: 0.2.0 version: 0.2.0 browserslist: - specifier: ^4.24.2 - version: 4.24.2 + specifier: ^4.24.4 + version: 4.24.4 concurrently: - specifier: ^9.0.1 - version: 9.0.1 + specifier: ^9.1.2 + version: 9.1.2 copy-webpack-plugin: specifier: ^12.0.2 - version: 12.0.2(webpack@5.95.0) + version: 12.0.2(webpack@5.97.1) crx3: specifier: ^1.1.3 version: 1.1.3 css-loader: specifier: ^7.1.2 - version: 7.1.2(webpack@5.95.0) + version: 7.1.2(webpack@5.97.1) dotenv: - specifier: ^16.4.5 - version: 16.4.5 + specifier: ^16.4.7 + version: 16.4.7 eslint: - specifier: ^9.13.0 - version: 9.13.0 + specifier: ^9.19.0 + version: 9.19.0 eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@9.13.0) + specifier: ^10.0.1 + version: 10.0.1(eslint@9.19.0) globals: - specifier: ^15.11.0 - version: 15.11.0 + specifier: ^15.14.0 + version: 15.14.0 http-server: specifier: ^14.1.1 version: 14.1.1 mini-css-extract-plugin: - specifier: ^2.9.1 - version: 2.9.1(webpack@5.95.0) + specifier: ^2.9.2 + version: 2.9.2(webpack@5.97.1) path-browserify: specifier: ^1.0.1 version: 1.0.1 prettier: - specifier: ^3.3.3 - version: 3.3.3 + specifier: ^3.4.2 + version: 3.4.2 sass-embedded: - specifier: ^1.80.4 - version: 1.80.4 + specifier: ^1.83.4 + version: 1.83.4 sass-loader: - specifier: ^16.0.2 - version: 16.0.2(sass-embedded@1.80.4)(webpack@5.95.0) + specifier: ^16.0.4 + version: 16.0.4(sass-embedded@1.83.4)(webpack@5.97.1) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.7.39)(webpack@5.95.0) + version: 0.2.6(@swc/core@1.10.12)(webpack@5.97.1) terser-webpack-plugin: - specifier: ^5.3.10 - version: 5.3.10(@swc/core@1.7.39)(webpack@5.95.0) + specifier: ^5.3.11 + version: 5.3.11(@swc/core@1.10.12)(webpack@5.97.1) typescript: - specifier: ^5.6.3 - version: 5.6.3 + specifier: ^5.7.3 + version: 5.7.3 watchpack: specifier: ^2.4.2 version: 2.4.2 @@ -96,11 +96,11 @@ importers: specifier: ^8.3.0 version: 8.3.0 webpack: - specifier: ^5.95.0 - version: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + specifier: ^5.97.1 + version: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) webpack-cli: - specifier: ^5.1.4 - version: 5.1.4(webpack@5.95.0) + specifier: ^6.0.1 + version: 6.0.1(webpack@5.97.1) webpack-merge: specifier: ^6.0.1 version: 6.0.1 @@ -143,9 +143,9 @@ packages: engines: {node: '>= 0.10.4'} hasBin: true - '@discoveryjs/json-ext@0.5.7': - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} + '@discoveryjs/json-ext@0.6.3': + resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} + engines: {node: '>=14.17.0'} '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} @@ -153,52 +153,52 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.11.1': - resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.18.0': - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} + '@eslint/config-array@0.19.1': + resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.7.0': - resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==} + '@eslint/core@0.10.0': + resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/eslintrc@3.1.0': - resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + '@eslint/eslintrc@3.2.0': + resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/js@8.57.1': resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@9.13.0': - resolution: {integrity: sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==} + '@eslint/js@9.19.0': + resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.4': - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + '@eslint/object-schema@2.1.5': + resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.0': - resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} + '@eslint/plugin-kit@0.2.5': + resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@fluent/syntax@0.19.0': resolution: {integrity: sha512-5D2qVpZrgpjtqU4eNOcWGp1gnUCgjfM+vKGE2y03kKN6z5EBhtx0qdRFbg8QuNNj8wXNoX93KJoYb+NqoxswmQ==} engines: {node: '>=14.0.0', npm: '>=7.0.0'} - '@humanfs/core@0.19.0': - resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.5': - resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} engines: {node: '>=18.18.0'} '@humanwhocodes/config-array@0.13.0': @@ -218,6 +218,10 @@ packages: resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} + '@humanwhocodes/retry@0.4.1': + resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} + engines: {node: '>=18.18'} + '@jridgewell/gen-mapping@0.3.2': resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} engines: {node: '>=6.0.0'} @@ -236,16 +240,12 @@ packages: '@jridgewell/sourcemap-codec@1.4.14': resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - '@jridgewell/trace-mapping@0.3.22': - resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} '@mdn/browser-compat-data@5.6.0': resolution: {integrity: sha512-xArvLyzuk0r2m6hFVjTMYoLvhWwys3h7W8pO15tjSAea+U39cErWDNfoUs4g2C08HVg6bDHyDMBc0LC6FKRpVw==} - '@mole-inc/bin-wrapper@8.0.1': - resolution: {integrity: sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -270,87 +270,90 @@ packages: resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} engines: {node: '>=12'} - '@sindresorhus/is@4.6.0': - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sindresorhus/is@5.6.0': + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} '@sindresorhus/merge-streams@2.3.0': resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - '@swc/cli@0.4.0': - resolution: {integrity: sha512-4JdVrPtF/4rCMXp6Q1h5I6YkYZrCCcqod7Wk97ZQq7K8vNGzJUryBv4eHCvqx5sJOJBrbYm9fcswe1B0TygNoA==} + '@swc/cli@0.6.0': + resolution: {integrity: sha512-Q5FsI3Cw0fGMXhmsg7c08i4EmXCrcl+WnAxb6LYOLHw4JFFC3yzmx9LaXZ7QMbA+JZXbigU2TirI7RAfO0Qlnw==} engines: {node: '>= 16.14.0'} hasBin: true peerDependencies: '@swc/core': ^1.2.66 - chokidar: ^3.5.1 + chokidar: ^4.0.1 peerDependenciesMeta: chokidar: optional: true - '@swc/core-darwin-arm64@1.7.39': - resolution: {integrity: sha512-o2nbEL6scMBMCTvY9OnbyVXtepLuNbdblV9oNJEFia5v5eGj9WMrnRQiylH3Wp/G2NYkW7V1/ZVW+kfvIeYe9A==} + '@swc/core-darwin-arm64@1.10.12': + resolution: {integrity: sha512-pOANQegUTAriW7jq3SSMZGM5l89yLVMs48R0F2UG6UZsH04SiViCnDctOGlA/Sa++25C+rL9MGMYM1jDLylBbg==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.7.39': - resolution: {integrity: sha512-qMlv3XPgtPi/Fe11VhiPDHSLiYYk2dFYl747oGsHZPq+6tIdDQjIhijXPcsUHIXYDyG7lNpODPL8cP/X1sc9MA==} + '@swc/core-darwin-x64@1.10.12': + resolution: {integrity: sha512-m4kbpIDDsN1FrwfNQMU+FTrss356xsXvatLbearwR+V0lqOkjLBP0VmRvQfHEg+uy13VPyrT9gj4HLoztlci7w==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.7.39': - resolution: {integrity: sha512-NP+JIkBs1ZKnpa3Lk2W1kBJMwHfNOxCUJXuTa2ckjFsuZ8OUu2gwdeLFkTHbR43dxGwH5UzSmuGocXeMowra/Q==} + '@swc/core-linux-arm-gnueabihf@1.10.12': + resolution: {integrity: sha512-OY9LcupgqEu8zVK+rJPes6LDJJwPDmwaShU96beTaxX2K6VrXbpwm5WbPS/8FfQTsmpnuA7dCcMPUKhNgmzTrQ==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.7.39': - resolution: {integrity: sha512-cPc+/HehyHyHcvAsk3ML/9wYcpWVIWax3YBaA+ScecJpSE04l/oBHPfdqKUPslqZ+Gcw0OWnIBGJT/fBZW2ayw==} + '@swc/core-linux-arm64-gnu@1.10.12': + resolution: {integrity: sha512-nJD587rO0N4y4VZszz3xzVr7JIiCzSMhEMWnPjuh+xmPxDBz0Qccpr8xCr1cSxpl1uY7ERkqAGlKr6CwoV5kVg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.7.39': - resolution: {integrity: sha512-8RxgBC6ubFem66bk9XJ0vclu3exJ6eD7x7CwDhp5AD/tulZslTYXM7oNPjEtje3xxabXuj/bEUMNvHZhQRFdqA==} + '@swc/core-linux-arm64-musl@1.10.12': + resolution: {integrity: sha512-oqhSmV+XauSf0C//MoQnVErNUB/5OzmSiUzuazyLsD5pwqKNN+leC3JtRQ/QVzaCpr65jv9bKexT9+I2Tt3xDw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.7.39': - resolution: {integrity: sha512-3gtCPEJuXLQEolo9xsXtuPDocmXQx12vewEyFFSMSjOfakuPOBmOQMa0sVL8Wwius8C1eZVeD1fgk0omMqeC+Q==} + '@swc/core-linux-x64-gnu@1.10.12': + resolution: {integrity: sha512-XldSIHyjD7m1Gh+/8rxV3Ok711ENLI420CU2EGEqSe3VSGZ7pHJvJn9ZFbYpWhsLxPqBYMFjp3Qw+J6OXCPXCA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.7.39': - resolution: {integrity: sha512-mg39pW5x/eqqpZDdtjZJxrUvQNSvJF4O8wCl37fbuFUqOtXs4TxsjZ0aolt876HXxxhsQl7rS+N4KioEMSgTZw==} + '@swc/core-linux-x64-musl@1.10.12': + resolution: {integrity: sha512-wvPXzJxzPgTqhyp1UskOx1hRTtdWxlyFD1cGWOxgLsMik0V9xKRgqKnMPv16Nk7L9xl6quQ6DuUHj9ID7L3oVw==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.7.39': - resolution: {integrity: sha512-NZwuS0mNJowH3e9bMttr7B1fB8bW5svW/yyySigv9qmV5VcQRNz1kMlCvrCLYRsa93JnARuiaBI6FazSeG8mpA==} + '@swc/core-win32-arm64-msvc@1.10.12': + resolution: {integrity: sha512-TUYzWuu1O7uyIcRfxdm6Wh1u+gNnrW5M1DUgDOGZLsyQzgc2Zjwfh2llLhuAIilvCVg5QiGbJlpibRYJ/8QGsg==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.7.39': - resolution: {integrity: sha512-qFmvv5UExbJPXhhvCVDBnjK5Duqxr048dlVB6ZCgGzbRxuarOlawCzzLK4N172230pzlAWGLgn9CWl3+N6zfHA==} + '@swc/core-win32-ia32-msvc@1.10.12': + resolution: {integrity: sha512-4Qrw+0Xt+Fe2rz4OJ/dEPMeUf/rtuFWWAj/e0vL7J5laUHirzxawLRE5DCJLQTarOiYR6mWnmadt9o3EKzV6Xg==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.7.39': - resolution: {integrity: sha512-o+5IMqgOtj9+BEOp16atTfBgCogVak9svhBpwsbcJQp67bQbxGYhAPPDW/hZ2rpSSF7UdzbY9wudoX9G4trcuQ==} + '@swc/core-win32-x64-msvc@1.10.12': + resolution: {integrity: sha512-YiloZXLW7rUxJpALwHXaGjVaAEn+ChoblG7/3esque+Y7QCyheoBUJp2DVM1EeVA43jBfZ8tvYF0liWd9Tpz1A==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.7.39': - resolution: {integrity: sha512-jns6VFeOT49uoTKLWIEfiQqJAlyqldNAt80kAr8f7a5YjX0zgnG3RBiLMpksx4Ka4SlK4O6TJ/lumIM3Trp82g==} + '@swc/core@1.10.12': + resolution: {integrity: sha512-+iUL0PYpPm6N9AdV1wvafakvCqFegQus1aoEDxgFsv3/uNVNIyRaupf/v/Zkp5hbep2EzhtoJR0aiJIzDbXWHg==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '*' @@ -361,24 +364,24 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/types@0.1.13': - resolution: {integrity: sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==} + '@swc/types@0.1.17': + resolution: {integrity: sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==} - '@szmarczak/http-timer@4.0.6': - resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} - engines: {node: '>=10'} + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@types/cacheable-request@6.0.3': - resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + '@types/chrome@0.0.300': + resolution: {integrity: sha512-vS5bUmNjMrbPut43Q8plS8GTAiJE+pBOxw1ovGC4LcwiGNKTithAH7TxhzHeX4wNq/FsaLj5KaW7riI0CgYjIg==} - '@types/chrome@0.0.279': - resolution: {integrity: sha512-wl0IxQ2OQiMazPZM5LimHQ7Jwd72/O8UvvzyptplXT2S4eUqXH5C0n8S+v8PtKhyX89p0igCPpNy3Bwksyk57g==} + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -398,8 +401,8 @@ packages: '@types/har-format@1.2.10': resolution: {integrity: sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg==} - '@types/http-cache-semantics@4.0.1': - resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} '@types/json-schema@7.0.11': resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} @@ -407,20 +410,14 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/keyv@3.1.4': - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - '@types/node@22.7.9': - resolution: {integrity: sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==} - - '@types/responselike@1.0.3': - resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + '@types/node@22.13.0': + resolution: {integrity: sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==} - '@types/tampermonkey@5.0.3': - resolution: {integrity: sha512-i8+x8ipoib8xAfho25oNTbILgrO665oxq5tNr3LvH5DaW5UOPsc88Fe1mTVTDwsux5LYOcd8Syb6q+s95x878Q==} + '@types/tampermonkey@5.0.4': + resolution: {integrity: sha512-HEJ0O5CkDZSwIgd9Zip4xM8o7gZC8zBmJuH1YEXNINIC+aCWEXD10pnpo3NQG5IWHx+Xr4fMSGq1jqeKXH2lpA==} '@types/webpack@5.28.5': resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==} @@ -434,76 +431,116 @@ packages: '@violentmonkey/types@0.2.0': resolution: {integrity: sha512-JRPtwhyodYKNkENciULg6v+ZtsoBR2ybYsA1KDvjw4JBzLNmvHixhd8TTl2s8eS1hU7MA1FU8kd1Ren9SCjxew==} - '@webassemblyjs/ast@1.12.1': - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - '@webassemblyjs/floating-point-hex-parser@1.11.6': - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - '@webassemblyjs/helper-api-error@1.11.6': - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - '@webassemblyjs/helper-buffer@1.12.1': - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - '@webassemblyjs/helper-numbers@1.11.6': - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - '@webassemblyjs/helper-wasm-bytecode@1.11.6': - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - '@webassemblyjs/helper-wasm-section@1.12.1': - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - '@webassemblyjs/ieee754@1.11.6': - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - '@webassemblyjs/leb128@1.11.6': - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - '@webassemblyjs/utf8@1.11.6': - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - '@webassemblyjs/wasm-edit@1.12.1': - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - '@webassemblyjs/wasm-gen@1.12.1': - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - '@webassemblyjs/wasm-opt@1.12.1': - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - '@webassemblyjs/wasm-parser@1.12.1': - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - '@webassemblyjs/wast-printer@1.12.1': - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - '@webpack-cli/configtest@2.1.1': - resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} - engines: {node: '>=14.15.0'} + '@webpack-cli/configtest@3.0.1': + resolution: {integrity: sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==} + engines: {node: '>=18.12.0'} peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x + webpack: ^5.82.0 + webpack-cli: 6.x.x - '@webpack-cli/info@2.0.2': - resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} - engines: {node: '>=14.15.0'} + '@webpack-cli/info@3.0.1': + resolution: {integrity: sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==} + engines: {node: '>=18.12.0'} peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x + webpack: ^5.82.0 + webpack-cli: 6.x.x - '@webpack-cli/serve@2.0.5': - resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} - engines: {node: '>=14.15.0'} + '@webpack-cli/serve@3.0.1': + resolution: {integrity: sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==} + engines: {node: '>=18.12.0'} peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x + webpack: ^5.82.0 + webpack-cli: 6.x.x webpack-dev-server: '*' peerDependenciesMeta: webpack-dev-server: optional: true + '@xhmikosr/archive-type@7.0.0': + resolution: {integrity: sha512-sIm84ZneCOJuiy3PpWR5bxkx3HaNt1pqaN+vncUBZIlPZCq8ASZH+hBVdu5H8znR7qYC6sKwx+ie2Q7qztJTxA==} + engines: {node: ^14.14.0 || >=16.0.0} + + '@xhmikosr/bin-check@7.0.3': + resolution: {integrity: sha512-4UnCLCs8DB+itHJVkqFp9Zjg+w/205/J2j2wNBsCEAm/BuBmtua2hhUOdAMQE47b1c7P9Xmddj0p+X1XVsfHsA==} + engines: {node: '>=18'} + + '@xhmikosr/bin-wrapper@13.0.5': + resolution: {integrity: sha512-DT2SAuHDeOw0G5bs7wZbQTbf4hd8pJ14tO0i4cWhRkIJfgRdKmMfkDilpaJ8uZyPA0NVRwasCNAmMJcWA67osw==} + engines: {node: '>=18'} + + '@xhmikosr/decompress-tar@8.0.1': + resolution: {integrity: sha512-dpEgs0cQKJ2xpIaGSO0hrzz3Kt8TQHYdizHsgDtLorWajuHJqxzot9Hbi0huRxJuAGG2qiHSQkwyvHHQtlE+fg==} + engines: {node: '>=18'} + + '@xhmikosr/decompress-tarbz2@8.0.1': + resolution: {integrity: sha512-OF+6DysDZP5YTDO8uHuGG6fMGZjc+HszFPBkVltjoje2Cf60hjBg/YP5OQndW1hfwVWOdP7f3CnJiPZHJUTtEg==} + engines: {node: '>=18'} + + '@xhmikosr/decompress-targz@8.0.1': + resolution: {integrity: sha512-mvy5AIDIZjQ2IagMI/wvauEiSNHhu/g65qpdM4EVoYHUJBAmkQWqcPJa8Xzi1aKVTmOA5xLJeDk7dqSjlHq8Mg==} + engines: {node: '>=18'} + + '@xhmikosr/decompress-unzip@7.0.0': + resolution: {integrity: sha512-GQMpzIpWTsNr6UZbISawsGI0hJ4KA/mz5nFq+cEoPs12UybAqZWKbyIaZZyLbJebKl5FkLpsGBkrplJdjvUoSQ==} + engines: {node: '>=18'} + + '@xhmikosr/decompress@10.0.1': + resolution: {integrity: sha512-6uHnEEt5jv9ro0CDzqWlFgPycdE+H+kbJnwyxgZregIMLQ7unQSCNVsYG255FoqU8cP46DyggI7F7LohzEl8Ag==} + engines: {node: '>=18'} + + '@xhmikosr/downloader@15.0.1': + resolution: {integrity: sha512-fiuFHf3Dt6pkX8HQrVBsK0uXtkgkVlhrZEh8b7VgoDqFf+zrgFBPyrwCqE/3nDwn3hLeNz+BsrS7q3mu13Lp1g==} + engines: {node: '>=18'} + + '@xhmikosr/os-filter-obj@3.0.0': + resolution: {integrity: sha512-siPY6BD5dQ2SZPl3I0OZBHL27ZqZvLEosObsZRQ1NUB8qcxegwt0T9eKtV96JMFQpIz1elhkzqOg4c/Ri6Dp9A==} + engines: {node: ^14.14.0 || >=16.0.0} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -514,28 +551,18 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - acorn-import-attributes@1.9.5: - resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} - peerDependencies: - acorn: ^8 - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true - - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true - acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} engines: {node: '>=0.4.0'} hasBin: true @@ -622,8 +649,8 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + arch@3.0.0: + resolution: {integrity: sha512-AmIAC+Wtm2AU8lGfTtHsw0Y9Qtftx2YXEEtiBP10xFUtMOA+sHHx6OAddyL52mUKh1vsXQ6/w1mVDptZCyUt4Q==} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -649,9 +676,15 @@ packages: atomically@2.0.3: resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} + b4a@1.6.7: + resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.5.4: + resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -663,10 +696,6 @@ packages: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} - bin-check@4.1.0: - resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==} - engines: {node: '>=4'} - bin-version-check@5.1.0: resolution: {integrity: sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g==} engines: {node: '>=12'} @@ -699,8 +728,8 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -713,6 +742,9 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -720,13 +752,13 @@ packages: resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} engines: {node: '>=12'} - cacheable-lookup@5.0.4: - resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} - engines: {node: '>=10.6.0'} + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} - cacheable-request@7.0.4: - resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} - engines: {node: '>=8'} + cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} @@ -739,8 +771,8 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - caniuse-lite@1.0.30001669: - resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} + caniuse-lite@1.0.30001692: + resolution: {integrity: sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -782,9 +814,6 @@ packages: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} - clone-response@1.0.3: - resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} - clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -812,9 +841,9 @@ packages: resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==} engines: {node: '>=8.0.0'} - commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -823,6 +852,10 @@ packages: resolution: {integrity: sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==} engines: {node: '>= 0.6.x'} + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} @@ -842,8 +875,8 @@ packages: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} engines: {'0': node >= 0.8} - concurrently@9.0.1: - resolution: {integrity: sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==} + concurrently@9.1.2: + resolution: {integrity: sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==} engines: {node: '>=18'} hasBin: true @@ -871,13 +904,14 @@ packages: resolution: {integrity: sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==} engines: {node: '>= 0.4.0'} - cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} - cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + crx3@1.1.3: resolution: {integrity: sha512-E4c3y/2ak83wAGN4h9Q8j3A2ii4bpRVf2vxinYYy+wJs8pyscMfEnKGzhgngZcRfOhUMr7/sxzy+lTZmQ/4KpQ==} engines: {node: '>=12'} @@ -965,6 +999,10 @@ packages: defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + defaults@3.0.0: + resolution: {integrity: sha512-RsqXDEAALjfRTro+IFNKpcPCt0/Cy2FqHSIlnomiJp9YGadpQnrtbRpSgN2+np21qHcIKiva4fiOQGjS9/qR/A==} + engines: {node: '>=18'} + defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -994,12 +1032,12 @@ packages: resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} engines: {node: '>=18'} - dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} - electron-to-chromium@1.5.42: - resolution: {integrity: sha512-gIfKavKDw1mhvic9nbzA5lZw8QSHpdMwLwXc0cWidQz9B15pDoDdDH4boIatuFfeoCatb3a/NGL6CYRVFxGZ9g==} + electron-to-chromium@1.5.80: + resolution: {integrity: sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==} emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -1018,8 +1056,8 @@ packages: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} - envinfo@7.8.1: - resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} + envinfo@7.14.0: + resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} engines: {node: '>=4'} hasBin: true @@ -1048,12 +1086,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - - eslint-config-prettier@9.1.0: - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + eslint-config-prettier@10.0.1: + resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} hasBin: true peerDependencies: eslint: '>=7.0.0' @@ -1071,8 +1105,8 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-scope@8.1.0: - resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -1083,8 +1117,8 @@ packages: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@4.1.0: - resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint@8.57.1: @@ -1093,8 +1127,8 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true - eslint@9.13.0: - resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==} + eslint@9.19.0: + resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1107,8 +1141,8 @@ packages: resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@10.2.0: - resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} espree@9.6.1: @@ -1151,10 +1185,6 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@0.7.0: - resolution: {integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==} - engines: {node: '>=4'} - execa@4.1.0: resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} engines: {node: '>=10'} @@ -1167,10 +1197,6 @@ packages: resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - executable@4.1.1: - resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} - engines: {node: '>=4'} - ext-list@2.2.2: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} @@ -1182,6 +1208,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -1220,17 +1249,17 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - file-type@17.1.6: - resolution: {integrity: sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + file-type@19.6.0: + resolution: {integrity: sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==} + engines: {node: '>=18'} filename-reserved-regex@3.0.0: resolution: {integrity: sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - filenamify@5.1.1: - resolution: {integrity: sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==} - engines: {node: '>=12.20'} + filenamify@6.0.0: + resolution: {integrity: sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==} + engines: {node: '>=16'} fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} @@ -1281,6 +1310,10 @@ packages: debug: optional: true + form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} @@ -1306,10 +1339,6 @@ packages: get-intrinsic@1.2.0: resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} - get-stream@3.0.0: - resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} - engines: {node: '>=4'} - get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} @@ -1318,6 +1347,10 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1345,17 +1378,17 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.11.0: - resolution: {integrity: sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==} + globals@15.14.0: + resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} engines: {node: '>=18'} globby@14.0.1: resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==} engines: {node: '>=18'} - got@11.8.6: - resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} - engines: {node: '>=10.19.0'} + got@13.0.0: + resolution: {integrity: sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==} + engines: {node: '>=16'} graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} @@ -1399,8 +1432,8 @@ packages: htmlparser2@8.0.1: resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==} - http-cache-semantics@4.1.0: - resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} http-proxy@1.18.1: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} @@ -1411,8 +1444,8 @@ packages: engines: {node: '>=12'} hasBin: true - http2-wrapper@1.0.3: - resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} engines: {node: '>=10.19.0'} https-proxy-agent@7.0.5: @@ -1456,8 +1489,8 @@ packages: immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} - immutable@4.2.2: - resolution: {integrity: sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==} + immutable@5.0.3: + resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -1490,6 +1523,9 @@ packages: resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + inspect-with-kind@1.0.5: + resolution: {integrity: sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==} + interpret@3.1.1: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} @@ -1572,10 +1608,6 @@ packages: resolution: {integrity: sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA==} engines: {node: '>=0.10.0'} - is-stream@1.1.0: - resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} - engines: {node: '>=0.10.0'} - is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -1584,6 +1616,10 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + is-utf8@0.2.1: resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} @@ -1700,17 +1736,18 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - lowercase-keys@2.0.0: - resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} - engines: {node: '>=8'} - - lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -1757,16 +1794,16 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - mimic-response@1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} - mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - mini-css-extract-plugin@2.9.1: - resolution: {integrity: sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ==} + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + mini-css-extract-plugin@2.9.2: + resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 @@ -1834,20 +1871,16 @@ packages: node-notifier@10.0.1: resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - - npm-run-path@2.0.2: - resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} - engines: {node: '>=4'} + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} @@ -1889,10 +1922,6 @@ packages: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} - os-filter-obj@2.0.0: - resolution: {integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==} - engines: {node: '>=4'} - os-locale@5.0.0: resolution: {integrity: sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==} engines: {node: '>=10'} @@ -1901,18 +1930,14 @@ packages: resolution: {integrity: sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==} engines: {node: '>= 0.4.0'} - p-cancelable@2.1.1: - resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} - engines: {node: '>=8'} + p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} p-defer@1.0.0: resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} engines: {node: '>=4'} - p-finally@1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - p-is-promise@2.1.0: resolution: {integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==} engines: {node: '>=6'} @@ -1969,10 +1994,6 @@ packages: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1992,8 +2013,8 @@ packages: resolution: {integrity: sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==} hasBin: true - peek-readable@5.0.0: - resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==} + peek-readable@5.3.1: + resolution: {integrity: sha512-GVlENSDW6KHaXcd9zkZltB7tCLosKB/4Hg0fqBJkAoBgYG2Tn1xtMgXtSUuMU9AK/gCm/tTdT8mgAeF4YNeeqw==} engines: {node: '>=14.16'} pend@1.2.0: @@ -2009,10 +2030,6 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - pino-abstract-transport@1.1.0: resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} @@ -2083,8 +2100,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.3.3: - resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} engines: {node: '>=14'} hasBin: true @@ -2111,9 +2128,6 @@ packages: protocol-buffers-schema@3.6.0: resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} - pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -2132,6 +2146,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} @@ -2152,18 +2169,10 @@ packages: readable-stream@2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - readable-stream@4.3.0: resolution: {integrity: sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - readable-web-to-node-stream@3.0.2: - resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==} - engines: {node: '>=8'} - real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} @@ -2221,8 +2230,9 @@ packages: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true - responselike@2.0.1: - resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} @@ -2256,133 +2266,133 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sass-embedded-android-arm64@1.80.4: - resolution: {integrity: sha512-htAuBmRvvN2d4smrqxZ6WBw4+OOURaoHzq5oZKqS/E35zYl5FHmrJzp4S5e26a0tEBcjca014tfb/uu9cQgnqA==} + sass-embedded-android-arm64@1.83.4: + resolution: {integrity: sha512-tgX4FzmbVqnQmD67ZxQDvI+qFNABrboOQgwsG05E5bA/US42zGajW9AxpECJYiMXVOHmg+d81ICbjb0fsVHskw==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [android] - sass-embedded-android-arm@1.80.4: - resolution: {integrity: sha512-iAZ7AiKTLGxQGTkZ37c2/7YC4lkbP1o3eP/K74YaF8O+qhKTLyLOwV7OcmzIywac7dqLcNuGqhFCmFqTYpewZw==} + sass-embedded-android-arm@1.83.4: + resolution: {integrity: sha512-9Z4pJAOgEkXa3VDY/o+U6l5XvV0mZTJcSl0l/mSPHihjAHSpLYnOW6+KOWeM8dxqrsqTYcd6COzhanI/a++5Gw==} engines: {node: '>=14.0.0'} cpu: [arm] os: [android] - sass-embedded-android-ia32@1.80.4: - resolution: {integrity: sha512-IIee89Jco8/ad2s/oRJTFqpLhBMzg0UXteJyZ5waZPZmkeSR/t9l67Ef1lLQVh9t9/fJ1ViTTiGYm/g/zu6UGw==} + sass-embedded-android-ia32@1.83.4: + resolution: {integrity: sha512-RsFOziFqPcfZXdFRULC4Ayzy9aK6R6FwQ411broCjlOBX+b0gurjRadkue3cfUEUR5mmy0KeCbp7zVKPLTK+5Q==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [android] - sass-embedded-android-riscv64@1.80.4: - resolution: {integrity: sha512-iJM2kqmWrOeE1aUyTp3uMAG86hyAqbpbOEV7tv828fUsMRDM4uHsHtmyp2n8P2Y0Y2FnLzJpvIm3SwDXGDzT1Q==} + sass-embedded-android-riscv64@1.83.4: + resolution: {integrity: sha512-EHwh0nmQarBBrMRU928eTZkFGx19k/XW2YwbPR4gBVdWLkbTgCA5aGe8hTE6/1zStyx++3nDGvTZ78+b/VvvLg==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [android] - sass-embedded-android-x64@1.80.4: - resolution: {integrity: sha512-vd8VrLvUoHeTcsDoIJesXLbQYZH26a8lAzXy6u4+vEuAwikF4WiXBDFrpqiv38QeD3faLeoPtksRsFbAdQqJAA==} + sass-embedded-android-x64@1.83.4: + resolution: {integrity: sha512-0PgQNuPWYy1jEOEPDVsV89KfqOsMLIp9CSbjBY7jRcwRhyVAcigqrUG6bDeNtojHUYKA1kU+Eh/85WxOHUOgBw==} engines: {node: '>=14.0.0'} cpu: [x64] os: [android] - sass-embedded-darwin-arm64@1.80.4: - resolution: {integrity: sha512-SJz7EM1i4NXa7CT/njIWMNYJ6CvbHljDIzUAZEe3V3u1KWl/eNO3pbWAnnDN62tBppwgWx/UdDUbAKowsT6Z8w==} + sass-embedded-darwin-arm64@1.83.4: + resolution: {integrity: sha512-rp2ywymWc3nymnSnAFG5R/8hvxWCsuhK3wOnD10IDlmNB7o4rzKby1c+2ZfpQGowlYGWsWWTgz8FW2qzmZsQRw==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [darwin] - sass-embedded-darwin-x64@1.80.4: - resolution: {integrity: sha512-J/QlBVO66DLtgALgCmM8rZ5zG0dBCIYW1eXIAnnDwC7vGkbAXMtO60M0O/2WNrAfmFfJz1hvKDLjlsxB2XGBLg==} + sass-embedded-darwin-x64@1.83.4: + resolution: {integrity: sha512-kLkN2lXz9PCgGfDS8Ev5YVcl/V2173L6379en/CaFuJJi7WiyPgBymW7hOmfCt4uO4R1y7CP2Uc08DRtZsBlAA==} engines: {node: '>=14.0.0'} cpu: [x64] os: [darwin] - sass-embedded-linux-arm64@1.80.4: - resolution: {integrity: sha512-hI6zQyrR6qJbvyEHfj8UGXNB8VyUa72jel46406AuxUnViA0RyZDSqXUF8vwVw/Hjv1LkA5ihK9dBmWNbLz1zQ==} + sass-embedded-linux-arm64@1.83.4: + resolution: {integrity: sha512-E0zjsZX2HgESwyqw31EHtI39DKa7RgK7nvIhIRco1d0QEw227WnoR9pjH3M/ZQy4gQj3GKilOFHM5Krs/omeIA==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - sass-embedded-linux-arm@1.80.4: - resolution: {integrity: sha512-vuaWhc4ebnaY1AgIWNvFv1snxmkWfvlCU7vnQf4qkn3R2Yyd2J+sjkO8o0NgMX8n5XRUSkAaYUJFCH+Nim6KgQ==} + sass-embedded-linux-arm@1.83.4: + resolution: {integrity: sha512-nL90ryxX2lNmFucr9jYUyHHx21AoAgdCL1O5Ltx2rKg2xTdytAGHYo2MT5S0LIeKLa/yKP/hjuSvrbICYNDvtA==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] - sass-embedded-linux-ia32@1.80.4: - resolution: {integrity: sha512-wcPExI8UbYrrJvGvo4v2Q+RktbCp44i3qZQ18hglPcVZOC1IzT9NPqZn0XmrqD4hmNbgsYR+picODkvqGw7iDA==} + sass-embedded-linux-ia32@1.83.4: + resolution: {integrity: sha512-ew5HpchSzgAYbQoriRh8QhlWn5Kw2nQ2jHoV9YLwGKe3fwwOWA0KDedssvDv7FWnY/FCqXyymhLd6Bxae4Xquw==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] - sass-embedded-linux-musl-arm64@1.80.4: - resolution: {integrity: sha512-y8slzQ8Jjkl+53mUDkp3zxcDrTXVVxzpa+6nKh5Ue8l1YU2KdVZG1v2PoDXxE6o99B5I2TVBG8i02IsdYoL8jQ==} + sass-embedded-linux-musl-arm64@1.83.4: + resolution: {integrity: sha512-IzMgalf6MZOxgp4AVCgsaWAFDP/IVWOrgVXxkyhw29fyAEoSWBJH4k87wyPhEtxSuzVHLxKNbc8k3UzdWmlBFg==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - sass-embedded-linux-musl-arm@1.80.4: - resolution: {integrity: sha512-HWo0G/9tuhj/uSEwte9KiDK2Xezrfh7nhdEH69ZIfOAqP5byTXL7o08TYagbvMAoljR43Vfna6MelV7NUX4WCw==} + sass-embedded-linux-musl-arm@1.83.4: + resolution: {integrity: sha512-0RrJRwMrmm+gG0VOB5b5Cjs7Sd+lhqpQJa6EJNEaZHljJokEfpE5GejZsGMRMIQLxEvVphZnnxl6sonCGFE/QQ==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] - sass-embedded-linux-musl-ia32@1.80.4: - resolution: {integrity: sha512-A2WSwnomho491iCeHh3c0YRympfAoJOKr+IyxalTcRH/pjENOWZWZUt00WE2q0tTpEd2V+goWvgS5pmUGewgmg==} + sass-embedded-linux-musl-ia32@1.83.4: + resolution: {integrity: sha512-LLb4lYbcxPzX4UaJymYXC+WwokxUlfTJEFUv5VF0OTuSsHAGNRs/rslPtzVBTvMeG9TtlOQDhku1F7G6iaDotA==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] - sass-embedded-linux-musl-riscv64@1.80.4: - resolution: {integrity: sha512-tYQsAHZLr2mnlJQBJ8Z/n/ySIFJ9JWpsUsoLe9fYgGDaBUfItdzUnj15CChRWld8vFe/I84hb7fbCtYXrI60Jg==} + sass-embedded-linux-musl-riscv64@1.83.4: + resolution: {integrity: sha512-zoKlPzD5Z13HKin1UGR74QkEy+kZEk2AkGX5RelRG494mi+IWwRuWCppXIovor9+BQb9eDWPYPoMVahwN5F7VA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - sass-embedded-linux-musl-x64@1.80.4: - resolution: {integrity: sha512-NZnr+SYbWlmXx0IaSQ8oF0jYkOULp9qKWMmmZQ1mxuGQ3z7tJqFhpH3M+hYkrFNeOq+GaH+nhHGOD4ZNBxeRkg==} + sass-embedded-linux-musl-x64@1.83.4: + resolution: {integrity: sha512-hB8+/PYhfEf2zTIcidO5Bpof9trK6WJjZ4T8g2MrxQh8REVtdPcgIkoxczRynqybf9+fbqbUwzXtiUao2GV+vQ==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - sass-embedded-linux-riscv64@1.80.4: - resolution: {integrity: sha512-h/BmU7QONa7ScvQztFp4Th4aSo3X+Olu3I+RYsaH9s7P683WT3f2w5zr+wwP1V4roM5eyKDCRJBuefT3Fkkkgw==} + sass-embedded-linux-riscv64@1.83.4: + resolution: {integrity: sha512-83fL4n+oeDJ0Y4KjASmZ9jHS1Vl9ESVQYHMhJE0i4xDi/P3BNarm2rsKljq/QtrwGpbqwn8ujzOu7DsNCMDSHA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - sass-embedded-linux-x64@1.80.4: - resolution: {integrity: sha512-aZbZFs/X9bEmzDiBEiV4IAsKEA0zrCM+s/u2OzvrX4GRvZFJ+/XRTTvf+RTm7mgvTFgfPwCkNGVECQZ1eHh+6A==} + sass-embedded-linux-x64@1.83.4: + resolution: {integrity: sha512-NlnGdvCmTD5PK+LKXlK3sAuxOgbRIEoZfnHvxd157imCm/s2SYF/R28D0DAAjEViyI8DovIWghgbcqwuertXsA==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - sass-embedded-win32-arm64@1.80.4: - resolution: {integrity: sha512-8JiatFi2VVFqCdJzKNDteaPC4KPmh8/giaVh7TyMcDhKjnvRLeu3v5V1egTMiwwpnQHuwzU3uqBlm/llVNR2Pw==} + sass-embedded-win32-arm64@1.83.4: + resolution: {integrity: sha512-J2BFKrEaeSrVazU2qTjyQdAk+MvbzJeTuCET0uAJEXSKtvQ3AzxvzndS7LqkDPbF32eXAHLw8GVpwcBwKbB3Uw==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [win32] - sass-embedded-win32-ia32@1.80.4: - resolution: {integrity: sha512-SodmTD6mjxEgoq44jWMibmBQvWkCfENK/70zp4qsztcBSOggg3nYUzwG0YpraClAMXpB1xOvzrArWu9/9fguAg==} + sass-embedded-win32-ia32@1.83.4: + resolution: {integrity: sha512-uPAe9T/5sANFhJS5dcfAOhOJy8/l2TRYG4r+UO3Wp4yhqbN7bggPvY9c7zMYS0OC8tU/bCvfYUDFHYMCl91FgA==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [win32] - sass-embedded-win32-x64@1.80.4: - resolution: {integrity: sha512-7+oRRwCCcnOmw152qDiC7x7SphYBo1eLB4KdyThO+7+rYRO8AftXO+kqBPTVSkM8kGp4wxCMF9auPpYBZbjsow==} + sass-embedded-win32-x64@1.83.4: + resolution: {integrity: sha512-C9fkDY0jKITdJFij4UbfPFswxoXN9O/Dr79v17fJnstVwtUojzVJWKHUXvF0Zg2LIR7TCc4ju3adejKFxj7ueA==} engines: {node: '>=14.0.0'} cpu: [x64] os: [win32] - sass-embedded@1.80.4: - resolution: {integrity: sha512-lPzKX5g79ZxohlPxh0pXTPFseWj9RfgYI0cPm14CH5ok77Ujuheq/DCp7RStvNDWS8RCQ8Ii6gJC/5WTkGyrhA==} + sass-embedded@1.83.4: + resolution: {integrity: sha512-Hf2burRA/y5PGxsg6jB9UpoK/xZ6g/pgrkOcdl6j+rRg1Zj8XhGKZ1MTysZGtTPUUmiiErqzkP5+Kzp95yv9GQ==} engines: {node: '>=16.0.0'} hasBin: true - sass-loader@16.0.2: - resolution: {integrity: sha512-Ll6iXZ1EYwYT19SqW4mSBb76vSSi8JgzElmzIerhEGgzB5hRjDQIWsPmuk1UrAXkR16KJHqVY0eH+5/uw9Tmfw==} + sass-loader@16.0.4: + resolution: {integrity: sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==} engines: {node: '>= 18.12.0'} peerDependencies: '@rspack/core': 0.x || 1.x @@ -2413,9 +2423,17 @@ packages: resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} engines: {node: '>= 12.13.0'} + schema-utils@4.3.0: + resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} + engines: {node: '>= 10.13.0'} + secure-compare@3.0.1: resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} + seek-bzip@2.0.0: + resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==} + hasBin: true + semver-regex@4.0.5: resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} engines: {node: '>=12'} @@ -2434,9 +2452,6 @@ packages: engines: {node: '>=10'} hasBin: true - serialize-javascript@6.0.1: - resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} - serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -2447,18 +2462,10 @@ packages: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} - shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} - shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} @@ -2525,6 +2532,9 @@ packages: split@1.0.1: resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} + streamx@2.21.1: + resolution: {integrity: sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2556,9 +2566,8 @@ packages: resolution: {integrity: sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A==} engines: {node: '>=12'} - strip-eof@1.0.0: - resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} - engines: {node: '>=0.10.0'} + strip-dirs@3.0.0: + resolution: {integrity: sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==} strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} @@ -2580,13 +2589,9 @@ packages: resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} engines: {node: '>=14.16'} - strip-outer@2.0.0: - resolution: {integrity: sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - strtok3@7.0.0: - resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==} - engines: {node: '>=14.16'} + strtok3@9.1.1: + resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==} + engines: {node: '>=16'} stubborn-fs@1.2.5: resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==} @@ -2613,12 +2618,23 @@ packages: '@swc/core': ^1.2.147 webpack: '>=2' + sync-child-process@1.0.2: + resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==} + engines: {node: '>=16.0.0'} + + sync-message-port@1.1.3: + resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==} + engines: {node: '>=16.0.0'} + tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - terser-webpack-plugin@5.3.10: - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + terser-webpack-plugin@5.3.11: + resolution: {integrity: sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -2633,11 +2649,14 @@ packages: uglify-js: optional: true - terser@5.27.2: - resolution: {integrity: sha512-sHXmLSkImesJ4p5apTeT63DsV4Obe1s37qT8qvwHRmVxKTBH7Rv9Wr26VcAMmLbmk9UliiwK8z+657NyJHHy/w==} + terser@5.37.0: + resolution: {integrity: sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==} engines: {node: '>=10'} hasBin: true + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -2662,18 +2681,14 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - token-types@5.0.1: - resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==} + token-types@6.0.0: + resolution: {integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==} engines: {node: '>=14.16'} tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - trim-repeated@2.0.0: - resolution: {integrity: sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==} - engines: {node: '>=12'} - tslib@2.4.1: resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} @@ -2696,13 +2711,20 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript@5.6.3: - resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} engines: {node: '>=14.17'} hasBin: true - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + uint8array-extras@1.4.0: + resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==} + engines: {node: '>=18'} + + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} @@ -2762,27 +2784,20 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - webpack-cli@5.1.4: - resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==} - engines: {node: '>=14.15.0'} + webpack-cli@6.0.1: + resolution: {integrity: sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==} + engines: {node: '>=18.12.0'} hasBin: true peerDependencies: - '@webpack-cli/generators': '*' - webpack: 5.x.x + webpack: ^5.82.0 webpack-bundle-analyzer: '*' webpack-dev-server: '*' peerDependenciesMeta: - '@webpack-cli/generators': - optional: true webpack-bundle-analyzer: optional: true webpack-dev-server: optional: true - webpack-merge@5.10.0: - resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} - engines: {node: '>=10.0.0'} - webpack-merge@6.0.1: resolution: {integrity: sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==} engines: {node: '>=18.0.0'} @@ -2791,8 +2806,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.95.0: - resolution: {integrity: sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==} + webpack@5.97.1: + resolution: {integrity: sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -2815,10 +2830,6 @@ packages: resolution: {integrity: sha512-zDRAqDSBudazdfM9zpiI30Fu9ve47htYXcGi3ln0wfKu2a7SmrT6F3VDoYONu//48V8Vz4TdCRNPjtvyRO3yBA==} hasBin: true - which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2828,9 +2839,6 @@ packages: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} - wildcard@2.0.0: - resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==} - wildcard@2.0.1: resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} @@ -2876,9 +2884,6 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -2893,6 +2898,10 @@ packages: yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yauzl@3.2.0: + resolution: {integrity: sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==} + engines: {node: '>=12'} + yazl@2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} @@ -2943,29 +2952,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@discoveryjs/json-ext@0.5.7': {} + '@discoveryjs/json-ext@0.6.3': {} '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.4.0(eslint@9.13.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.19.0)': dependencies: - eslint: 9.13.0 + eslint: 9.19.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.11.1': {} + '@eslint-community/regexpp@4.12.1': {} - '@eslint/config-array@0.18.0': + '@eslint/config-array@0.19.1': dependencies: - '@eslint/object-schema': 2.1.4 + '@eslint/object-schema': 2.1.5 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/core@0.7.0': {} + '@eslint/core@0.10.0': + dependencies: + '@types/json-schema': 7.0.15 '@eslint/eslintrc@2.1.4': dependencies: @@ -2981,11 +2992,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/eslintrc@3.1.0': + '@eslint/eslintrc@3.2.0': dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 10.2.0 + espree: 10.3.0 globals: 14.0.0 ignore: 5.2.4 import-fresh: 3.3.0 @@ -2997,21 +3008,22 @@ snapshots: '@eslint/js@8.57.1': {} - '@eslint/js@9.13.0': {} + '@eslint/js@9.19.0': {} - '@eslint/object-schema@2.1.4': {} + '@eslint/object-schema@2.1.5': {} - '@eslint/plugin-kit@0.2.0': + '@eslint/plugin-kit@0.2.5': dependencies: + '@eslint/core': 0.10.0 levn: 0.4.1 '@fluent/syntax@0.19.0': {} - '@humanfs/core@0.19.0': {} + '@humanfs/core@0.19.1': {} - '@humanfs/node@0.16.5': + '@humanfs/node@0.16.6': dependencies: - '@humanfs/core': 0.19.0 + '@humanfs/core': 0.19.1 '@humanwhocodes/retry': 0.3.1 '@humanwhocodes/config-array@0.13.0': @@ -3028,11 +3040,13 @@ snapshots: '@humanwhocodes/retry@0.3.1': {} + '@humanwhocodes/retry@0.4.1': {} + '@jridgewell/gen-mapping@0.3.2': dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.22 + '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/resolve-uri@3.1.0': {} @@ -3041,28 +3055,17 @@ snapshots: '@jridgewell/source-map@0.3.5': dependencies: '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.22 + '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/sourcemap-codec@1.4.14': {} - '@jridgewell/trace-mapping@0.3.22': + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 '@mdn/browser-compat-data@5.6.0': {} - '@mole-inc/bin-wrapper@8.0.1': - dependencies: - bin-check: 4.1.0 - bin-version-check: 5.1.0 - content-disposition: 0.5.4 - ext-name: 5.0.0 - file-type: 17.1.6 - filenamify: 5.1.1 - got: 11.8.6 - os-filter-obj: 2.0.0 - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3087,94 +3090,97 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@sindresorhus/is@4.6.0': {} + '@sec-ant/readable-stream@0.4.1': {} + + '@sindresorhus/is@5.6.0': {} '@sindresorhus/merge-streams@2.3.0': {} - '@swc/cli@0.4.0(@swc/core@1.7.39)': + '@swc/cli@0.6.0(@swc/core@1.10.12)': dependencies: - '@mole-inc/bin-wrapper': 8.0.1 - '@swc/core': 1.7.39 + '@swc/core': 1.10.12 '@swc/counter': 0.1.3 + '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 fast-glob: 3.3.2 minimatch: 9.0.3 piscina: 4.3.2 - semver: 7.5.4 + semver: 7.6.3 slash: 3.0.0 source-map: 0.7.4 - '@swc/core-darwin-arm64@1.7.39': + '@swc/core-darwin-arm64@1.10.12': optional: true - '@swc/core-darwin-x64@1.7.39': + '@swc/core-darwin-x64@1.10.12': optional: true - '@swc/core-linux-arm-gnueabihf@1.7.39': + '@swc/core-linux-arm-gnueabihf@1.10.12': optional: true - '@swc/core-linux-arm64-gnu@1.7.39': + '@swc/core-linux-arm64-gnu@1.10.12': optional: true - '@swc/core-linux-arm64-musl@1.7.39': + '@swc/core-linux-arm64-musl@1.10.12': optional: true - '@swc/core-linux-x64-gnu@1.7.39': + '@swc/core-linux-x64-gnu@1.10.12': optional: true - '@swc/core-linux-x64-musl@1.7.39': + '@swc/core-linux-x64-musl@1.10.12': optional: true - '@swc/core-win32-arm64-msvc@1.7.39': + '@swc/core-win32-arm64-msvc@1.10.12': optional: true - '@swc/core-win32-ia32-msvc@1.7.39': + '@swc/core-win32-ia32-msvc@1.10.12': optional: true - '@swc/core-win32-x64-msvc@1.7.39': + '@swc/core-win32-x64-msvc@1.10.12': optional: true - '@swc/core@1.7.39': + '@swc/core@1.10.12': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.13 + '@swc/types': 0.1.17 optionalDependencies: - '@swc/core-darwin-arm64': 1.7.39 - '@swc/core-darwin-x64': 1.7.39 - '@swc/core-linux-arm-gnueabihf': 1.7.39 - '@swc/core-linux-arm64-gnu': 1.7.39 - '@swc/core-linux-arm64-musl': 1.7.39 - '@swc/core-linux-x64-gnu': 1.7.39 - '@swc/core-linux-x64-musl': 1.7.39 - '@swc/core-win32-arm64-msvc': 1.7.39 - '@swc/core-win32-ia32-msvc': 1.7.39 - '@swc/core-win32-x64-msvc': 1.7.39 + '@swc/core-darwin-arm64': 1.10.12 + '@swc/core-darwin-x64': 1.10.12 + '@swc/core-linux-arm-gnueabihf': 1.10.12 + '@swc/core-linux-arm64-gnu': 1.10.12 + '@swc/core-linux-arm64-musl': 1.10.12 + '@swc/core-linux-x64-gnu': 1.10.12 + '@swc/core-linux-x64-musl': 1.10.12 + '@swc/core-win32-arm64-msvc': 1.10.12 + '@swc/core-win32-ia32-msvc': 1.10.12 + '@swc/core-win32-x64-msvc': 1.10.12 '@swc/counter@0.1.3': {} - '@swc/types@0.1.13': + '@swc/types@0.1.17': dependencies: '@swc/counter': 0.1.3 - '@szmarczak/http-timer@4.0.6': + '@szmarczak/http-timer@5.0.1': dependencies: defer-to-connect: 2.0.1 '@tokenizer/token@0.3.0': {} - '@types/cacheable-request@6.0.3': - dependencies: - '@types/http-cache-semantics': 4.0.1 - '@types/keyv': 3.1.4 - '@types/node': 22.7.9 - '@types/responselike': 1.0.3 - - '@types/chrome@0.0.279': + '@types/chrome@0.0.300': dependencies: '@types/filesystem': 0.0.32 '@types/har-format': 1.2.10 - '@types/estree@1.0.5': {} + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.6 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 '@types/estree@1.0.6': {} @@ -3190,33 +3196,25 @@ snapshots: '@types/har-format@1.2.10': {} - '@types/http-cache-semantics@4.0.1': {} + '@types/http-cache-semantics@4.0.4': {} '@types/json-schema@7.0.11': {} '@types/json-schema@7.0.15': {} - '@types/keyv@3.1.4': - dependencies: - '@types/node': 22.7.9 - '@types/minimatch@3.0.5': {} - '@types/node@22.7.9': + '@types/node@22.13.0': dependencies: - undici-types: 6.19.8 + undici-types: 6.20.0 - '@types/responselike@1.0.3': - dependencies: - '@types/node': 22.7.9 + '@types/tampermonkey@5.0.4': {} - '@types/tampermonkey@5.0.3': {} - - '@types/webpack@5.28.5(@swc/core@1.7.39)(webpack-cli@5.1.4)': + '@types/webpack@5.28.5(@swc/core@1.10.12)(webpack-cli@6.0.1)': dependencies: - '@types/node': 22.7.9 + '@types/node': 22.13.0 tapable: 2.2.1 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -3225,125 +3223,187 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.7.9 + '@types/node': 22.13.0 '@ungap/structured-clone@1.2.0': {} '@violentmonkey/types@0.2.0': {} - '@webassemblyjs/ast@1.12.1': + '@webassemblyjs/ast@1.14.1': dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/floating-point-hex-parser@1.11.6': {} + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - '@webassemblyjs/helper-api-error@1.11.6': {} + '@webassemblyjs/helper-api-error@1.13.2': {} - '@webassemblyjs/helper-buffer@1.12.1': {} + '@webassemblyjs/helper-buffer@1.14.1': {} - '@webassemblyjs/helper-numbers@1.11.6': + '@webassemblyjs/helper-numbers@1.13.2': dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 '@xtuc/long': 4.2.2 - '@webassemblyjs/helper-wasm-bytecode@1.11.6': {} + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} - '@webassemblyjs/helper-wasm-section@1.12.1': + '@webassemblyjs/helper-wasm-section@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/ieee754@1.11.6': + '@webassemblyjs/ieee754@1.13.2': dependencies: '@xtuc/ieee754': 1.2.0 - '@webassemblyjs/leb128@1.11.6': + '@webassemblyjs/leb128@1.13.2': dependencies: '@xtuc/long': 4.2.2 - '@webassemblyjs/utf8@1.11.6': {} + '@webassemblyjs/utf8@1.13.2': {} - '@webassemblyjs/wasm-edit@1.12.1': + '@webassemblyjs/wasm-edit@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 - '@webassemblyjs/wasm-gen@1.12.1': + '@webassemblyjs/wasm-gen@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 - '@webassemblyjs/wasm-opt@1.12.1': + '@webassemblyjs/wasm-opt@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wasm-parser@1.12.1': + '@webassemblyjs/wasm-parser@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 - '@webassemblyjs/wast-printer@1.12.1': + '@webassemblyjs/wast-printer@1.14.1': dependencies: - '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.95.0)': + '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': dependencies: - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.95.0) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.97.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.95.0)': + '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': dependencies: - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.95.0) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.97.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.95.0)': + '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': dependencies: - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.95.0) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.97.1) - '@xtuc/ieee754@1.2.0': {} + '@xhmikosr/archive-type@7.0.0': + dependencies: + file-type: 19.6.0 - '@xtuc/long@4.2.2': {} + '@xhmikosr/bin-check@7.0.3': + dependencies: + execa: 5.1.1 + isexe: 2.0.0 - abort-controller@3.0.0: + '@xhmikosr/bin-wrapper@13.0.5': dependencies: - event-target-shim: 5.0.1 + '@xhmikosr/bin-check': 7.0.3 + '@xhmikosr/downloader': 15.0.1 + '@xhmikosr/os-filter-obj': 3.0.0 + bin-version-check: 5.1.0 - acorn-import-attributes@1.9.5(acorn@8.11.3): + '@xhmikosr/decompress-tar@8.0.1': dependencies: - acorn: 8.11.3 + file-type: 19.6.0 + is-stream: 2.0.1 + tar-stream: 3.1.7 - acorn-jsx@5.3.2(acorn@8.12.1): + '@xhmikosr/decompress-tarbz2@8.0.1': dependencies: - acorn: 8.12.1 + '@xhmikosr/decompress-tar': 8.0.1 + file-type: 19.6.0 + is-stream: 2.0.1 + seek-bzip: 2.0.0 + unbzip2-stream: 1.4.3 - acorn@8.10.0: {} + '@xhmikosr/decompress-targz@8.0.1': + dependencies: + '@xhmikosr/decompress-tar': 8.0.1 + file-type: 19.6.0 + is-stream: 2.0.1 - acorn@8.11.3: {} + '@xhmikosr/decompress-unzip@7.0.0': + dependencies: + file-type: 19.6.0 + get-stream: 6.0.1 + yauzl: 3.2.0 + + '@xhmikosr/decompress@10.0.1': + dependencies: + '@xhmikosr/decompress-tar': 8.0.1 + '@xhmikosr/decompress-tarbz2': 8.0.1 + '@xhmikosr/decompress-targz': 8.0.1 + '@xhmikosr/decompress-unzip': 7.0.0 + graceful-fs: 4.2.11 + make-dir: 4.0.0 + strip-dirs: 3.0.0 + + '@xhmikosr/downloader@15.0.1': + dependencies: + '@xhmikosr/archive-type': 7.0.0 + '@xhmikosr/decompress': 10.0.1 + content-disposition: 0.5.4 + defaults: 3.0.0 + ext-name: 5.0.0 + file-type: 19.6.0 + filenamify: 6.0.0 + get-stream: 6.0.1 + got: 13.0.0 + + '@xhmikosr/os-filter-obj@3.0.0': + dependencies: + arch: 3.0.0 + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 acorn@8.12.1: {} + acorn@8.14.0: {} + addons-linter@7.1.0: dependencies: '@fluent/syntax': 0.19.0 @@ -3403,6 +3463,10 @@ snapshots: optionalDependencies: ajv: 8.12.0 + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv-keywords@3.5.2(ajv@6.12.6): dependencies: ajv: 6.12.6 @@ -3412,6 +3476,11 @@ snapshots: ajv: 8.12.0 fast-deep-equal: 3.1.3 + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -3451,7 +3520,7 @@ snapshots: ansi-styles@6.2.1: {} - arch@2.2.0: {} + arch@3.0.0: {} argparse@2.0.1: {} @@ -3472,8 +3541,13 @@ snapshots: stubborn-fs: 1.2.5 when-exit: 2.1.3 + b4a@1.6.7: {} + balanced-match@1.0.2: {} + bare-events@2.5.4: + optional: true + base64-js@1.5.1: {} basic-auth@2.0.1: @@ -3482,15 +3556,10 @@ snapshots: big-integer@1.6.52: {} - bin-check@4.1.0: - dependencies: - execa: 0.7.0 - executable: 4.1.1 - bin-version-check@5.1.0: dependencies: bin-version: 6.0.0 - semver: 7.5.4 + semver: 7.6.3 semver-truncate: 3.0.0 bin-version@6.0.0: @@ -3530,12 +3599,12 @@ snapshots: dependencies: fill-range: 7.0.1 - browserslist@4.24.2: + browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001669 - electron-to-chromium: 1.5.42 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) + caniuse-lite: 1.0.30001692 + electron-to-chromium: 1.5.80 + node-releases: 2.0.19 + update-browserslist-db: 1.1.1(browserslist@4.24.4) buffer-builder@0.2.0: {} @@ -3543,6 +3612,11 @@ snapshots: buffer-from@1.1.2: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + buffer@6.0.3: dependencies: base64-js: 1.5.1 @@ -3552,17 +3626,17 @@ snapshots: dependencies: run-applescript: 5.0.0 - cacheable-lookup@5.0.4: {} + cacheable-lookup@7.0.0: {} - cacheable-request@7.0.4: + cacheable-request@10.2.14: dependencies: - clone-response: 1.0.3 - get-stream: 5.2.0 - http-cache-semantics: 4.1.0 + '@types/http-cache-semantics': 4.0.4 + get-stream: 6.0.1 + http-cache-semantics: 4.1.1 keyv: 4.5.4 - lowercase-keys: 2.0.0 - normalize-url: 6.1.0 - responselike: 2.0.1 + mimic-response: 4.0.0 + normalize-url: 8.0.1 + responselike: 3.0.0 call-bind@1.0.2: dependencies: @@ -3573,7 +3647,7 @@ snapshots: camelcase@8.0.0: {} - caniuse-lite@1.0.30001669: {} + caniuse-lite@1.0.30001692: {} chalk@2.4.2: dependencies: @@ -3609,7 +3683,7 @@ snapshots: chrome-launcher@1.1.2: dependencies: - '@types/node': 22.7.9 + '@types/node': 22.13.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.1 @@ -3632,10 +3706,6 @@ snapshots: kind-of: 6.0.3 shallow-clone: 3.0.1 - clone-response@1.0.3: - dependencies: - mimic-response: 1.0.1 - clone@1.0.4: {} color-convert@1.9.3: @@ -3659,7 +3729,7 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 - commander@10.0.1: {} + commander@12.1.0: {} commander@2.20.3: {} @@ -3667,6 +3737,8 @@ snapshots: dependencies: graceful-readlink: 1.0.1 + commander@6.2.1: {} + commander@8.3.0: {} commander@9.5.0: {} @@ -3682,7 +3754,7 @@ snapshots: readable-stream: 2.3.7 typedarray: 0.0.6 - concurrently@9.0.1: + concurrently@9.1.2: dependencies: chalk: 4.1.2 lodash: 4.17.21 @@ -3708,7 +3780,7 @@ snapshots: dependencies: safe-buffer: 5.2.1 - copy-webpack-plugin@12.0.2(webpack@5.95.0): + copy-webpack-plugin@12.0.2(webpack@5.97.1): dependencies: fast-glob: 3.3.2 glob-parent: 6.0.2 @@ -3716,19 +3788,19 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) core-util-is@1.0.3: {} corser@2.0.1: {} - cross-spawn@5.1.0: + cross-spawn@7.0.3: dependencies: - lru-cache: 4.1.5 - shebang-command: 1.2.0 - which: 1.3.1 + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 - cross-spawn@7.0.3: + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 @@ -3740,7 +3812,7 @@ snapshots: pbf: 3.2.1 yazl: 2.5.1 - css-loader@7.1.2(webpack@5.95.0): + css-loader@7.1.2(webpack@5.97.1): dependencies: icss-utils: 5.1.0(postcss@8.4.35) postcss: 8.4.35 @@ -3751,7 +3823,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.5.4 optionalDependencies: - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) css-select@5.1.0: dependencies: @@ -3807,6 +3879,8 @@ snapshots: dependencies: clone: 1.0.4 + defaults@3.0.0: {} + defer-to-connect@2.0.1: {} define-lazy-prop@3.0.0: {} @@ -3837,9 +3911,9 @@ snapshots: dependencies: type-fest: 4.26.1 - dotenv@16.4.5: {} + dotenv@16.4.7: {} - electron-to-chromium@1.5.42: {} + electron-to-chromium@1.5.80: {} emoji-regex@10.4.0: {} @@ -3856,7 +3930,7 @@ snapshots: entities@4.4.0: {} - envinfo@7.8.1: {} + envinfo@7.14.0: {} error-ex@1.3.2: dependencies: @@ -3874,11 +3948,9 @@ snapshots: escape-string-regexp@4.0.0: {} - escape-string-regexp@5.0.0: {} - - eslint-config-prettier@9.1.0(eslint@9.13.0): + eslint-config-prettier@10.0.1(eslint@9.19.0): dependencies: - eslint: 9.13.0 + eslint: 9.19.0 eslint-plugin-no-unsanitized@4.0.2(eslint@8.57.1): dependencies: @@ -3894,7 +3966,7 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-scope@8.1.0: + eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -3903,12 +3975,12 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint-visitor-keys@4.1.0: {} + eslint-visitor-keys@4.2.0: {} eslint@8.57.1: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) - '@eslint-community/regexpp': 4.11.1 + '@eslint-community/regexpp': 4.12.1 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.57.1 '@humanwhocodes/config-array': 0.13.0 @@ -3917,7 +3989,7 @@ snapshots: '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 debug: 4.3.4 doctrine: 3.0.0 escape-string-regexp: 4.0.0 @@ -3948,28 +4020,28 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.13.0: + eslint@9.19.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0) - '@eslint-community/regexpp': 4.11.1 - '@eslint/config-array': 0.18.0 - '@eslint/core': 0.7.0 - '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.13.0 - '@eslint/plugin-kit': 0.2.0 - '@humanfs/node': 0.16.5 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.19.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.1 + '@eslint/core': 0.10.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.19.0 + '@eslint/plugin-kit': 0.2.5 + '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/retry': 0.4.1 '@types/estree': 1.0.6 '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 debug: 4.3.4 escape-string-regexp: 4.0.0 - eslint-scope: 8.1.0 - eslint-visitor-keys: 4.1.0 - espree: 10.2.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -3984,26 +4056,25 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.3 - text-table: 0.2.0 transitivePeerDependencies: - supports-color espree@10.1.0: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.1.0 + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 - espree@10.2.0: + espree@10.3.0: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.1.0 + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 espree@9.6.1: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -4028,19 +4099,9 @@ snapshots: events@3.3.0: {} - execa@0.7.0: - dependencies: - cross-spawn: 5.1.0 - get-stream: 3.0.0 - is-stream: 1.1.0 - npm-run-path: 2.0.2 - p-finally: 1.0.0 - signal-exit: 3.0.7 - strip-eof: 1.0.0 - execa@4.1.0: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 5.2.0 human-signals: 1.1.1 is-stream: 2.0.1 @@ -4052,7 +4113,7 @@ snapshots: execa@5.1.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 6.0.1 human-signals: 2.1.0 is-stream: 2.0.1 @@ -4064,7 +4125,7 @@ snapshots: execa@7.2.0: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 6.0.1 human-signals: 4.3.1 is-stream: 3.0.0 @@ -4074,10 +4135,6 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 3.0.0 - executable@4.1.1: - dependencies: - pify: 2.3.0 - ext-list@2.2.2: dependencies: mime-db: 1.52.0 @@ -4089,6 +4146,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-fifo@1.3.2: {} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4125,19 +4184,18 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-type@17.1.6: + file-type@19.6.0: dependencies: - readable-web-to-node-stream: 3.0.2 - strtok3: 7.0.0 - token-types: 5.0.1 + get-stream: 9.0.1 + strtok3: 9.1.1 + token-types: 6.0.0 + uint8array-extras: 1.4.0 filename-reserved-regex@3.0.0: {} - filenamify@5.1.1: + filenamify@6.0.0: dependencies: filename-reserved-regex: 3.0.0 - strip-outer: 2.0.0 - trim-repeated: 2.0.0 fill-range@7.0.1: dependencies: @@ -4183,6 +4241,8 @@ snapshots: follow-redirects@1.15.2: {} + form-data-encoder@2.1.4: {} + fs-extra@11.2.0: dependencies: graceful-fs: 4.2.11 @@ -4212,14 +4272,17 @@ snapshots: has: 1.0.3 has-symbols: 1.0.3 - get-stream@3.0.0: {} - get-stream@5.2.0: dependencies: pump: 3.0.0 get-stream@6.0.1: {} + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -4249,7 +4312,7 @@ snapshots: globals@14.0.0: {} - globals@15.11.0: {} + globals@15.14.0: {} globby@14.0.1: dependencies: @@ -4260,19 +4323,19 @@ snapshots: slash: 5.1.0 unicorn-magic: 0.1.0 - got@11.8.6: + got@13.0.0: dependencies: - '@sindresorhus/is': 4.6.0 - '@szmarczak/http-timer': 4.0.6 - '@types/cacheable-request': 6.0.3 - '@types/responselike': 1.0.3 - cacheable-lookup: 5.0.4 - cacheable-request: 7.0.4 + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 decompress-response: 6.0.0 - http2-wrapper: 1.0.3 - lowercase-keys: 2.0.0 - p-cancelable: 2.1.1 - responselike: 2.0.1 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 graceful-fs@4.2.10: {} @@ -4307,7 +4370,7 @@ snapshots: domutils: 3.0.1 entities: 4.4.0 - http-cache-semantics@4.1.0: {} + http-cache-semantics@4.1.1: {} http-proxy@1.18.1: dependencies: @@ -4336,7 +4399,7 @@ snapshots: - debug - supports-color - http2-wrapper@1.0.3: + http2-wrapper@2.2.1: dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 @@ -4372,7 +4435,7 @@ snapshots: immediate@3.0.6: {} - immutable@4.2.2: {} + immutable@5.0.3: {} import-fresh@3.3.0: dependencies: @@ -4399,6 +4462,10 @@ snapshots: ini@4.1.3: {} + inspect-with-kind@1.0.5: + dependencies: + kind-of: 6.0.3 + interpret@3.1.1: {} invert-kv@3.0.1: {} @@ -4452,12 +4519,12 @@ snapshots: is-relative@0.1.3: {} - is-stream@1.1.0: {} - is-stream@2.0.1: {} is-stream@3.0.0: {} + is-stream@4.0.1: {} + is-utf8@0.2.1: {} is-wsl@2.2.0: @@ -4476,7 +4543,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.7.9 + '@types/node': 22.13.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -4565,17 +4632,16 @@ snapshots: lodash@4.17.21: {} - lowercase-keys@2.0.0: {} - - lru-cache@4.1.5: - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 + lowercase-keys@3.0.0: {} lru-cache@6.0.0: dependencies: yallist: 4.0.0 + make-dir@4.0.0: + dependencies: + semver: 7.6.3 + make-error@1.3.6: {} map-age-cleaner@0.1.3: @@ -4611,15 +4677,15 @@ snapshots: mimic-fn@4.0.0: {} - mimic-response@1.0.1: {} - mimic-response@3.1.0: {} - mini-css-extract-plugin@2.9.1(webpack@5.95.0): + mimic-response@4.0.0: {} + + mini-css-extract-plugin@2.9.2(webpack@5.97.1): dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) minimatch@3.1.2: dependencies: @@ -4676,20 +4742,16 @@ snapshots: dependencies: growly: 1.3.0 is-wsl: 2.2.0 - semver: 7.5.4 + semver: 7.6.3 shellwords: 0.1.1 uuid: 8.3.2 which: 2.0.2 - node-releases@2.0.18: {} + node-releases@2.0.19: {} normalize-path@3.0.0: {} - normalize-url@6.1.0: {} - - npm-run-path@2.0.2: - dependencies: - path-key: 2.0.1 + normalize-url@8.0.1: {} npm-run-path@4.0.1: dependencies: @@ -4737,10 +4799,6 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - os-filter-obj@2.0.0: - dependencies: - arch: 2.2.0 - os-locale@5.0.0: dependencies: execa: 4.1.0 @@ -4749,12 +4807,10 @@ snapshots: os-shim@0.1.3: {} - p-cancelable@2.1.1: {} + p-cancelable@3.0.0: {} p-defer@1.0.0: {} - p-finally@1.0.0: {} - p-is-promise@2.1.0: {} p-limit@2.3.0: @@ -4811,8 +4867,6 @@ snapshots: path-is-absolute@1.0.1: {} - path-key@2.0.1: {} - path-key@3.1.1: {} path-key@4.0.0: {} @@ -4826,7 +4880,7 @@ snapshots: ieee754: 1.2.1 resolve-protobuf-schema: 2.1.0 - peek-readable@5.0.0: {} + peek-readable@5.3.1: {} pend@1.2.0: {} @@ -4836,8 +4890,6 @@ snapshots: picomatch@2.3.1: {} - pify@2.3.0: {} - pino-abstract-transport@1.1.0: dependencies: readable-stream: 4.3.0 @@ -4932,7 +4984,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.3.3: {} + prettier@3.4.2: {} process-nextick-args@2.0.1: {} @@ -4950,8 +5002,6 @@ snapshots: protocol-buffers-schema@3.6.0: {} - pseudomap@1.0.2: {} - pump@3.0.0: dependencies: end-of-stream: 1.4.4 @@ -4969,6 +5019,8 @@ snapshots: queue-microtask@1.2.3: {} + queue-tick@1.0.1: {} + queue@6.0.2: dependencies: inherits: 2.0.4 @@ -4998,12 +5050,6 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - readable-stream@4.3.0: dependencies: abort-controller: 3.0.0 @@ -5011,10 +5057,6 @@ snapshots: events: 3.3.0 process: 0.11.10 - readable-web-to-node-stream@3.0.2: - dependencies: - readable-stream: 3.6.2 - real-require@0.2.0: {} rechoir@0.8.0: @@ -5062,9 +5104,9 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - responselike@2.0.1: + responselike@3.0.0: dependencies: - lowercase-keys: 2.0.0 + lowercase-keys: 3.0.0 reusify@1.0.4: {} @@ -5092,109 +5134,110 @@ snapshots: safer-buffer@2.1.2: {} - sass-embedded-android-arm64@1.80.4: + sass-embedded-android-arm64@1.83.4: optional: true - sass-embedded-android-arm@1.80.4: + sass-embedded-android-arm@1.83.4: optional: true - sass-embedded-android-ia32@1.80.4: + sass-embedded-android-ia32@1.83.4: optional: true - sass-embedded-android-riscv64@1.80.4: + sass-embedded-android-riscv64@1.83.4: optional: true - sass-embedded-android-x64@1.80.4: + sass-embedded-android-x64@1.83.4: optional: true - sass-embedded-darwin-arm64@1.80.4: + sass-embedded-darwin-arm64@1.83.4: optional: true - sass-embedded-darwin-x64@1.80.4: + sass-embedded-darwin-x64@1.83.4: optional: true - sass-embedded-linux-arm64@1.80.4: + sass-embedded-linux-arm64@1.83.4: optional: true - sass-embedded-linux-arm@1.80.4: + sass-embedded-linux-arm@1.83.4: optional: true - sass-embedded-linux-ia32@1.80.4: + sass-embedded-linux-ia32@1.83.4: optional: true - sass-embedded-linux-musl-arm64@1.80.4: + sass-embedded-linux-musl-arm64@1.83.4: optional: true - sass-embedded-linux-musl-arm@1.80.4: + sass-embedded-linux-musl-arm@1.83.4: optional: true - sass-embedded-linux-musl-ia32@1.80.4: + sass-embedded-linux-musl-ia32@1.83.4: optional: true - sass-embedded-linux-musl-riscv64@1.80.4: + sass-embedded-linux-musl-riscv64@1.83.4: optional: true - sass-embedded-linux-musl-x64@1.80.4: + sass-embedded-linux-musl-x64@1.83.4: optional: true - sass-embedded-linux-riscv64@1.80.4: + sass-embedded-linux-riscv64@1.83.4: optional: true - sass-embedded-linux-x64@1.80.4: + sass-embedded-linux-x64@1.83.4: optional: true - sass-embedded-win32-arm64@1.80.4: + sass-embedded-win32-arm64@1.83.4: optional: true - sass-embedded-win32-ia32@1.80.4: + sass-embedded-win32-ia32@1.83.4: optional: true - sass-embedded-win32-x64@1.80.4: + sass-embedded-win32-x64@1.83.4: optional: true - sass-embedded@1.80.4: + sass-embedded@1.83.4: dependencies: '@bufbuild/protobuf': 2.2.0 buffer-builder: 0.2.0 colorjs.io: 0.5.2 - immutable: 4.2.2 + immutable: 5.0.3 rxjs: 7.8.1 supports-color: 8.1.1 + sync-child-process: 1.0.2 varint: 6.0.0 optionalDependencies: - sass-embedded-android-arm: 1.80.4 - sass-embedded-android-arm64: 1.80.4 - sass-embedded-android-ia32: 1.80.4 - sass-embedded-android-riscv64: 1.80.4 - sass-embedded-android-x64: 1.80.4 - sass-embedded-darwin-arm64: 1.80.4 - sass-embedded-darwin-x64: 1.80.4 - sass-embedded-linux-arm: 1.80.4 - sass-embedded-linux-arm64: 1.80.4 - sass-embedded-linux-ia32: 1.80.4 - sass-embedded-linux-musl-arm: 1.80.4 - sass-embedded-linux-musl-arm64: 1.80.4 - sass-embedded-linux-musl-ia32: 1.80.4 - sass-embedded-linux-musl-riscv64: 1.80.4 - sass-embedded-linux-musl-x64: 1.80.4 - sass-embedded-linux-riscv64: 1.80.4 - sass-embedded-linux-x64: 1.80.4 - sass-embedded-win32-arm64: 1.80.4 - sass-embedded-win32-ia32: 1.80.4 - sass-embedded-win32-x64: 1.80.4 - - sass-loader@16.0.2(sass-embedded@1.80.4)(webpack@5.95.0): + sass-embedded-android-arm: 1.83.4 + sass-embedded-android-arm64: 1.83.4 + sass-embedded-android-ia32: 1.83.4 + sass-embedded-android-riscv64: 1.83.4 + sass-embedded-android-x64: 1.83.4 + sass-embedded-darwin-arm64: 1.83.4 + sass-embedded-darwin-x64: 1.83.4 + sass-embedded-linux-arm: 1.83.4 + sass-embedded-linux-arm64: 1.83.4 + sass-embedded-linux-ia32: 1.83.4 + sass-embedded-linux-musl-arm: 1.83.4 + sass-embedded-linux-musl-arm64: 1.83.4 + sass-embedded-linux-musl-ia32: 1.83.4 + sass-embedded-linux-musl-riscv64: 1.83.4 + sass-embedded-linux-musl-x64: 1.83.4 + sass-embedded-linux-riscv64: 1.83.4 + sass-embedded-linux-x64: 1.83.4 + sass-embedded-win32-arm64: 1.83.4 + sass-embedded-win32-ia32: 1.83.4 + sass-embedded-win32-x64: 1.83.4 + + sass-loader@16.0.4(sass-embedded@1.83.4)(webpack@5.97.1): dependencies: neo-async: 2.6.2 optionalDependencies: - sass-embedded: 1.80.4 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + sass-embedded: 1.83.4 + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) sax@1.2.4: {} schema-utils@3.3.0: dependencies: - '@types/json-schema': 7.0.11 + '@types/json-schema': 7.0.15 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) @@ -5205,13 +5248,24 @@ snapshots: ajv-formats: 2.1.1(ajv@8.12.0) ajv-keywords: 5.1.0(ajv@8.12.0) + schema-utils@4.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + secure-compare@3.0.1: {} + seek-bzip@2.0.0: + dependencies: + commander: 6.2.1 + semver-regex@4.0.5: {} semver-truncate@3.0.0: dependencies: - semver: 7.5.4 + semver: 7.6.3 semver@7.5.4: dependencies: @@ -5219,10 +5273,6 @@ snapshots: semver@7.6.3: {} - serialize-javascript@6.0.1: - dependencies: - randombytes: 2.1.0 - serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -5233,16 +5283,10 @@ snapshots: dependencies: kind-of: 6.0.3 - shebang-command@1.2.0: - dependencies: - shebang-regex: 1.0.0 - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - shebang-regex@1.0.0: {} - shebang-regex@3.0.0: {} shell-quote@1.7.3: {} @@ -5301,6 +5345,14 @@ snapshots: dependencies: through: 2.3.8 + streamx@2.21.1: + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + text-decoder: 1.2.3 + optionalDependencies: + bare-events: 2.5.4 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -5336,7 +5388,10 @@ snapshots: strip-bom@5.0.0: {} - strip-eof@1.0.0: {} + strip-dirs@3.0.0: + dependencies: + inspect-with-kind: 1.0.5 + is-plain-obj: 1.1.0 strip-final-newline@2.0.0: {} @@ -5348,12 +5403,10 @@ snapshots: strip-json-comments@5.0.1: {} - strip-outer@2.0.0: {} - - strtok3@7.0.0: + strtok3@9.1.1: dependencies: '@tokenizer/token': 0.3.0 - peek-readable: 5.0.0 + peek-readable: 5.3.1 stubborn-fs@1.2.5: {} @@ -5371,32 +5424,48 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swc-loader@0.2.6(@swc/core@1.7.39)(webpack@5.95.0): + swc-loader@0.2.6(@swc/core@1.10.12)(webpack@5.97.1): dependencies: - '@swc/core': 1.7.39 + '@swc/core': 1.10.12 '@swc/counter': 0.1.3 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + + sync-child-process@1.0.2: + dependencies: + sync-message-port: 1.1.3 + + sync-message-port@1.1.3: {} tapable@2.2.1: {} - terser-webpack-plugin@5.3.10(@swc/core@1.7.39)(webpack@5.95.0): + tar-stream@3.1.7: + dependencies: + b4a: 1.6.7 + fast-fifo: 1.3.2 + streamx: 2.21.1 + + terser-webpack-plugin@5.3.11(@swc/core@1.10.12)(webpack@5.97.1): dependencies: - '@jridgewell/trace-mapping': 0.3.22 + '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.1 - terser: 5.27.2 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) + schema-utils: 4.3.0 + serialize-javascript: 6.0.2 + terser: 5.37.0 + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) optionalDependencies: - '@swc/core': 1.7.39 + '@swc/core': 1.10.12 - terser@5.27.2: + terser@5.37.0: dependencies: '@jridgewell/source-map': 0.3.5 - acorn: 8.10.0 + acorn: 8.12.1 commander: 2.20.3 source-map-support: 0.5.21 + text-decoder@1.2.3: + dependencies: + b4a: 1.6.7 + text-table@0.2.0: {} thread-stream@2.3.0: @@ -5417,17 +5486,13 @@ snapshots: dependencies: is-number: 7.0.0 - token-types@5.0.1: + token-types@6.0.0: dependencies: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 tree-kill@1.2.2: {} - trim-repeated@2.0.0: - dependencies: - escape-string-regexp: 5.0.0 - tslib@2.4.1: {} type-check@0.4.0: @@ -5442,9 +5507,16 @@ snapshots: typedarray@0.0.6: {} - typescript@5.6.3: {} + typescript@5.7.3: {} - undici-types@6.19.8: {} + uint8array-extras@1.4.0: {} + + unbzip2-stream@1.4.3: + dependencies: + buffer: 5.7.1 + through: 2.3.8 + + undici-types@6.20.0: {} unicorn-magic@0.1.0: {} @@ -5458,9 +5530,9 @@ snapshots: upath@2.0.1: {} - update-browserslist-db@1.1.1(browserslist@4.24.2): + update-browserslist-db@1.1.1(browserslist@4.24.4): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.4 escalade: 3.2.0 picocolors: 1.1.0 @@ -5537,28 +5609,22 @@ snapshots: - supports-color - utf-8-validate - webpack-cli@5.1.4(webpack@5.95.0): + webpack-cli@6.0.1(webpack@5.97.1): dependencies: - '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.95.0) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.95.0) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.95.0) + '@discoveryjs/json-ext': 0.6.3 + '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.97.1) + '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.97.1) + '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.97.1) colorette: 2.0.19 - commander: 10.0.1 + commander: 12.1.0 cross-spawn: 7.0.3 - envinfo: 7.8.1 + envinfo: 7.14.0 fastest-levenshtein: 1.0.16 import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4) - webpack-merge: 5.10.0 - - webpack-merge@5.10.0: - dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.0 + webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack-merge: 6.0.1 webpack-merge@6.0.1: dependencies: @@ -5568,15 +5634,15 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.95.0(@swc/core@1.7.39)(webpack-cli@5.1.4): + webpack@5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1): dependencies: - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) - browserslist: 4.24.2 + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.6 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.14.0 + browserslist: 4.24.4 chrome-trace-event: 1.0.3 enhanced-resolve: 5.17.1 es-module-lexer: 1.3.0 @@ -5590,11 +5656,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.7.39)(webpack@5.95.0) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.12)(webpack@5.97.1) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack@5.95.0) + webpack-cli: 6.0.1(webpack@5.97.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -5613,10 +5679,6 @@ snapshots: is-absolute: 0.1.7 isexe: 1.1.2 - which@1.3.1: - dependencies: - isexe: 2.0.0 - which@2.0.2: dependencies: isexe: 2.0.0 @@ -5625,8 +5687,6 @@ snapshots: dependencies: string-width: 7.2.0 - wildcard@2.0.0: {} - wildcard@2.0.1: {} winreg@0.0.12: {} @@ -5658,8 +5718,6 @@ snapshots: y18n@5.0.8: {} - yallist@2.1.2: {} - yallist@4.0.0: {} yargs-parser@21.1.1: {} @@ -5679,6 +5737,11 @@ snapshots: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 + yauzl@3.2.0: + dependencies: + buffer-crc32: 0.2.13 + pend: 1.2.0 + yazl@2.5.1: dependencies: buffer-crc32: 0.2.13 diff --git a/src/UserJS/main.js b/src/UserJS/main.js index 8b98902..f0b7428 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -18,9 +18,16 @@ const err = (...msg) => { 'color: rgb(249, 24, 128);', ...msg ); + const a = typeof alert !== 'undefined' && alert; for (const ex of msg) { - if (typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined') { - alert(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); + // typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined' + // const isE = Object.prototype.toString.call(ex).includes('Error'); + // if (isE && 'cause' in ex && a) { + // a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); + // } + // const isO = Object.prototype.toString.call(ex).includes('Object'); + if (typeof ex === 'object' && 'cause' in ex && a) { + a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); } } }; @@ -48,14 +55,34 @@ const log = (...msg) => { * @type { import("../typings/types.d.ts").config } */ let cfg = {}; -// let ghMsg = null; + +/** + * https://github.com/zloirock/core-js/blob/master/packages/core-js/internals/global-this.js + * @returns {typeof globalThis} + */ +function globalWin() { + const check = function (it) { + return it && it.Math === Math && it; + }; + return ( + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + check(typeof self == 'object' && self) || + check(typeof this == 'object' && this) || + (function () { + return this; + })() || + Function('return this')() + ); +} /** @type { import("../typings/UserJS.d.ts").safeSelf } */ function safeSelf() { if (userjs.safeSelf) { return userjs.safeSelf; } - const g = globalThis; + const g = globalWin(); + /** @type { import("../typings/UserJS.d.ts").safeHandles } */ const safe = { XMLHttpRequest: g.XMLHttpRequest, createElement: g.document.createElement.bind(g.document), @@ -63,17 +90,49 @@ function safeSelf() { createTextNode: g.document.createTextNode.bind(g.document), setTimeout: g.setTimeout, clearTimeout: g.clearTimeout, - trustedTypes: g.trustedTypes + navigator: g.navigator, + scheduler: { + postTask(callback, options) { + if ('scheduler' in g && 'postTask' in g.scheduler) { + return g.scheduler.postTask(callback, options); + } + + options = Object.assign({}, options); + + if (options.delay === undefined) options.delay = 0; + options.delay = Number(options.delay); + if (options.delay < 0) { + return Promise.reject(new TypeError('"delay" must be a positive number.')); + } + return new Promise((resolve) => { + g.setTimeout(() => { + resolve(callback()); + }, options.delay); + }); + }, + yield() { + if ('scheduler' in g && 'yield' in g.scheduler) { + scheduler.yield(); + return g.scheduler.yield(); + } + return new Promise((resolve) => { + g.setTimeout(resolve, 0); + }); + } + } }; userjs.safeSelf = safe; - return safe; + return userjs.safeSelf; } const BLANK_PAGE = 'about:blank'; // Lets highlight me :) const authorID = 166061; -// Some UserJS I personally enjoy +/** + * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{{id}}` + */ const goodUserJS = [ + 12179, 423001, 376510, 23840, @@ -83,10 +142,10 @@ const goodUserJS = [ 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' ]; -// Remove UserJS from banned accounts -const badUserJS = [ - 478597, // Authors have been banned from GreasyFork -]; +/** + * Remove UserJS from banned accounts + */ +const badUserJS = [478597]; // Unsupport webpages for each engine const engineUnsupported = { greasyfork: ['pornhub.com'], @@ -95,18 +154,28 @@ const engineUnsupported = { github: [] }; const getUAData = () => { - if (typeof userjs.isMobile !== 'undefined') { + if (userjs.isMobile !== undefined) { return userjs.isMobile; } + // if (typeof userjs.isMobile !== 'undefined') { + // return userjs.isMobile; + // } try { - const { platform, mobile } = navigator.userAgentData ?? {}; - userjs.isMobile = - /Mobile|Tablet/.test(navigator.userAgent ?? '') || - mobile || - /Android|Apple/.test(platform ?? ''); + const { navigator } = safeSelf(); + if (navigator) { + const { userAgent, userAgentData } = navigator; + const { platform, mobile } = userAgentData ? Object(userAgentData) : {}; + userjs.isMobile = + /Mobile|Tablet/.test(userAgent ? String(userAgent) : '') || + Boolean(mobile) || + /Android|Apple/.test(platform ? String(platform) : ''); + } else { + userjs.isMobile = false; + } } catch (ex) { - err({ cause: 'getUAData', message: ex.message }); userjs.isMobile = false; + ex.cause = 'getUAData'; + err(ex); } return userjs.isMobile; }; @@ -137,23 +206,25 @@ const DEFAULT_CONFIG = { { enabled: true, name: 'greasyfork', - query: encodeURIComponent('https://greasyfork.org/scripts/by-site/{host}.json?language=all'), + query: encodeURIComponent('https://greasyfork.org/scripts/by-site/{host}.json?language=all') }, { enabled: false, name: 'sleazyfork', - query: encodeURIComponent('https://sleazyfork.org/scripts/by-site/{host}.json?language=all'), + query: encodeURIComponent('https://sleazyfork.org/scripts/by-site/{host}.json?language=all') }, { enabled: false, name: 'openuserjs', - query: encodeURIComponent('https://openuserjs.org/?q={host}'), + query: encodeURIComponent('https://openuserjs.org/?q={host}') }, { enabled: false, name: 'github', token: '', - query: encodeURIComponent('https://api.github.com/search/code?q="// ==UserScript=="+{host}+ "// ==/UserScript=="+in:file+language:js&per_page=30') + query: encodeURIComponent( + 'https://api.github.com/search/code?q="// ==UserScript=="+{host}+ "// ==/UserScript=="+in:file+language:js&per_page=30' + ) } ], theme: { @@ -188,12 +259,11 @@ const DEFAULT_CONFIG = { //#region i18n class i18nHandler { constructor() { - /** - * @type { string[] } - */ + /** @type { string[] } */ this.cache = []; - const languages = navigator.languages ?? []; + const { navigator } = safeSelf(); + const { languages } = navigator; for (const nlang of languages) { const lg = nlang.split('-')[0]; if (this.cache.indexOf(lg) === -1) { @@ -207,12 +277,15 @@ class i18nHandler { } } toDate(str = '') { + const { navigator } = safeSelf(); return new Intl.DateTimeFormat(navigator.language).format(new Date(str)); } toNumber(number) { + const { navigator } = safeSelf(); return new Intl.NumberFormat(navigator.language).format(number); } i18n$(...keys) { + const { navigator } = safeSelf(); const current = navigator.language.split('-')[0] ?? 'en'; const list = translations[cfg.language] ?? translations[current]; const arr = []; @@ -226,6 +299,7 @@ const language = new i18nHandler(); const { i18n$ } = language; //#endregion // #region Utilities +const union = (...arr) => [...new Set(arr.flat())]; /** * @type { import("../typings/types.d.ts").qs } */ @@ -248,21 +322,10 @@ const qsA = (selectors, root) => { } return []; }; -/** - * @type { import("../typings/types.d.ts").hasOwn } - */ -const hasOwn = (o, v) => { - if (typeof Object.hasOwn !== 'undefined') { - return Object.hasOwn(o, v); - } - return Object.prototype.hasOwnProperty.call(o, v); -}; /** * @type { import("../typings/types.d.ts").objToStr } */ -const objToStr = (obj) => { - return Object.prototype.toString.call(obj); -}; +const objToStr = (obj) => Object.prototype.toString.call(obj); /** * @type { import("../typings/types.d.ts").strToURL } */ @@ -272,7 +335,8 @@ const strToURL = (str) => { str = str ?? WIN_LOCATION; return objToStr(str).includes('URL') ? str : new URL(str); } catch (ex) { - err({ cause: 'strToURL', message: ex.message }); + ex.cause = 'strToURL'; + err(ex); } return WIN_LOCATION; }; @@ -394,8 +458,8 @@ const formAttrs = (elem, attr = {}) => { const make = (tagName, cname, attrs) => { let el; try { - const safe = safeSelf(); - el = safe.createElement(tagName); + const { createElement } = safeSelf(); + el = createElement(tagName); if (!isEmpty(cname)) { if (typeof cname === 'string') { el.className = cname; @@ -411,6 +475,7 @@ const make = (tagName, cname, attrs) => { } } } catch (ex) { + ex.cause = 'make'; err(ex); } return el; @@ -615,8 +680,8 @@ const iconSVG = { html: '' }, load(type, container) { - const safe = safeSelf(); - const svgElem = safe.createElementNS('http://www.w3.org/2000/svg', 'svg'); + const { createElementNS } = safeSelf(); + const svgElem = createElementNS('http://www.w3.org/2000/svg', 'svg'); for (const [k, v] of Object.entries(iconSVG[type])) { if (k === 'html') { continue; @@ -686,6 +751,7 @@ const StorageSystem = { : def; } catch (ex) { err(ex); + return def; } } }; @@ -714,10 +780,11 @@ const Command = { * @type { import("../typings/UserJS.d.ts").Network } */ const Network = { - async req(url, method = 'GET', responseType = 'json', data = {}, useFetch = false) { + async req(url, method = 'GET', responseType = 'json', data, useFetch = false) { if (isEmpty(url)) { throw new Error('"url" parameter is empty'); } + data = Object.assign({}, data); method = this.bscStr(method, false); responseType = this.bscStr(responseType); const params = { @@ -742,13 +809,15 @@ const Network = { } else if (params.onprogress) { delete params.onprogress; } - return await new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { if (isGM && !useFetch) { Network.xmlRequest({ url, responseType, ...params, - onerror: reject, + onerror: (r_1) => { + reject(new Error(`${r_1.status} ${url}`)); + }, onload: (r_1) => { if (r_1.status !== 200) reject(new Error(`${r_1.status} ${url}`)); if (responseType.match(/basic/)) resolve(r_1); @@ -811,8 +880,8 @@ const Network = { } } return await new Promise((resolve, reject) => { - const safe = safeSelf(); - const req = new safe.XMLHttpRequest(); + const { XMLHttpRequest } = safeSelf(); + const req = new XMLHttpRequest(); let method = 'GET'; let url = BLANK_PAGE; let body; @@ -930,6 +999,7 @@ class Container { this.updateCounter = this.updateCounter.bind(this); this.updateCounters = this.updateCounters.bind(this); this.showError = this.showError.bind(this); + this.webpage = strToURL(url); this.host = this.getHost(this.webpage.host); this.domain = this.getDomain(this.webpage.host); @@ -1020,7 +1090,7 @@ class Container { window.addEventListener('beforeunload', this.remove); } /** - * @param { Function } callback + * @param { function(): * } callback * @param { Document } doc */ async inject(callback, doc) { @@ -1035,6 +1105,7 @@ class Container { if (doc === null) { return; } + while (this.ready === false) { await new Promise((resolve) => requestAnimationFrame(resolve)); } @@ -1496,7 +1567,6 @@ class Container { } catch (ex) { err(ex); } - return null; } checkBlacklist(str) { str = str || this.host; @@ -1536,7 +1606,7 @@ class Container { } } this.isBlacklisted = blacklisted; - return blacklisted; + return this.isBlacklisted; } getInfo(url) { const webpage = strToURL(url || this.webpage); @@ -1617,8 +1687,9 @@ class Container { } this.promptElem.append(el); } - makeError(...ex) { - const safe = safeSelf(); + showError(...ex) { + err(...ex); + const { createTextNode } = safeSelf(); const error = make('mu-js', 'error'); let str = ''; for (const e of ex) { @@ -1629,13 +1700,9 @@ class Container { } } } - error.appendChild(safe.createTextNode(str)); + error.appendChild(createTextNode(str)); this.footer.append(error); } - showError(...ex) { - err(...ex); - this.makeError(...ex); - } updateCounter(count, engine) { this.counters[engine.name] += count; this.counters.total += count; @@ -1646,8 +1713,9 @@ class Container { if (k === 'total') { continue; } - if (qs(`count-frame[data-counter="${k}"]`, this.countframe)) { - dom.text(qs(`count-frame[data-counter="${k}"]`, this.countframe), v); + const c = qs(`count-frame[data-counter="${k}"]`, this.countframe); + if (c) { + dom.text(c, v); } } dom.text(this.mainbtn, this.counters.total); @@ -1669,6 +1737,7 @@ const container = new Container(); // #region Primary Function function primaryFN() { try { + const { scheduler } = safeSelf(); const { mainframe, urlBar, @@ -1821,11 +1890,6 @@ function primaryFN() { dom.cl.remove(mainframe, 'hidden'); timeoutFrame(); } else if (cmd === 'save') { - // if (!isNull(ghMsg)) { - // ghMsg = null; - // container.rebuild = true; - // dom.prop(rateContainer, 'innerHTML', ''); - // } container.rebuild = true; dom.prop(rateContainer, 'innerHTML', ''); if (!dom.prop(target, 'disabled')) { @@ -2318,6 +2382,9 @@ function primaryFN() { } return false; } + // intersect(a, ...arr) { + // return [...new Set(a)].filter((v) => arr.every((b) => b.includes(v))); + // } } const mergeTemplate = (obj = {}) => { const template = { @@ -2344,6 +2411,12 @@ function primaryFN() { } ] }; + /** @type {ObjectConstructor["hasOwn"]} */ + const hasOwn = + Object.hasOwn || + function hasOwn(it, key) { + return Object.prototype.hasOwnProperty.call(it, key); + }; for (const key in template) { if (hasOwn(obj, key)) continue; obj[key] = template[key]; @@ -2417,17 +2490,20 @@ function primaryFN() { } } }; + /** + * @param {number} [time] + */ const timeoutFrame = async (time) => { - time = time ?? cfg.time; frameTimeout.clear(...frameTimeout.ids); if (dom.cl.has(mainframe, 'hidden')) { return; } + time = time ?? cfg.time ?? DEFAULT_CONFIG.time; + let n = 10000; if (typeof time === 'number' && !Number.isNaN(time)) { - await frameTimeout.set(container.isBlacklisted ? time / 2 : time); - } else { - await frameTimeout.set(10000); + n = container.isBlacklisted ? time / 2 : time; } + await frameTimeout.set(n); container.remove(); return frameTimeout.clear(...frameTimeout.ids); }; @@ -2643,15 +2719,14 @@ function primaryFN() { return tr; }; // #endregion - // #region Build List + // #region List class List { engines; cache; intHost; constructor(host = undefined) { - if (isEmpty(host)) { - host = container.host; - } + this.build = this.build.bind(this); + if (isEmpty(host)) host = container.host; this.engines = cfg.engines; this.cache = container.cache.get(host); this.host = host; @@ -2688,20 +2763,14 @@ function primaryFN() { }; this.engines = cfg.engines.filter((e) => e.enabled && isSupported(e.name)); this.cache = container.cache.get(hostname); - // if (!isNull(ghMsg)) { - // const txt = make('mujs-row', 'legacy-config', { - // textContent: ghMsg - // }); - // rateContainer.append(txt); - // return; - // } } get host() { return this.intHost; } - async build() { + // #region Builder + build() { try { container.refresh(); if (this.blacklisted) { @@ -2714,8 +2783,9 @@ function primaryFN() { } info(' Building list', { cache: this.cache, engines: this.engines }); const customRecords = []; - const arr = []; const host = this.host; + const arr = []; + for (const engine of this.engines) { const cEngine = this.cache[`${engine.name}`]; if (!isEmpty(cEngine)) { @@ -2727,6 +2797,13 @@ function primaryFN() { updateCounter(cEngine.length, engine); continue; } + const respError = (error) => { + if (error.message.startsWith('429')) { + showError(`Engine: "${engine.name}" Too many requests...`); + return; + } + showError(`Engine: "${engine.name}"`, error.message); + }; const _mujs = (d) => { const obj = { ...d, @@ -2854,7 +2931,7 @@ function primaryFN() { : Array.isArray(dataQ.query) ? dataQ.query : []; - const dataA = dq.filter((d) => !d.deleted); + const dataA = dq.filter(Boolean).filter((d) => !d.deleted); if (isBlank(dataA)) { return; } @@ -2886,7 +2963,7 @@ function primaryFN() { hds.push(ujs); } } - finalList = [...new Set([...hds, ...filterLang])]; + finalList = union(hds, filterLang); for (const ujs of finalList) { if (cfg.codePreview && !ujs._mujs.code.data) { @@ -2993,7 +3070,9 @@ function primaryFN() { continue; } netFN = Network.req( - toQuery(`${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30`), + toQuery( + `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` + ), 'GET', 'json', { @@ -3021,27 +3100,25 @@ function primaryFN() { rateContainer.append(txt); } }) - .catch(showError); - }) - .catch(showError); - } else if (/openuserjs/gi.test(engine.name)) { - netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document') - .then(openuserjs) - .catch((error) => { - showError(`Engine: "${engine.name}"`, error); + .catch(respError); }); + } else if (/openuserjs/gi.test(engine.name)) { + netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document').then( + openuserjs + ); } else { - netFN = Network.req(toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`)) - .then(forkFN) - .catch(showError); + netFN = Network.req( + toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) + ).then(forkFN); } if (netFN) { - arr.push(netFN); + arr.push(netFN.catch(respError)); } } urlBar.placeholder = i18n$('search_placeholder'); urlBar.value = ''; + Promise.allSettled(arr).then(() => { tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); @@ -3050,6 +3127,7 @@ function primaryFN() { showError(ex); } } + // #endregion } const MUList = new List(); // #endregion @@ -3107,7 +3185,7 @@ function primaryFN() { }); if (engine.query) { - const d = DEFAULT_CONFIG.engines.find(e => e.name === engine.name); + const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); const urlInp = make('input', '', { type: 'text', defaultValue: '', @@ -3148,7 +3226,6 @@ function primaryFN() { cfgMap.set('github-token', ghToken); } } - } else { inp.checked = cfg[nm]; ael(inp, 'change', (evt) => { @@ -3196,22 +3273,6 @@ function primaryFN() { makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); makerow('Open UserJS', 'checkbox', 'openuserjs'); makerow('GitHub API', 'checkbox', 'github'); - // const ghAPI = cfg.engines.find((c) => c.name === 'github'); - // const ghToken = makerow('GitHub API (Token)', 'text', 'github', { - // defaultValue: '', - // value: ghAPI.token ?? '', - // placeholder: 'Paste Access Token', - // onchange(evt) { - // container.unsaved = true; - // container.rebuild = true; - // ghAPI.token = evt.target.value; - // // if (isNull(ghMsg)) { - // // ghAPI.token = evt.target.value; - // // } - // } - // }); - // ghToken.dataset.engine = 'github-token'; - // cfgMap.set('github-token', ghToken); makerow(`${i18n$('dtime')} (ms)`, 'number', 'time', { defaultValue: 10000, value: cfg.time, @@ -3363,7 +3424,7 @@ function primaryFN() { if (!dom.cl.has(cfgpage, 'hidden')) { const reg = new RegExp(val, 'gi'); for (const elem of qsA('mujs-section[data-name]', cfgpage)) { - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -3386,7 +3447,7 @@ function primaryFN() { const reg = new RegExp(q_value, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -3408,7 +3469,7 @@ function primaryFN() { const reg = new RegExp(q_value, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -3441,7 +3502,7 @@ function primaryFN() { const reg = new RegExp(q_value, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -3459,7 +3520,7 @@ function primaryFN() { const reg = new RegExp(val, 'gi'); for (const v of userjsCache.values()) { const elem = v._mujs.root; - if (!elem) { + if (!isElem(elem)) { continue; } if (finds.has(elem)) { @@ -3521,8 +3582,8 @@ function primaryFN() { return; } }); - makecfg(); - MUList.build().then(timeoutFrame); + scheduler.postTask(makecfg, { priority: 'user-visible' }); + scheduler.postTask(MUList.build, { priority: 'background' }).then(timeoutFrame); dbg('Container', container); } catch (ex) { err(ex); @@ -3532,16 +3593,17 @@ function primaryFN() { // #endregion /** * @template { Function } F - * @param { (this: F, doc: Document) => any } onDomReady + * @param { (this: F, doc: Document) => * } onDomReady */ const loadDOM = (onDomReady) => { if (!isFN(onDomReady)) { return; } if (document.readyState === 'interactive' || document.readyState === 'complete') { - onDomReady.call({}, document); + onDomReady(document); + return; } - document.addEventListener('DOMContentLoaded', (evt) => onDomReady.call({}, evt.target), { + document.addEventListener('DOMContentLoaded', (evt) => onDomReady(evt.target), { once: true }); }; @@ -3556,18 +3618,20 @@ const init = async () => { loadDOM((doc) => { try { if (window.location === null) { - throw new Error('"window.location" is null, reload the webpage or use a different one'); + throw new Error('"window.location" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); } if (doc === null) { - throw new Error('"doc" is null, reload the webpage or use a different one'); + throw new Error('"doc" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); } if (window.trustedTypes && window.trustedTypes.createPolicy) { window.trustedTypes.createPolicy('default', { createHTML: (string) => string }); } + sleazyRedirect(); container.inject(primaryFN, doc); + Command.register(i18n$('userjs_inject'), () => { container.inject(primaryFN, doc); }); diff --git a/src/typings/UserJS.d.ts b/src/typings/UserJS.d.ts index 3868ff4..25c80ad 100644 --- a/src/typings/UserJS.d.ts +++ b/src/typings/UserJS.d.ts @@ -2,22 +2,42 @@ // import '@types/tampermonkey'; import '@violentmonkey/types'; import { type GSForkQuery } from './types'; +import './scheduler'; + +export interface safeHandles { + // trustedTypes: { + // createPolicy(): void; + // }; + XMLHttpRequest: typeof XMLHttpRequest; + createElement: typeof document.createElement; + createElementNS: typeof document.createElementNS; + createTextNode: typeof document.createTextNode; + setTimeout: typeof setTimeout; + clearTimeout: typeof clearTimeout; + navigator: typeof navigator; + /** Taken from [scheduler-polyfill](https://github.com/GoogleChromeLabs/scheduler-polyfill) */ + scheduler: typeof scheduler; +} /** * Some sites will alter or remove document functions * To get around this we bind them to the `userjs` object * - * This method is based on uBlock Origin `scriptlets.js` file - * - * [Source Code](https://github.com/gorhill/uBlock/blob/master/assets/resources/scriptlets.js) + * This method is based on uBlock Origin [scriptlets.js](https://github.com/gorhill/uBlock/blob/master/assets/resources/scriptlets.js) */ export declare function safeSelf(): { + // trustedTypes: { + // createPolicy(): void; + // }; XMLHttpRequest: typeof XMLHttpRequest; createElement: typeof document.createElement; createElementNS: typeof document.createElementNS; createTextNode: typeof document.createTextNode; setTimeout: typeof setTimeout; clearTimeout: typeof clearTimeout; + navigator: typeof navigator; + /** Taken from [scheduler-polyfill](https://github.com/GoogleChromeLabs/scheduler-polyfill) */ + scheduler: typeof scheduler; }; export declare function loadCSS(css: string, name: string): HTMLStyleElement | undefined; diff --git a/src/typings/scheduler.d.ts b/src/typings/scheduler.d.ts new file mode 100644 index 0000000..8c4148e --- /dev/null +++ b/src/typings/scheduler.d.ts @@ -0,0 +1,131 @@ +/** + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Task priorities that determine the order in which tasks run. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Prioritized_Task_Scheduling_API#task_priorities) + */ +export type TaskPriority = 'user-blocking' | 'user-visible' | 'background'; + +/** + * {@link Scheduler.postTask} options. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Scheduler/postTask#options) + */ +export type SchedulerPostTaskOptions = { + /** The immutable {@link TaskPriority} of the task. One of `"user-blocking"`, `"user-visible"`, or `"background"`. If set, this priority is used for the lifetime of the task and priority set on the `signal` is ignored. */ + priority?: TaskPriority; + /** An {@link AbortSignal} or {@link TaskSignal} that can be used to abort or re-prioritize the task (from its associated controller). The signal's priority is ignored if `priority` is set. */ + signal?: AbortSignal | TaskSignal; + /** The minimum amount of time after which the task will be added to the scheduler queue, in whole milliseconds. The actual delay may be higher than specified, but will not be less. The default delay is 0. */ + delay?: number; +}; + +/** + * {@link TaskController} options. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskController/TaskController#options) + */ +type TaskControllerOptions = { + /** The {@link TaskPriority} of the signal associated with this {@link TaskController}. One of `"user-blocking"`, `"user-visible"`, or `"background"`. The default is `"user-visible"`. */ + priority?: TaskPriority; +} + +/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskPriorityChangeEvent/TaskPriorityChangeEvent#options) */ +interface TaskPriorityChangeEventInit extends EventInit { + /** A string indicating the previous priority of the task. One of `"user-blocking"`, `"user-visible"`, or `"background"`. */ + previousPriority: TaskPriority; +} + +declare global { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Scheduler) */ + interface Scheduler { + /** + * Adds a task to the scheduler as a callback, optionally specifying a priority, delay, and/or a signal for aborting the task. + * @param callback A callback function that implements the task. The return value of the callback is used to resolve the promise returned by this function. + * @param options {@link SchedulerPostTaskOptions} options. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Scheduler/postTask) + */ + postTask(callback: () => T, options?: SchedulerPostTaskOptions): Promise; + /** + * Returns a promise that yields to the event loop when awaited, allowing continuation in a new task. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Scheduler/yield) + */ + yield(): Promise; + } + + /** + * A controller object that can be used to both abort and change the priority of one or more prioritized tasks. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskController) + */ + class TaskController extends AbortController { + constructor(options?: TaskControllerOptions); + /** Returns a {@link TaskSignal} instance. The signal is passed to tasks so that they can be aborted or re-prioritized by the controller. */ + readonly signal: TaskSignal; + /** + * Sets the priority of the controller's signal, and hence the priority of any tasks with which it is associated. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskController/setPriority) + */ + setPriority(priority: TaskPriority): void; + } + + /** + * The `prioritychange` event, sent to a {@link TaskSignal} if its priority is changed. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskPriorityChangeEvent) + */ + class TaskPriorityChangeEvent extends Event { + constructor(type: string, init: TaskPriorityChangeEventInit); + /** + * The priority of the corresponding {@link TaskSignal} _before_ this prioritychange event. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskPriorityChangeEvent/previousPriority) + */ + readonly previousPriority: TaskPriority; + } + + /** + * A signal object that allows you to communicate with a prioritized task, aborting it or changing the priority (if required) via a {@link TaskController} object. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskSignal) + */ + class TaskSignal extends AbortSignal { + /** + * The priority of the signal. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskSignal/priority) + */ + readonly priority: TaskPriority; + /** + * Fired when the priority is changed. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/TaskSignal/prioritychange_event) + */ + onprioritychange: (event: TaskPriorityChangeEvent) => void; + } + + /** + * The global {@link Scheduler} entry point for using the Prioritized Task Scheduling API. + * + * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/scheduler) + */ + const scheduler: Scheduler; +} diff --git a/src/typings/types.d.ts b/src/typings/types.d.ts index 9f6c0d0..873ba4c 100644 --- a/src/typings/types.d.ts +++ b/src/typings/types.d.ts @@ -176,8 +176,6 @@ export type config = { }; }; -export declare function hasOwn(o: object, p: PropertyKey): boolean; - export declare function objToStr(obj: O): string; export declare function strToURL(str: S): URL; From 07ab44cefab9f64a6533d4f14d1534e8f1cd7317 Mon Sep 17 00:00:00 2001 From: Magic Date: Fri, 7 Feb 2025 09:48:29 -0800 Subject: [PATCH 03/35] UserJS v7.1.1 Signed-off-by: Magic --- CHANGELOG.user.md | 18 ++++++++++++------ dist/magic-userjs.meta.js | 2 +- dist/magic-userjs.user.js | 23 ++++++++++++++++------- package.json | 2 +- src/UserJS/main.js | 21 +++++++++++++++------ 5 files changed, 45 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index cf60e4a..617a32a 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,4 +1,10 @@ -# What's New (v7.1.0) +# Changelog + +## v7.1.1 + +* Fixed "Error When Opening YouTube" https://github.com/magicoflolis/Userscript-Plus/issues/63 + +## v7.1.0 * Implemented [Task Scheduling API](https://developer.mozilla.org/en-US/docs/Web/API/Prioritized_Task_Scheduling_API) * Limited availability, see [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Scheduler#browser_compatibility) @@ -6,12 +12,12 @@ * Improved error handling * _Be sure to look in your console if the UserScript stops working for some reason!_ -## Known Issues +**Known Issues:** * "Filter out other languages" may not filter _every_ userscript that is not in your language. * SVG elements don't load on every webpage, _can be blocked by the page._ -## TODO +**TODO:** * Add [GreasyFork Bullshit Filter](https://greasyfork.org/scripts/12179) into list * Merge https://github.com/magicoflolis/Userscript-Plus/pull/59 @@ -20,7 +26,7 @@ --- -# What's New (v7.0.0) +## v7.0.0 * Ability to change the URL of each engine * **Please reset your config if updating!** @@ -38,12 +44,12 @@ * `search_engine:` or `engine:` * UI ajustments -## Known Issues +**Known Issues:** * "Filter out other languages" may not filter _every_ userscript that is not in your language. * SVG elements don't load on every webpage, _can be blocked by the page._ -## TODO +**TODO:** * Add sorting to the following: "Total installs", "Ratings", "Created date" * Improve design of blacklist section diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index 65a9e86..6957e0f 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.1.0 +// @version 7.1.1 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index e4ff1da..aa4330d 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.1.0 +// @version 7.1.1 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -1618,6 +1618,20 @@ function safeSelf() { return userjs.safeSelf; } +let trusedPolicy = false; +function setTrust() { + if (trusedPolicy) { + return; + } + if (window.trustedTypes && window.trustedTypes.createPolicy) { + window.trustedTypes.createPolicy('default', { + createHTML: (string) => string + }); + trusedPolicy = true; + } +} +setTrust(); + const BLANK_PAGE = 'about:blank'; // Lets highlight me :) const authorID = 166061; @@ -5116,12 +5130,7 @@ const init = async () => { if (doc === null) { throw new Error('"doc" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); } - if (window.trustedTypes && window.trustedTypes.createPolicy) { - window.trustedTypes.createPolicy('default', { - createHTML: (string) => string - }); - } - + setTrust(); sleazyRedirect(); container.inject(primaryFN, doc); diff --git a/package.json b/package.json index da80506..2177234 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/magicoflolis/Userscript-Plus/issues" }, "userJS": { - "version": "7.1.0", + "version": "7.1.1", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", diff --git a/src/UserJS/main.js b/src/UserJS/main.js index f0b7428..8beb5c8 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -125,6 +125,20 @@ function safeSelf() { return userjs.safeSelf; } +let trusedPolicy = false; +function setTrust() { + if (trusedPolicy) { + return; + } + if (window.trustedTypes && window.trustedTypes.createPolicy) { + window.trustedTypes.createPolicy('default', { + createHTML: (string) => string + }); + trusedPolicy = true; + } +} +setTrust(); + const BLANK_PAGE = 'about:blank'; // Lets highlight me :) const authorID = 166061; @@ -3623,12 +3637,7 @@ const init = async () => { if (doc === null) { throw new Error('"doc" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); } - if (window.trustedTypes && window.trustedTypes.createPolicy) { - window.trustedTypes.createPolicy('default', { - createHTML: (string) => string - }); - } - + setTrust(); sleazyRedirect(); container.inject(primaryFN, doc); From 4f3971a1f57310e144b80afc144263e7e7246e6f Mon Sep 17 00:00:00 2001 From: Magic Date: Fri, 7 Feb 2025 16:39:45 -0800 Subject: [PATCH 04/35] v7.1.2 Signed-off-by: Magic --- CHANGELOG.user.md | 28 ++ README.md | 16 +- dist/magic-userjs.meta.js | 2 +- dist/magic-userjs.user.js | 549 +++++++++++++++++++++++++------ package.json | 11 +- pnpm-lock.yaml | 412 ++++++++--------------- src/UserJS/main.js | 444 +++++++++++++++++++------ src/_locales/ar/messages.json | 9 + src/_locales/de/messages.json | 9 + src/_locales/en/messages.json | 9 + src/_locales/en_GB/messages.json | 9 + src/_locales/es/messages.json | 9 + src/_locales/fr/messages.json | 9 + src/_locales/ja/messages.json | 9 + src/_locales/nl/messages.json | 9 + src/_locales/pl/messages.json | 9 + src/_locales/ru/messages.json | 9 + src/_locales/zh/messages.json | 9 + src/_locales/zh_CN/messages.json | 9 + src/_locales/zh_TW/messages.json | 9 + src/sass/_main.scss | 65 +++- src/typings/UserJS.d.ts | 15 +- src/typings/types.d.ts | 2 + 23 files changed, 1159 insertions(+), 502 deletions(-) diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 617a32a..43b6117 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,9 +1,37 @@ # Changelog +## v7.1.2 + +* New config "Inject on load", when disabled prevents this script from injecting the menu automatically. + * You can still inject the menu through the context menu in your UserScript manager. + * This will reduce overall distraction the script can have on certain pages. +* New config "Fetch on load", when disabled prevents UserScripts from being fetched automatically. + * When the menu is re-injected through the context menu in your UserScript manager UserScripts will always be fetched automatically. + * This will reduce network traffic for the engines. +* Improved design of theme section. +* Improved design of blacklist section, adding new pages to the list is still incomplete. +* Changed "Sync with GM" to "Sync with UserScript Manager". +* CSS adjustments. + +**Known Issues:** + +* "Filter out other languages" may not filter _every_ userscript that is not in your language. +* SVG elements don't load on every webpage, _can be blocked by the page._ + +**TODO:** + +* Add [GreasyFork Bullshit Filter](https://greasyfork.org/scripts/12179) into list +* Merge https://github.com/magicoflolis/Userscript-Plus/pull/59 +* Add sorting to the following: "Total installs", "Ratings", "Created date" + +--- + ## v7.1.1 * Fixed "Error When Opening YouTube" https://github.com/magicoflolis/Userscript-Plus/issues/63 +--- + ## v7.1.0 * Implemented [Task Scheduling API](https://developer.mozilla.org/en-US/docs/Web/API/Prioritized_Task_Scheduling_API) diff --git a/README.md b/README.md index 5f3c5bd..183cfb0 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,7 @@ Finds available UserScripts for the current webpage, the power of [Greasy Fork]( **UserScript:** > [!IMPORTANT] -> If the current webpage is set to block resources through CSP -> -> It will cause the UserScript not work for that webpage! -> -> [https://developer.mozilla.org/docs/Web/HTTP/CSP](https://developer.mozilla.org/docs/Web/HTTP/CSP) +> The UserScript only works on `HTTPS`([https://example.com](https://example.com)) * [Greasy Fork](https://greasyfork.org/scripts/421603) * [Open UserJS](https://openuserjs.org/scripts/Magic/Magic_Userscript+_Show_Site_All_UserJS) - outdated @@ -44,14 +40,14 @@ Finds available UserScripts for the current webpage, the power of [Greasy Fork]( * [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/userscript-plus/) * [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest) -Available for desktop and Android versions. +Works for desktop and mobile versions. *Chromium:* * ~~[Chrome Web Store](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest)~~ * [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest) -Userscript+ should be compatible with any Chromium-based browser +Magic Userscript+ should be compatible with any Chromium-based browser **(Not Recommended) Bookmarklet:** @@ -65,7 +61,11 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * Designed for mobile and desktop devices * Support multiple languages - date formats will match your current language -* Query UserScripts from [Greasy Fork](https://greasyfork.org), [Sleazy Fork](https://sleazyfork.org), [Open UserJS](https://openuserjs.org), [GitHub](https://github.com/search?l=JavaScript&o=desc&q="==UserScript==") ( requires a [Personal Access Token](https://github.com/settings/tokens), the token does not require any permissions ) +* Query UserScripts from: + * [Greasy Fork](https://greasyfork.org) + * [Sleazy Fork](https://sleazyfork.org) + * [Open UserJS](https://openuserjs.org) ( limited availability, will read `Too many requests...` if limit is reached ) + * [GitHub](https://github.com/search?l=JavaScript&o=desc&q="==UserScript==") ( requires [Personal Access Token](https://github.com/settings/tokens), no permissions are required ) * Customize the theme * Import / export config and theme * Search for UserScripts diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index 6957e0f..5733d26 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.1.1 +// @version 7.2.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index aa4330d..ca3a993 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.1.1 +// @version 7.2.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -138,7 +138,10 @@ const translations = { "code_size": "حجم الرمز", "prmpt_css": "التثبيت كأسلوب المستخدم؟", "userjs_inject": "حقن Userscript+", - "userjs_close": "إغلاق Userscript+" + "userjs_close": "إغلاق Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "de": { "createdby": "Erstellt von", @@ -181,7 +184,10 @@ const translations = { "code_size": "Code Größe", "prmpt_css": "Als UserStyle installieren?", "userjs_inject": "Userscript+ einfügen", - "userjs_close": "Userscript+ schließen" + "userjs_close": "Userscript+ schließen", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "en": { "createdby": "Created by", @@ -224,7 +230,10 @@ const translations = { "code_size": "Code Size", "prmpt_css": "Install as UserStyle?", "userjs_inject": "Inject Userscript+", - "userjs_close": "Close Userscript+" + "userjs_close": "Close Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "en_GB": { "createdby": "Created by", @@ -267,7 +276,10 @@ const translations = { "code_size": "Code Size", "prmpt_css": "Install as UserStyle?", "userjs_inject": "Inject Userscript+", - "userjs_close": "Close Userscript+" + "userjs_close": "Close Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "es": { "createdby": "Creado por", @@ -310,7 +322,10 @@ const translations = { "code_size": "Código Tamaño", "prmpt_css": "¿Instalar como UserStyle?", "userjs_inject": "Inyectar Userscript+", - "userjs_close": "Cerrar Userscript+" + "userjs_close": "Cerrar Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "fr": { "createdby": "Créé par", @@ -353,7 +368,10 @@ const translations = { "code_size": "Code Taille", "prmpt_css": "Installer comme UserStyle ?", "userjs_inject": "Injecter Userscript+", - "userjs_close": "Fermer Userscript+" + "userjs_close": "Fermer Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "ja": { "createdby": "によって作成された", @@ -396,7 +414,10 @@ const translations = { "code_size": "コード・サイズ", "prmpt_css": "UserStyleとしてインストールしますか?", "userjs_inject": "Userscript+ を挿入", - "userjs_close": "Userscript+ を閉じる" + "userjs_close": "Userscript+ を閉じる", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "nl": { "createdby": "Gemaakt door", @@ -439,7 +460,10 @@ const translations = { "code_size": "Code Grootte", "prmpt_css": "Installeren als UserStyle?", "userjs_inject": "Injecteer Userscript+", - "userjs_close": "Sluit Userscript+" + "userjs_close": "Sluit Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "pl": { "createdby": "Stworzony przez", @@ -482,7 +506,10 @@ const translations = { "code_size": "Kod Rozmiar", "prmpt_css": "Zainstalować jako UserStyle?", "userjs_inject": "Wstrzyknij Userscript+", - "userjs_close": "Zamknij Userscript+" + "userjs_close": "Zamknij Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "ru": { "createdby": "Сделано", @@ -525,7 +552,10 @@ const translations = { "code_size": "Код Размер", "prmpt_css": "Установить как UserStyle?", "userjs_inject": "Вставить Userscript+", - "userjs_close": "Закрыть Userscript+" + "userjs_close": "Закрыть Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "zh": { "createdby": "由...制作", @@ -568,7 +598,10 @@ const translations = { "code_size": "代码 尺寸", "prmpt_css": "安装为用户风格?", "userjs_inject": "注入 Userscript+", - "userjs_close": "关闭 Userscript+" + "userjs_close": "关闭 Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "zh_CN": { "createdby": "由...制作", @@ -611,7 +644,10 @@ const translations = { "code_size": "代码 尺寸", "prmpt_css": "安装为用户风格?", "userjs_inject": "注入 Userscript+", - "userjs_close": "关闭 Userscript+" + "userjs_close": "关闭 Userscript+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" }, "zh_TW": { "createdby": "由...制作", @@ -654,7 +690,10 @@ const translations = { "code_size": "代码 尺寸", "prmpt_css": "作為使用者樣式安裝?", "userjs_inject": "注入用戶腳本+", - "userjs_close": "關閉用戶腳本+" + "userjs_close": "關閉用戶腳本+", + "userjs_sync": "Sync with UserScript Manager", + "userjs_autoinject": "Inject on load", + "auto_fetch": "Fetch on load" } }; /** @@ -1220,6 +1259,21 @@ mujs-body table .frame[data-good] mu-jsbtn:hover, mujs-body table .frame[data-au background: hsl(81, 56%, 65%); border-color: hsl(81, 56%, 65%); } +mujs-body table .frame.translated:not([data-good], [data-author]) mujs-a { + color: hsl(249, 56%, 65%); +} +mujs-body table .frame.translated:not([data-good], [data-author]) mujs-a:hover { + color: hsl(249, 56%, 85%); +} +mujs-body table .frame.translated:not([data-good], [data-author]) mu-jsbtn { + color: hsl(215, 47%, 85%); + background: hsl(249, 56%, 65%); + border-color: hsl(249, 56%, 65%); +} +mujs-body table .frame.translated:not([data-good], [data-author]) mu-jsbtn:hover { + background: hsl(249, 56%, 65%); + border-color: hsl(249, 56%, 65%); +} mujs-body table .frame .mujs-ratings[data-el=good] { border-color: hsl(120, 50%, 40%); background-color: hsla(120, 50%, 40%, 0.102); @@ -1337,6 +1391,12 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg mujs-section:nth-child(odd) { background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; } +.mujs-cfg mujs-section[data-name=theme], .mujs-cfg mujs-section[data-name=blacklist] { + display: flex; + justify-content: space-between; + flex-direction: column; + gap: 0.25em; +} .mujs-cfg mujs-section input[type=text]::-webkit-input-placeholder { color: var(--mujs-placeholder, hsl(81, 56%, 54%)); } @@ -1352,10 +1412,23 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg mujs-section input[type=text]::placeholder { color: var(--mujs-placeholder, hsl(81, 56%, 54%)); } -.mujs-cfg mujs-section > label { +.mujs-cfg mujs-section > label:not([data-blacklist]) { display: flex; justify-content: space-between; } +.mujs-cfg mujs-section > label[data-blacklist] { + display: grid; + grid-auto-flow: column; +} +.mujs-cfg mujs-section > label[data-blacklist]:not(.new-list) { + grid-template-columns: repeat(2, 1fr); +} +.mujs-cfg mujs-section > label.new-list { + order: 999999999999; +} +.mujs-cfg mujs-section > label.new-list mujs-add { + font-size: 20px; +} .mujs-cfg mujs-section > label input:not([type=checkbox]) { font-size: 14px; position: relative; @@ -1483,7 +1556,7 @@ mu-jsbtn { mujs-a, mu-jsbtn, .mujs-pointer, -.mujs-cfg mujs-section *:not(input[type=password], input[type=text], input[type=number]), +.mujs-cfg mujs-section *:not(input[type=password], input[type=text], input[type=number], [data-theme], [data-blacklist]), .mainbtn, .mainframe, mujs-btn { @@ -1618,19 +1691,28 @@ function safeSelf() { return userjs.safeSelf; } -let trusedPolicy = false; -function setTrust() { - if (trusedPolicy) { - return; - } - if (window.trustedTypes && window.trustedTypes.createPolicy) { - window.trustedTypes.createPolicy('default', { - createHTML: (string) => string - }); - trusedPolicy = true; +const trustedTypes = { + policy: false, + init() { + if (this.policy) { + return this.policy; + } + this.policy = true; + try { + // Native implementation exists + if (window.trustedTypes && window.trustedTypes.createPolicy) { + window.trustedTypes.createPolicy('default', { + createHTML: (string) => string + }); + } + } catch (ex) { + ex.cause = 'trustedTypes.init()'; + err(ex); + } + return this.policy; } -} -setTrust(); +}; +trustedTypes.init(); const BLANK_PAGE = 'about:blank'; // Lets highlight me :) @@ -1702,6 +1784,8 @@ const builtinList = { * @type { import("../typings/types.d.ts").config } */ const DEFAULT_CONFIG = { + autofetch: true, + autoinject: true, cache: true, codePreview: false, autoexpand: false, @@ -2594,6 +2678,8 @@ class Container { mouse: new Timeout() }; + this.injFN = () => {} + window.addEventListener('beforeunload', this.remove); } /** @@ -2619,6 +2705,9 @@ class Container { try { doc.documentElement.appendChild(this.frame); if (this.injected) { + if (isFN(this.injFN.build)) { + this.injFN.build(); + } return; } this.shadowRoot.append(this.root); @@ -2628,7 +2717,7 @@ class Container { this.injected = true; this.initFn(); if (this.elementsReady && isFN(callback)) { - callback.call(this, this.shadowRoot); + this.injFN = callback.call(this, this.shadowRoot); } } catch (ex) { err(ex); @@ -2745,8 +2834,6 @@ class Container { this.intFN(host); } else { this.custom(host); - // MUList.host = host; - // MUList.build(); } } } @@ -3022,7 +3109,7 @@ class Container { async save() { this.unsaved = false; await StorageSystem.setValue('Config', cfg); - info('Saved:', cfg); + info('Saved config:', cfg); return cfg; } /** @@ -3196,17 +3283,17 @@ class Container { } showError(...ex) { err(...ex); - const { createTextNode } = safeSelf(); const error = make('mu-js', 'error'); let str = ''; for (const e of ex) { - str += `${typeof e === 'string' ? e : `${e.cause ? `[${e.cause}] ` : ''}${e.message} ${e.stack ?? ''}`}\n`; + str += `${typeof e === 'string' ? e : `${e.cause ? `[${e.cause}] ` : ''}${e.message}${e.stack ? ` ${e.stack}` : ''}`}\n`; if (isObj(e)) { if (e.notify) { dom.cl.add(this.mainframe, 'error'); } } } + const { createTextNode } = safeSelf(); error.appendChild(createTextNode(str)); this.footer.append(error); } @@ -3243,6 +3330,9 @@ const container = new Container(); // #endregion // #region Primary Function function primaryFN() { + const respHandles = { + build: async () => {} + }; try { const { scheduler } = safeSelf(); const { @@ -3291,8 +3381,13 @@ function primaryFN() { } } } - dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); - dom.prop(cfgMap.get('theme'), 'value', JSON.stringify(cfg.theme, null, ' ')); + // dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); + // for (const [k, v] of Object.entries(cfg.blacklist)) { + // dom.prop(cfgMap.get(k), 'value', v); + // } + for (const [k, v] of Object.entries(cfg.theme)) { + dom.prop(cfgMap.get(k), 'value', v); + } container.renderTheme(cfg.theme); }; const doInstallProcess = async (installLink) => { @@ -3400,11 +3495,13 @@ function primaryFN() { container.rebuild = true; dom.prop(rateContainer, 'innerHTML', ''); if (!dom.prop(target, 'disabled')) { - container.save(); + const config = await container.save(); sleazyRedirect(); if (container.rebuild) { container.cache.clear(); - MUList.build(); + if (config.autofetch) { + respHandles.build(); + } } container.unsaved = false; container.rebuild = false; @@ -3562,12 +3659,21 @@ function primaryFN() { container.unsaved = true; container.rebuild = true; rebuildCfg(); - container.save(); - sleazyRedirect(); - container.cache.clear(); - MUList.build(); - container.unsaved = false; - container.rebuild = false; + container.save().then((config) => { + sleazyRedirect(); + container.cache.clear(); + if (config.autofetch) { + respHandles.build(); + }; + container.unsaved = false; + container.rebuild = false; + }); + // container.save(); + // sleazyRedirect(); + // container.cache.clear(); + // MUList.build(); + // container.unsaved = false; + // container.rebuild = false; } else { log(`Imported theme: { ${file.name} }`, result); cfg.theme = result; @@ -4217,6 +4323,10 @@ function primaryFN() { codeArea.value = code_obj.get_code_block(); } + if (ujs._mujs.code?.translated) { + tr.classList.add('translated'); + } + for (const e of [fname, uframe, fdaily, fupdated, eframe]) { tr.append(e); } @@ -4304,7 +4414,11 @@ function primaryFN() { updateCounter(cEngine.length, engine); continue; } + // if (!cfg.autofetch) { + // continue; + // } const respError = (error) => { + if (!error.cause) error.cause = engine.name; if (error.message.startsWith('429')) { showError(`Engine: "${engine.name}" Too many requests...`); return; @@ -4640,6 +4754,43 @@ function primaryFN() { // #endregion // #region Make Config const makecfg = () => { + const makesection = (name, tag) => { + tag = tag ?? i18n$('no_license'); + name = name ?? i18n$('no_license'); + const sec = make('mujs-section', '', { + dataset: { + name: tag + } + }); + const lb = make('label', '', { + dataset: { + command: tag + } + }); + const divDesc = make('mu-js', '', { + textContent: name + }); + ael(sec, 'click', (evt) => { + /** @type { HTMLElement } */ + const target = evt.target.closest('[data-command]'); + if (!target) { + return; + } + const cmd = target.dataset.command; + if (cmd === tag) { + const a = qsA(`label[data-${tag}]`, sec); + if (dom.cl.has(a, 'hidden')) { + dom.cl.remove(a, 'hidden'); + } else { + dom.cl.add(a, 'hidden'); + } + } + }); + lb.append(divDesc); + sec.append(lb); + cfgpage.append(sec); + return sec; + }; const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); @@ -4749,8 +4900,10 @@ function primaryFN() { return inp; }; if (isGM) { - makerow('Sync with GM', 'checkbox', 'cache'); + makerow(i18n$('userjs_sync'), 'checkbox', 'cache'); + makerow(i18n$('userjs_autoinject'), 'checkbox', 'autoinject'); } + makerow(i18n$('auto_fetch'), 'checkbox', 'autofetch'); makerow(i18n$('userjs_fullscreen'), 'checkbox', 'autoexpand', { onchange(e) { if (e.target.checked) { @@ -4821,72 +4974,228 @@ function primaryFN() { command: 'reset' } }); - const blacklist = make('textarea', '', { - dataset: { - name: 'blacklist' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.blacklist, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.blacklist = JSON.parse(evt.target.value); - isvalid = true; - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); + // const blacklist = make('textarea', '', { + // dataset: { + // name: 'blacklist' + // }, + // rows: '10', + // autocomplete: false, + // spellcheck: false, + // wrap: 'soft', + // value: JSON.stringify(cfg.blacklist, null, ' '), + // oninput(evt) { + // let isvalid = true; + // try { + // cfg.blacklist = JSON.parse(evt.target.value); + // isvalid = true; + // } catch (ex) { + // err(ex); + // isvalid = false; + // } finally { + // if (isvalid) { + // dom.cl.remove(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', false); + // } else { + // dom.cl.add(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', true); + // } + // } + // } + // }); + // cfgMap.set('blacklist', blacklist); + cbtn.append(resetbtn, savebtn); + + const themeSec = makesection('Theme Colors', 'theme'); + for (const [k, v] of Object.entries(cfg.theme)) { + cfgMap.set(k, v); + const lb = make('label', 'hidden', { + textContent: k, + dataset: { + theme: k + } + }); + const inp = make('input', '', { + type: 'text', + defaultValue: '', + value: v ?? '', + placeholder: v ?? '', + dataset: { + theme: k + }, + onchange(evt) { + let isvalid = true; + try { + const val = evt.target.value; + const sty = container.root.style; + const str = `--mujs-${k}`; + const prop = sty.getPropertyValue(str); + if (isEmpty(val)) { + cfg.theme[k] = DEFAULT_CONFIG.theme[k]; + cfgMap.set(k, DEFAULT_CONFIG.theme[k]); + sty.removeProperty(str); + return; + } + if (prop === val) { + return; + } + sty.removeProperty(str); + sty.setProperty(str, val); + cfg.theme[k] = val; + cfgMap.set(k, val); + } catch (ex) { + err(ex); + isvalid = false; + } finally { + if (isvalid) { + dom.cl.remove(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', false); + } else { + dom.cl.add(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', true); + } } } + }); + lb.append(inp); + themeSec.append(lb); + } + + const listSec = makesection('Blacklist (WIP)', 'blacklist'); + const createList = (key, v = '', disabled = false, type = 'String') => { + let txt = key; + if (typeof key === 'string') { + if (key.startsWith('userjs-')) { + disabled = true; + const s = key.substring(7); + txt = `Built-in "${s}"`; + v = builtinList[s]; + }; + } else { + if (!key.enabled) { + return; + } } - }); - const theme = make('textarea', '', { - dataset: { - name: 'theme' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.theme, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.theme = JSON.parse(evt.target.value); - container.renderTheme(JSON.parse(evt.target.value)); - isvalid = true; - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); + + if (isRegExp(v)) { + v = v.toString(); + type = 'RegExp'; + } else { + v = JSON.stringify(v); + type = 'Object'; + } + + const lb = make('label', 'hidden', { + textContent: txt, + dataset: { + blacklist: key + } + }); + const inp = make('input', '', { + type: 'text', + defaultValue: '', + value: v ?? '', + placeholder: v ?? '', + dataset: { + blacklist: key + }, + onchange(evt) { + let isvalid = true; + try { + const val = evt.target.value; + if (isEmpty(val)) { + return; + } + // if (isRegExp(val)) { + // v = val.toString(); + // }; + isvalid = true; + } catch (ex) { + err(ex); + isvalid = false; + } finally { + if (isvalid) { + dom.cl.remove(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', false); + } else { + dom.cl.add(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', true); + } } } + }); + const selType = make('select', '', { + disabled, + dataset: { + blacklist: key + } + }); + if (disabled) { + inp.readOnly = true; + const o = make('option', '', { + value: type, + textContent: type + }); + selType.append(o); + } else { + for (const selV of ['String', 'RegExp', 'Object']) { + const o = make('option', '', { + value: selV, + textContent: selV + }); + selType.append(o); + }; } - }); - cfgMap.set('blacklist', blacklist); - cfgMap.set('theme', theme); - cbtn.append(resetbtn, savebtn); - cfgpage.append(blacklist, theme, cbtn); + selType.value = type; + lb.append(inp, selType); + listSec.append(lb); + }; + // const addList = make('mujs-add', '', { + // textContent: '+', + // dataset: { + // command: 'new-list' + // } + // }); + // const n = make('input', '', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Name', + // }); + // const inpValue = make('input', '', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Value', + // }); + // const label = make('label', 'new-list hidden', { + // dataset: { + // blacklist: 'new-list' + // } + // }); + // label.append(n, inpValue, addList); + // listSec.append(label); + // ael(addList, 'click', () => { + // if (isEmpty(n.value) || isEmpty(inpValue.value)) { + // return + // }; + // createList(n.value, n.value, inpValue.value); + // }); + + for (const key of cfg.blacklist) { + createList(key); + } + + cfgpage.append(cbtn); + // cfgpage.append(blacklist, theme, cbtn); }; // #endregion container.tab.custom = (host) => { MUList.host = host; - MUList.build(); + respHandles.build(); + // if (cfg.autofetch) { + // respHandles.build(); + // } + // MUList.build(); }; ael(mainframe, 'mouseenter', (evt) => { evt.preventDefault(); @@ -5073,7 +5382,11 @@ function primaryFN() { tabHost.title = ''; tabHost.textContent = ''; MUList.host = val; - MUList.build(); + respHandles.build(); + // if (cfg.autofetch) { + // respHandles.build(); + // } + // MUList.build(); return; } const value = container.getHost(val); @@ -5085,17 +5398,30 @@ function primaryFN() { tabHost.title = value; tabHost.textContent = value; MUList.host = value; - MUList.build(); + respHandles.build(); + // if (cfg.autofetch) { + // respHandles.build(); + // } + // MUList.build(); return; } }); - scheduler.postTask(makecfg, { priority: 'user-visible' }); - scheduler.postTask(MUList.build, { priority: 'background' }).then(timeoutFrame); + scheduler.postTask(makecfg, { priority: 'background' }); + + respHandles.build = async () => { + const time = await scheduler.postTask(MUList.build, { priority: 'background' }); + return timeoutFrame(time); + }; + + if (cfg.autofetch) { + respHandles.build(); + } dbg('Container', container); } catch (ex) { err(ex); container.remove(); } + return respHandles; } // #endregion /** @@ -5125,14 +5451,19 @@ const init = async () => { loadDOM((doc) => { try { if (window.location === null) { - throw new Error('"window.location" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); + throw new Error('"window.location" is null, reload the webpage or use a different one', { + cause: 'loadDOM' + }); } if (doc === null) { - throw new Error('"doc" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); + throw new Error('"doc" is null, reload the webpage or use a different one', { + cause: 'loadDOM' + }); } - setTrust(); + trustedTypes.init(); sleazyRedirect(); - container.inject(primaryFN, doc); + + if (cfg.autoinject) container.inject(primaryFN, doc); Command.register(i18n$('userjs_inject'), () => { container.inject(primaryFN, doc); diff --git a/package.json b/package.json index 2177234..d63164f 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/magicoflolis/Userscript-Plus/issues" }, "userJS": { - "version": "7.1.1", + "version": "7.2.0", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", @@ -106,12 +106,13 @@ }, "devDependencies": { "@swc/cli": "^0.6.0", - "@swc/core": "^1.10.12", - "@types/chrome": "0.0.300", + "@swc/core": "^1.10.14", + "@types/chrome": "0.0.301", "@types/firefox-webext-browser": "120.0.4", "@types/greasemonkey": "4.0.7", - "@types/node": "^22.13.0", + "@types/node": "^22.13.1", "@types/tampermonkey": "^5.0.4", + "@types/trusted-types": "^2.0.7", "@types/webpack": "^5.28.5", "@violentmonkey/types": "0.2.0", "browserslist": "^4.24.4", @@ -133,7 +134,7 @@ "terser-webpack-plugin": "^5.3.11", "typescript": "^5.7.3", "watchpack": "^2.4.2", - "web-ext": "^8.3.0", + "web-ext": "^8.4.0", "webpack": "^5.97.1", "webpack-cli": "^6.0.1", "webpack-merge": "^6.0.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4307bb1..b8ed7a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,13 +10,13 @@ importers: devDependencies: '@swc/cli': specifier: ^0.6.0 - version: 0.6.0(@swc/core@1.10.12) + version: 0.6.0(@swc/core@1.10.14) '@swc/core': - specifier: ^1.10.12 - version: 1.10.12 + specifier: ^1.10.14 + version: 1.10.14 '@types/chrome': - specifier: 0.0.300 - version: 0.0.300 + specifier: 0.0.301 + version: 0.0.301 '@types/firefox-webext-browser': specifier: 120.0.4 version: 120.0.4 @@ -24,14 +24,17 @@ importers: specifier: 4.0.7 version: 4.0.7 '@types/node': - specifier: ^22.13.0 - version: 22.13.0 + specifier: ^22.13.1 + version: 22.13.1 '@types/tampermonkey': specifier: ^5.0.4 version: 5.0.4 + '@types/trusted-types': + specifier: ^2.0.7 + version: 2.0.7 '@types/webpack': specifier: ^5.28.5 - version: 5.28.5(@swc/core@1.10.12)(webpack-cli@6.0.1) + version: 5.28.5(@swc/core@1.10.14)(webpack-cli@6.0.1) '@violentmonkey/types': specifier: 0.2.0 version: 0.2.0 @@ -82,10 +85,10 @@ importers: version: 16.0.4(sass-embedded@1.83.4)(webpack@5.97.1) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.12)(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.14)(webpack@5.97.1) terser-webpack-plugin: specifier: ^5.3.11 - version: 5.3.11(@swc/core@1.10.12)(webpack@5.97.1) + version: 5.3.11(@swc/core@1.10.14)(webpack@5.97.1) typescript: specifier: ^5.7.3 version: 5.7.3 @@ -93,11 +96,11 @@ importers: specifier: ^2.4.2 version: 2.4.2 web-ext: - specifier: ^8.3.0 - version: 8.3.0 + specifier: ^8.4.0 + version: 8.4.0 webpack: specifier: ^5.97.1 - version: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + version: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) webpack-cli: specifier: ^6.0.1 version: 6.0.1(webpack@5.97.1) @@ -123,8 +126,8 @@ packages: resolution: {integrity: sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.25.6': - resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} + '@babel/runtime@7.26.7': + resolution: {integrity: sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==} engines: {node: '>=6.9.0'} '@bufbuild/protobuf@2.2.0': @@ -138,8 +141,8 @@ packages: resolution: {integrity: sha512-ZzZY/b66W2Jd6NHbAhLyDWOEIBWC11VizGFk7Wx7M61JZRz7HR9Cq5P+65RKWUU7u6wgsE8Lmh9nE4Mz+U2eTg==} engines: {node: '>= 0.10.4'} - '@devicefarmer/adbkit@3.2.6': - resolution: {integrity: sha512-8lO1hSeTgtxcOHhp4tTWq/JaOysp5KNbbyFoxNEBnwkCDZu/Bji3ZfOaG++Riv9jN6c9bgdLBOZqJTC5VJPRKQ==} + '@devicefarmer/adbkit@3.3.8': + resolution: {integrity: sha512-7rBLLzWQnBwutH2WZ0EWUkQdihqrnLYCUMaB44hSol9e0/cdIhuNFcqZO0xNheAU6qqHVA8sMiLofkYTgb+lmw==} engines: {node: '>= 0.10.4'} hasBin: true @@ -193,6 +196,10 @@ packages: resolution: {integrity: sha512-5D2qVpZrgpjtqU4eNOcWGp1gnUCgjfM+vKGE2y03kKN6z5EBhtx0qdRFbg8QuNNj8wXNoX93KJoYb+NqoxswmQ==} engines: {node: '>=14.0.0', npm: '>=7.0.0'} + '@fregante/relaxed-json@2.0.0': + resolution: {integrity: sha512-PyUXQWB42s4jBli435TDiYuVsadwRHnMc27YaLouINktvTWsL3FcKrRMGawTayFk46X+n5bE23RjUTWQwrukWw==} + engines: {node: '>= 0.10.0'} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -243,8 +250,8 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@mdn/browser-compat-data@5.6.0': - resolution: {integrity: sha512-xArvLyzuk0r2m6hFVjTMYoLvhWwys3h7W8pO15tjSAea+U39cErWDNfoUs4g2C08HVg6bDHyDMBc0LC6FKRpVw==} + '@mdn/browser-compat-data@5.6.31': + resolution: {integrity: sha512-E/X4YlErVjBCMvaJbqD2Jb0B/Z+TQJyw4vN6q98iit05RLW9VEcsedaTiL81BAbYF9GICn/KpFGE9dMJi66Ydw==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -292,68 +299,68 @@ packages: chokidar: optional: true - '@swc/core-darwin-arm64@1.10.12': - resolution: {integrity: sha512-pOANQegUTAriW7jq3SSMZGM5l89yLVMs48R0F2UG6UZsH04SiViCnDctOGlA/Sa++25C+rL9MGMYM1jDLylBbg==} + '@swc/core-darwin-arm64@1.10.14': + resolution: {integrity: sha512-Dh4VyrhDDb05tdRmqJ/MucOPMTnrB4pRJol18HVyLlqu1HOT5EzonUniNTCdQbUXjgdv5UVJSTE1lYTzrp+myA==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.10.12': - resolution: {integrity: sha512-m4kbpIDDsN1FrwfNQMU+FTrss356xsXvatLbearwR+V0lqOkjLBP0VmRvQfHEg+uy13VPyrT9gj4HLoztlci7w==} + '@swc/core-darwin-x64@1.10.14': + resolution: {integrity: sha512-KpzotL/I0O12RE3tF8NmQErINv0cQe/0mnN/Q50ESFzB5kU6bLgp2HMnnwDTm/XEZZRJCNe0oc9WJ5rKbAJFRQ==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.10.12': - resolution: {integrity: sha512-OY9LcupgqEu8zVK+rJPes6LDJJwPDmwaShU96beTaxX2K6VrXbpwm5WbPS/8FfQTsmpnuA7dCcMPUKhNgmzTrQ==} + '@swc/core-linux-arm-gnueabihf@1.10.14': + resolution: {integrity: sha512-20yRXZjMJVz1wp1TcscKiGTVXistG+saIaxOmxSNQia1Qun3hSWLL+u6+5kXbfYGr7R2N6kqSwtZbIfJI25r9Q==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.10.12': - resolution: {integrity: sha512-nJD587rO0N4y4VZszz3xzVr7JIiCzSMhEMWnPjuh+xmPxDBz0Qccpr8xCr1cSxpl1uY7ERkqAGlKr6CwoV5kVg==} + '@swc/core-linux-arm64-gnu@1.10.14': + resolution: {integrity: sha512-Gy7cGrNkiMfPxQyLGxdgXPwyWzNzbHuWycJFcoKBihxZKZIW8hkPBttkGivuLC+0qOgsV2/U+S7tlvAju7FtmQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.10.12': - resolution: {integrity: sha512-oqhSmV+XauSf0C//MoQnVErNUB/5OzmSiUzuazyLsD5pwqKNN+leC3JtRQ/QVzaCpr65jv9bKexT9+I2Tt3xDw==} + '@swc/core-linux-arm64-musl@1.10.14': + resolution: {integrity: sha512-+oYVqJvFw62InZ8PIy1rBACJPC2WTe4vbVb9kM1jJj2D7dKLm9acnnYIVIDsM5Wo7Uab8RvPHXVbs19IBurzuw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.10.12': - resolution: {integrity: sha512-XldSIHyjD7m1Gh+/8rxV3Ok711ENLI420CU2EGEqSe3VSGZ7pHJvJn9ZFbYpWhsLxPqBYMFjp3Qw+J6OXCPXCA==} + '@swc/core-linux-x64-gnu@1.10.14': + resolution: {integrity: sha512-OmEbVEKQFLQVHwo4EJl9osmlulURy46k232Opfpn/1ji0t2KcNCci3POsnfMuoZjLkGJv8vGNJdPQxX+CP+wSA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.10.12': - resolution: {integrity: sha512-wvPXzJxzPgTqhyp1UskOx1hRTtdWxlyFD1cGWOxgLsMik0V9xKRgqKnMPv16Nk7L9xl6quQ6DuUHj9ID7L3oVw==} + '@swc/core-linux-x64-musl@1.10.14': + resolution: {integrity: sha512-OZW+Icm8DMPqHbhdxplkuG8qrNnPk5i7xJOZWYi1y5bTjgGFI4nEzrsmmeHKMdQTaWwsFrm3uK1rlyQ48MmXmg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.10.12': - resolution: {integrity: sha512-TUYzWuu1O7uyIcRfxdm6Wh1u+gNnrW5M1DUgDOGZLsyQzgc2Zjwfh2llLhuAIilvCVg5QiGbJlpibRYJ/8QGsg==} + '@swc/core-win32-arm64-msvc@1.10.14': + resolution: {integrity: sha512-sTvc+xrDQXy3HXZFtTEClY35Efvuc3D+busYm0+rb1+Thau4HLRY9WP+sOKeGwH9/16rzfzYEqD7Ds8A9ykrHw==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.10.12': - resolution: {integrity: sha512-4Qrw+0Xt+Fe2rz4OJ/dEPMeUf/rtuFWWAj/e0vL7J5laUHirzxawLRE5DCJLQTarOiYR6mWnmadt9o3EKzV6Xg==} + '@swc/core-win32-ia32-msvc@1.10.14': + resolution: {integrity: sha512-j2iQ4y9GWTKtES5eMU0sDsFdYni7IxME7ejFej25Tv3Fq4B+U9tgtYWlJwh1858nIWDXelHiKcSh/UICAyVMdQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.10.12': - resolution: {integrity: sha512-YiloZXLW7rUxJpALwHXaGjVaAEn+ChoblG7/3esque+Y7QCyheoBUJp2DVM1EeVA43jBfZ8tvYF0liWd9Tpz1A==} + '@swc/core-win32-x64-msvc@1.10.14': + resolution: {integrity: sha512-TYtWkUSMkjs0jGPeWdtWbex4B+DlQZmN/ySVLiPI+EltYCLEXsFMkVFq6aWn48dqFHggFK0UYfvDrJUR2c3Qxg==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.10.12': - resolution: {integrity: sha512-+iUL0PYpPm6N9AdV1wvafakvCqFegQus1aoEDxgFsv3/uNVNIyRaupf/v/Zkp5hbep2EzhtoJR0aiJIzDbXWHg==} + '@swc/core@1.10.14': + resolution: {integrity: sha512-WSrnE6JRnH20ZYjOOgSS4aOaPv9gxlkI2KRkN24kagbZnPZMnN8bZZyzw1rrLvwgpuRGv17Uz+hflosbR+SP6w==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '*' @@ -374,8 +381,8 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@types/chrome@0.0.300': - resolution: {integrity: sha512-vS5bUmNjMrbPut43Q8plS8GTAiJE+pBOxw1ovGC4LcwiGNKTithAH7TxhzHeX4wNq/FsaLj5KaW7riI0CgYjIg==} + '@types/chrome@0.0.301': + resolution: {integrity: sha512-BljW7InXXOfDYr4nG79y5lnaklrZ0gmeTwCUkuCXK2+69dHnZIrg13KhXJE/HrcFUmy8NG/EK+RTGScsh/Hbiw==} '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -413,12 +420,15 @@ packages: '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - '@types/node@22.13.0': - resolution: {integrity: sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==} + '@types/node@22.13.1': + resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==} '@types/tampermonkey@5.0.4': resolution: {integrity: sha512-HEJ0O5CkDZSwIgd9Zip4xM8o7gZC8zBmJuH1YEXNINIC+aCWEXD10pnpo3NQG5IWHx+Xr4fMSGq1jqeKXH2lpA==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/webpack@5.28.5': resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==} @@ -566,19 +576,19 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - addons-linter@7.1.0: - resolution: {integrity: sha512-UmkUB3dZSpf8bqhlulGDbpoxBwcfOk8JvaJTRvJ+AAXKHvTjqeNlFC+GRMqa0EjJJh/0yqpBaJzyaUIx+fjl+A==} + addons-linter@7.8.0: + resolution: {integrity: sha512-SnDJUAtrHu1RUMIiIZXNN8wF0ze7IbDokwUy5HZYlCkNTn8E4RcI74xhdHtCdtoQprAmyhxePP/hFf+9XPhe8w==} engines: {node: '>=18.0.0'} hasBin: true addons-moz-compare@1.3.0: resolution: {integrity: sha512-/rXpQeaY0nOKhNx00pmZXdk5Mu+KhVlL3/pSBuAYwrxRrNiTvI/9xfQI8Lmm7DMMl+PDhtfAHY/0ibTpdeoQQQ==} - addons-scanner-utils@9.11.0: - resolution: {integrity: sha512-X95V8ymnue9EHmOLz3zJTGHvHDFlWKiavlH+kJKOlv2sJDWFvD3TWeJMHJgxS9GKOqT/545mOXvX3vuuGGum+g==} + addons-scanner-utils@9.12.0: + resolution: {integrity: sha512-Nn+mOgJhdSZKkycXd5GYfSfoyT1lEGbCVoCBKriEFceuP0dJxVBuFwuRD8+PuXegQQBw7COTS5DwM4nj+bK8Mg==} peerDependencies: - body-parser: 1.20.2 - express: 4.19.2 + body-parser: 1.20.3 + express: 4.21.0 node-fetch: 2.6.11 safe-compare: 1.1.4 peerDependenciesMeta: @@ -1045,9 +1055,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - enhanced-resolve@5.17.1: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} @@ -1092,10 +1099,10 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-no-unsanitized@4.0.2: - resolution: {integrity: sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==} + eslint-plugin-no-unsanitized@4.1.2: + resolution: {integrity: sha512-ydF3PMFKEIkP71ZbLHFvu6/FW8SvRv6VV/gECfrQkqyD5+5oCAtPz8ZHy0GRuMDtNe2jsNdPCQXX4LSbkapAVQ==} peerDependencies: - eslint: ^6 || ^7 || ^8 + eslint: ^8 || ^9 eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} @@ -1113,10 +1120,6 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@4.2.0: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1137,10 +1140,6 @@ packages: jiti: optional: true - espree@10.1.0: - resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@10.3.0: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1185,10 +1184,6 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@4.1.0: - resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} - engines: {node: '>=10'} - execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -1339,10 +1334,6 @@ packages: get-intrinsic@1.2.0: resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} - get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -1452,10 +1443,6 @@ packages: resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} engines: {node: '>= 14'} - human-signals@1.1.1: - resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} - engines: {node: '>=8.12.0'} - human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -1481,8 +1468,8 @@ packages: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} - image-size@1.1.1: - resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==} + image-size@1.2.0: + resolution: {integrity: sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==} engines: {node: '>=16.x'} hasBin: true @@ -1530,10 +1517,6 @@ packages: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} - invert-kv@3.0.1: - resolution: {integrity: sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==} - engines: {node: '>=8'} - is-absolute@0.1.7: resolution: {integrity: sha512-Xi9/ZSn4NFapG8RP98iNPMOeaV3mXPisxKxzKtHVqr3g56j/fBn+yZmnxSVAA8lmZbl2J9b/a4kJvfU3hqQYgA==} engines: {node: '>=0.10.0'} @@ -1640,15 +1623,12 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - jed@1.1.1: - resolution: {integrity: sha512-z35ZSEcXHxLW4yumw0dF6L464NT36vmx3wxJw8MDpraBcWuNVgUPZgPJKcu1HekNgwlMFNqol7i/IpSbjhqwqA==} - jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} - jose@5.9.2: - resolution: {integrity: sha512-ILI2xx/I57b20sd7rHZvgiiQrmp2mcotwsAH+5ajbpFQbrYVQdNHYlQhoA5cFb78CgtBOxtC05TeA+mcgkuCqQ==} + jose@5.9.6: + resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1700,10 +1680,6 @@ packages: resolution: {integrity: sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==} engines: {node: '>=18'} - lcid@3.1.1: - resolution: {integrity: sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==} - engines: {node: '>=8'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1751,17 +1727,9 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - map-age-cleaner@0.1.3: - resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} - engines: {node: '>=6'} - marky@1.2.5: resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} - mem@5.1.1: - resolution: {integrity: sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==} - engines: {node: '>=8'} - merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1922,10 +1890,6 @@ packages: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} - os-locale@5.0.0: - resolution: {integrity: sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==} - engines: {node: '>=10'} - os-shim@0.1.3: resolution: {integrity: sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==} engines: {node: '>= 0.4.0'} @@ -1934,14 +1898,6 @@ packages: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} engines: {node: '>=12.20'} - p-defer@1.0.0: - resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} - engines: {node: '>=4'} - - p-is-promise@2.1.0: - resolution: {integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==} - engines: {node: '>=6'} - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -2030,9 +1986,6 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - pino-abstract-transport@1.1.0: - resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} - pino-abstract-transport@1.2.0: resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} @@ -2128,9 +2081,6 @@ packages: protocol-buffers-schema@3.6.0: resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} - pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -2192,11 +2142,6 @@ packages: resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} engines: {node: '>=12'} - relaxed-json@1.0.3: - resolution: {integrity: sha512-b7wGPo7o2KE/g7SqkJDDbav6zmrEeP4TK2VpITU72J/M949TLe/23y/ZHJo+pskcGM52xIfFoT9hydwmgr1AEg==} - engines: {node: '>= 0.10.0'} - hasBin: true - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -2779,8 +2724,8 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - web-ext@8.3.0: - resolution: {integrity: sha512-mXSOiDtmm3n0KNpSuQ65fJpypAoNLAmZv3QkdlVbJ6etn0BK+hl/k+tjHefSIKdbzGUIeFbhn2oxWMe9Tdyrdg==} + web-ext@8.4.0: + resolution: {integrity: sha512-zO0GNacJeqw3fwbBvgHC2G8reieyN+oCKiMQepX3iv2fm9KEBqg1gdbcdEvi7edfj+gjgxyXhVlFcHIvcEM2Cg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2930,7 +2875,7 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.0 - '@babel/runtime@7.25.6': + '@babel/runtime@7.26.7': dependencies: regenerator-runtime: 0.14.1 @@ -2940,7 +2885,7 @@ snapshots: '@devicefarmer/adbkit-monkey@1.2.1': {} - '@devicefarmer/adbkit@3.2.6': + '@devicefarmer/adbkit@3.3.8': dependencies: '@devicefarmer/adbkit-logcat': 2.1.2 '@devicefarmer/adbkit-monkey': 1.2.1 @@ -3019,6 +2964,8 @@ snapshots: '@fluent/syntax@0.19.0': {} + '@fregante/relaxed-json@2.0.0': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -3064,7 +3011,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - '@mdn/browser-compat-data@5.6.0': {} + '@mdn/browser-compat-data@5.6.31': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -3096,9 +3043,9 @@ snapshots: '@sindresorhus/merge-streams@2.3.0': {} - '@swc/cli@0.6.0(@swc/core@1.10.12)': + '@swc/cli@0.6.0(@swc/core@1.10.14)': dependencies: - '@swc/core': 1.10.12 + '@swc/core': 1.10.14 '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 @@ -3109,51 +3056,51 @@ snapshots: slash: 3.0.0 source-map: 0.7.4 - '@swc/core-darwin-arm64@1.10.12': + '@swc/core-darwin-arm64@1.10.14': optional: true - '@swc/core-darwin-x64@1.10.12': + '@swc/core-darwin-x64@1.10.14': optional: true - '@swc/core-linux-arm-gnueabihf@1.10.12': + '@swc/core-linux-arm-gnueabihf@1.10.14': optional: true - '@swc/core-linux-arm64-gnu@1.10.12': + '@swc/core-linux-arm64-gnu@1.10.14': optional: true - '@swc/core-linux-arm64-musl@1.10.12': + '@swc/core-linux-arm64-musl@1.10.14': optional: true - '@swc/core-linux-x64-gnu@1.10.12': + '@swc/core-linux-x64-gnu@1.10.14': optional: true - '@swc/core-linux-x64-musl@1.10.12': + '@swc/core-linux-x64-musl@1.10.14': optional: true - '@swc/core-win32-arm64-msvc@1.10.12': + '@swc/core-win32-arm64-msvc@1.10.14': optional: true - '@swc/core-win32-ia32-msvc@1.10.12': + '@swc/core-win32-ia32-msvc@1.10.14': optional: true - '@swc/core-win32-x64-msvc@1.10.12': + '@swc/core-win32-x64-msvc@1.10.14': optional: true - '@swc/core@1.10.12': + '@swc/core@1.10.14': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.17 optionalDependencies: - '@swc/core-darwin-arm64': 1.10.12 - '@swc/core-darwin-x64': 1.10.12 - '@swc/core-linux-arm-gnueabihf': 1.10.12 - '@swc/core-linux-arm64-gnu': 1.10.12 - '@swc/core-linux-arm64-musl': 1.10.12 - '@swc/core-linux-x64-gnu': 1.10.12 - '@swc/core-linux-x64-musl': 1.10.12 - '@swc/core-win32-arm64-msvc': 1.10.12 - '@swc/core-win32-ia32-msvc': 1.10.12 - '@swc/core-win32-x64-msvc': 1.10.12 + '@swc/core-darwin-arm64': 1.10.14 + '@swc/core-darwin-x64': 1.10.14 + '@swc/core-linux-arm-gnueabihf': 1.10.14 + '@swc/core-linux-arm64-gnu': 1.10.14 + '@swc/core-linux-arm64-musl': 1.10.14 + '@swc/core-linux-x64-gnu': 1.10.14 + '@swc/core-linux-x64-musl': 1.10.14 + '@swc/core-win32-arm64-msvc': 1.10.14 + '@swc/core-win32-ia32-msvc': 1.10.14 + '@swc/core-win32-x64-msvc': 1.10.14 '@swc/counter@0.1.3': {} @@ -3167,7 +3114,7 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@types/chrome@0.0.300': + '@types/chrome@0.0.301': dependencies: '@types/filesystem': 0.0.32 '@types/har-format': 1.2.10 @@ -3204,17 +3151,19 @@ snapshots: '@types/minimatch@3.0.5': {} - '@types/node@22.13.0': + '@types/node@22.13.1': dependencies: undici-types: 6.20.0 '@types/tampermonkey@5.0.4': {} - '@types/webpack@5.28.5(@swc/core@1.10.12)(webpack-cli@6.0.1)': + '@types/trusted-types@2.0.7': {} + + '@types/webpack@5.28.5(@swc/core@1.10.14)(webpack-cli@6.0.1)': dependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 tapable: 2.2.1 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -3223,7 +3172,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 '@ungap/structured-clone@1.2.0': {} @@ -3307,17 +3256,17 @@ snapshots: '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': dependencies: - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack@5.97.1) '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': dependencies: - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack@5.97.1) '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': dependencies: - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack@5.97.1) '@xhmikosr/archive-type@7.0.0': @@ -3404,12 +3353,13 @@ snapshots: acorn@8.14.0: {} - addons-linter@7.1.0: + addons-linter@7.8.0: dependencies: '@fluent/syntax': 0.19.0 - '@mdn/browser-compat-data': 5.6.0 + '@fregante/relaxed-json': 2.0.0 + '@mdn/browser-compat-data': 5.6.31 addons-moz-compare: 1.3.0 - addons-scanner-utils: 9.11.0 + addons-scanner-utils: 9.12.0 ajv: 8.17.1 chalk: 4.1.2 cheerio: 1.0.0-rc.12 @@ -3417,17 +3367,14 @@ snapshots: common-tags: 1.8.2 deepmerge: 4.3.1 eslint: 8.57.1 - eslint-plugin-no-unsanitized: 4.0.2(eslint@8.57.1) - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 + eslint-plugin-no-unsanitized: 4.1.2(eslint@8.57.1) + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 esprima: 4.0.1 fast-json-patch: 3.1.1 - image-size: 1.1.1 - jed: 1.1.1 + image-size: 1.2.0 json-merge-patch: 1.0.2 - os-locale: 5.0.0 pino: 8.20.0 - relaxed-json: 1.0.3 semver: 7.6.3 source-map-support: 0.5.21 upath: 2.0.1 @@ -3442,7 +3389,7 @@ snapshots: addons-moz-compare@1.3.0: {} - addons-scanner-utils@9.11.0: + addons-scanner-utils@9.12.0: dependencies: '@types/yauzl': 2.10.3 common-tags: 1.8.2 @@ -3683,7 +3630,7 @@ snapshots: chrome-launcher@1.1.2: dependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.1 @@ -3788,7 +3735,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) core-util-is@1.0.3: {} @@ -3823,7 +3770,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.5.4 optionalDependencies: - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) css-select@5.1.0: dependencies: @@ -3919,10 +3866,6 @@ snapshots: emoji-regex@8.0.0: {} - end-of-stream@1.4.4: - dependencies: - once: 1.4.0 - enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 @@ -3952,7 +3895,7 @@ snapshots: dependencies: eslint: 9.19.0 - eslint-plugin-no-unsanitized@4.0.2(eslint@8.57.1): + eslint-plugin-no-unsanitized@4.1.2(eslint@8.57.1): dependencies: eslint: 8.57.1 @@ -3973,8 +3916,6 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.0.0: {} - eslint-visitor-keys@4.2.0: {} eslint@8.57.1: @@ -4059,12 +4000,6 @@ snapshots: transitivePeerDependencies: - supports-color - espree@10.1.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - espree@10.3.0: dependencies: acorn: 8.14.0 @@ -4099,18 +4034,6 @@ snapshots: events@3.3.0: {} - execa@4.1.0: - dependencies: - cross-spawn: 7.0.6 - get-stream: 5.2.0 - human-signals: 1.1.1 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -4272,10 +4195,6 @@ snapshots: has: 1.0.3 has-symbols: 1.0.3 - get-stream@5.2.0: - dependencies: - pump: 3.0.0 - get-stream@6.0.1: {} get-stream@9.0.1: @@ -4411,8 +4330,6 @@ snapshots: transitivePeerDependencies: - supports-color - human-signals@1.1.1: {} - human-signals@2.1.0: {} human-signals@4.3.1: {} @@ -4429,7 +4346,7 @@ snapshots: ignore@5.2.4: {} - image-size@1.1.1: + image-size@1.2.0: dependencies: queue: 6.0.2 @@ -4468,8 +4385,6 @@ snapshots: interpret@3.1.1: {} - invert-kv@3.0.1: {} - is-absolute@0.1.7: dependencies: is-relative: 0.1.3 @@ -4539,15 +4454,13 @@ snapshots: isobject@3.0.1: {} - jed@1.1.1: {} - jest-worker@27.5.1: dependencies: - '@types/node': 22.13.0 + '@types/node': 22.13.1 merge-stream: 2.0.0 supports-color: 8.1.1 - jose@5.9.2: {} + jose@5.9.6: {} js-tokens@4.0.0: {} @@ -4596,10 +4509,6 @@ snapshots: dependencies: package-json: 10.0.1 - lcid@3.1.1: - dependencies: - invert-kv: 3.0.1 - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4644,18 +4553,8 @@ snapshots: make-error@1.3.6: {} - map-age-cleaner@0.1.3: - dependencies: - p-defer: 1.0.0 - marky@1.2.5: {} - mem@5.1.1: - dependencies: - map-age-cleaner: 0.1.3 - mimic-fn: 2.1.0 - p-is-promise: 2.1.0 - merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -4685,7 +4584,7 @@ snapshots: dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) minimatch@3.1.2: dependencies: @@ -4799,20 +4698,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - os-locale@5.0.0: - dependencies: - execa: 4.1.0 - lcid: 3.1.1 - mem: 5.1.1 - os-shim@0.1.3: {} p-cancelable@3.0.0: {} - p-defer@1.0.0: {} - - p-is-promise@2.1.0: {} - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -4890,11 +4779,6 @@ snapshots: picomatch@2.3.1: {} - pino-abstract-transport@1.1.0: - dependencies: - readable-stream: 4.3.0 - split2: 4.1.0 - pino-abstract-transport@1.2.0: dependencies: readable-stream: 4.3.0 @@ -4909,7 +4793,7 @@ snapshots: atomic-sleep: 1.0.0 fast-redact: 3.1.2 on-exit-leak-free: 2.1.0 - pino-abstract-transport: 1.1.0 + pino-abstract-transport: 1.2.0 pino-std-serializers: 6.1.0 process-warning: 3.0.0 quick-format-unescaped: 4.0.4 @@ -5002,11 +4886,6 @@ snapshots: protocol-buffers-schema@3.6.0: {} - pump@3.0.0: - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - punycode@2.3.0: {} pupa@3.1.0: @@ -5037,7 +4916,7 @@ snapshots: dependencies: deep-extend: 0.6.0 ini: 1.3.8 - minimist: 1.2.7 + minimist: 1.2.8 strip-json-comments: 2.0.1 readable-stream@2.3.7: @@ -5073,11 +4952,6 @@ snapshots: dependencies: rc: 1.2.8 - relaxed-json@1.0.3: - dependencies: - chalk: 2.4.2 - commander: 2.20.3 - require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -5231,7 +5105,7 @@ snapshots: neo-async: 2.6.2 optionalDependencies: sass-embedded: 1.83.4 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) sax@1.2.4: {} @@ -5424,11 +5298,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swc-loader@0.2.6(@swc/core@1.10.12)(webpack@5.97.1): + swc-loader@0.2.6(@swc/core@1.10.14)(webpack@5.97.1): dependencies: - '@swc/core': 1.10.12 + '@swc/core': 1.10.14 '@swc/counter': 0.1.3 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) sync-child-process@1.0.2: dependencies: @@ -5444,16 +5318,16 @@ snapshots: fast-fifo: 1.3.2 streamx: 2.21.1 - terser-webpack-plugin@5.3.11(@swc/core@1.10.12)(webpack@5.97.1): + terser-webpack-plugin@5.3.11(@swc/core@1.10.14)(webpack@5.97.1): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) optionalDependencies: - '@swc/core': 1.10.12 + '@swc/core': 1.10.14 terser@5.37.0: dependencies: @@ -5570,11 +5444,11 @@ snapshots: dependencies: defaults: 1.0.4 - web-ext@8.3.0: + web-ext@8.4.0: dependencies: - '@babel/runtime': 7.25.6 - '@devicefarmer/adbkit': 3.2.6 - addons-linter: 7.1.0 + '@babel/runtime': 7.26.7 + '@devicefarmer/adbkit': 3.3.8 + addons-linter: 7.8.0 camelcase: 8.0.0 chrome-launcher: 1.1.2 debounce: 1.2.1 @@ -5583,7 +5457,7 @@ snapshots: firefox-profile: 4.7.0 fx-runner: 1.4.0 https-proxy-agent: 7.0.5 - jose: 5.9.2 + jose: 5.9.6 jszip: 3.10.1 multimatch: 6.0.0 node-notifier: 10.0.1 @@ -5623,7 +5497,7 @@ snapshots: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1) + webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) webpack-merge: 6.0.1 webpack-merge@6.0.1: @@ -5634,7 +5508,7 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.97.1(@swc/core@1.10.12)(webpack-cli@6.0.1): + webpack@5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.6 @@ -5656,7 +5530,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.12)(webpack@5.97.1) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.14)(webpack@5.97.1) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: diff --git a/src/UserJS/main.js b/src/UserJS/main.js index 8beb5c8..4d88413 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -125,19 +125,28 @@ function safeSelf() { return userjs.safeSelf; } -let trusedPolicy = false; -function setTrust() { - if (trusedPolicy) { - return; - } - if (window.trustedTypes && window.trustedTypes.createPolicy) { - window.trustedTypes.createPolicy('default', { - createHTML: (string) => string - }); - trusedPolicy = true; +const trustedTypes = { + policy: false, + init() { + if (this.policy) { + return this.policy; + } + this.policy = true; + try { + // Native implementation exists + if (window.trustedTypes && window.trustedTypes.createPolicy) { + window.trustedTypes.createPolicy('default', { + createHTML: (string) => string + }); + } + } catch (ex) { + ex.cause = 'trustedTypes.init()'; + err(ex); + } + return this.policy; } -} -setTrust(); +}; +trustedTypes.init(); const BLANK_PAGE = 'about:blank'; // Lets highlight me :) @@ -209,6 +218,8 @@ const builtinList = { * @type { import("../typings/types.d.ts").config } */ const DEFAULT_CONFIG = { + autofetch: true, + autoinject: true, cache: true, codePreview: false, autoexpand: false, @@ -1101,6 +1112,8 @@ class Container { mouse: new Timeout() }; + this.injFN = () => {} + window.addEventListener('beforeunload', this.remove); } /** @@ -1126,6 +1139,9 @@ class Container { try { doc.documentElement.appendChild(this.frame); if (this.injected) { + if (isFN(this.injFN.build)) { + this.injFN.build(); + } return; } this.shadowRoot.append(this.root); @@ -1135,7 +1151,7 @@ class Container { this.injected = true; this.initFn(); if (this.elementsReady && isFN(callback)) { - callback.call(this, this.shadowRoot); + this.injFN = callback.call(this, this.shadowRoot); } } catch (ex) { err(ex); @@ -1252,8 +1268,6 @@ class Container { this.intFN(host); } else { this.custom(host); - // MUList.host = host; - // MUList.build(); } } } @@ -1529,7 +1543,7 @@ class Container { async save() { this.unsaved = false; await StorageSystem.setValue('Config', cfg); - info('Saved:', cfg); + info('Saved config:', cfg); return cfg; } /** @@ -1703,17 +1717,17 @@ class Container { } showError(...ex) { err(...ex); - const { createTextNode } = safeSelf(); const error = make('mu-js', 'error'); let str = ''; for (const e of ex) { - str += `${typeof e === 'string' ? e : `${e.cause ? `[${e.cause}] ` : ''}${e.message} ${e.stack ?? ''}`}\n`; + str += `${typeof e === 'string' ? e : `${e.cause ? `[${e.cause}] ` : ''}${e.message}${e.stack ? ` ${e.stack}` : ''}`}\n`; if (isObj(e)) { if (e.notify) { dom.cl.add(this.mainframe, 'error'); } } } + const { createTextNode } = safeSelf(); error.appendChild(createTextNode(str)); this.footer.append(error); } @@ -1750,6 +1764,9 @@ const container = new Container(); // #endregion // #region Primary Function function primaryFN() { + const respHandles = { + build: async () => {} + }; try { const { scheduler } = safeSelf(); const { @@ -1798,8 +1815,13 @@ function primaryFN() { } } } - dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); - dom.prop(cfgMap.get('theme'), 'value', JSON.stringify(cfg.theme, null, ' ')); + // dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); + // for (const [k, v] of Object.entries(cfg.blacklist)) { + // dom.prop(cfgMap.get(k), 'value', v); + // } + for (const [k, v] of Object.entries(cfg.theme)) { + dom.prop(cfgMap.get(k), 'value', v); + } container.renderTheme(cfg.theme); }; const doInstallProcess = async (installLink) => { @@ -1907,11 +1929,13 @@ function primaryFN() { container.rebuild = true; dom.prop(rateContainer, 'innerHTML', ''); if (!dom.prop(target, 'disabled')) { - container.save(); + const config = await container.save(); sleazyRedirect(); if (container.rebuild) { container.cache.clear(); - MUList.build(); + if (config.autofetch) { + respHandles.build(); + } } container.unsaved = false; container.rebuild = false; @@ -2069,12 +2093,21 @@ function primaryFN() { container.unsaved = true; container.rebuild = true; rebuildCfg(); - container.save(); - sleazyRedirect(); - container.cache.clear(); - MUList.build(); - container.unsaved = false; - container.rebuild = false; + container.save().then((config) => { + sleazyRedirect(); + container.cache.clear(); + if (config.autofetch) { + respHandles.build(); + }; + container.unsaved = false; + container.rebuild = false; + }); + // container.save(); + // sleazyRedirect(); + // container.cache.clear(); + // MUList.build(); + // container.unsaved = false; + // container.rebuild = false; } else { log(`Imported theme: { ${file.name} }`, result); cfg.theme = result; @@ -2724,6 +2757,10 @@ function primaryFN() { codeArea.value = code_obj.get_code_block(); } + if (ujs._mujs.code?.translated) { + tr.classList.add('translated'); + } + for (const e of [fname, uframe, fdaily, fupdated, eframe]) { tr.append(e); } @@ -2811,7 +2848,11 @@ function primaryFN() { updateCounter(cEngine.length, engine); continue; } + // if (!cfg.autofetch) { + // continue; + // } const respError = (error) => { + if (!error.cause) error.cause = engine.name; if (error.message.startsWith('429')) { showError(`Engine: "${engine.name}" Too many requests...`); return; @@ -3147,6 +3188,43 @@ function primaryFN() { // #endregion // #region Make Config const makecfg = () => { + const makesection = (name, tag) => { + tag = tag ?? i18n$('no_license'); + name = name ?? i18n$('no_license'); + const sec = make('mujs-section', '', { + dataset: { + name: tag + } + }); + const lb = make('label', '', { + dataset: { + command: tag + } + }); + const divDesc = make('mu-js', '', { + textContent: name + }); + ael(sec, 'click', (evt) => { + /** @type { HTMLElement } */ + const target = evt.target.closest('[data-command]'); + if (!target) { + return; + } + const cmd = target.dataset.command; + if (cmd === tag) { + const a = qsA(`label[data-${tag}]`, sec); + if (dom.cl.has(a, 'hidden')) { + dom.cl.remove(a, 'hidden'); + } else { + dom.cl.add(a, 'hidden'); + } + } + }); + lb.append(divDesc); + sec.append(lb); + cfgpage.append(sec); + return sec; + }; const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); @@ -3256,8 +3334,10 @@ function primaryFN() { return inp; }; if (isGM) { - makerow('Sync with GM', 'checkbox', 'cache'); + makerow(i18n$('userjs_sync'), 'checkbox', 'cache'); + makerow(i18n$('userjs_autoinject'), 'checkbox', 'autoinject'); } + makerow(i18n$('auto_fetch'), 'checkbox', 'autofetch'); makerow(i18n$('userjs_fullscreen'), 'checkbox', 'autoexpand', { onchange(e) { if (e.target.checked) { @@ -3328,72 +3408,228 @@ function primaryFN() { command: 'reset' } }); - const blacklist = make('textarea', '', { - dataset: { - name: 'blacklist' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.blacklist, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.blacklist = JSON.parse(evt.target.value); - isvalid = true; - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); + // const blacklist = make('textarea', '', { + // dataset: { + // name: 'blacklist' + // }, + // rows: '10', + // autocomplete: false, + // spellcheck: false, + // wrap: 'soft', + // value: JSON.stringify(cfg.blacklist, null, ' '), + // oninput(evt) { + // let isvalid = true; + // try { + // cfg.blacklist = JSON.parse(evt.target.value); + // isvalid = true; + // } catch (ex) { + // err(ex); + // isvalid = false; + // } finally { + // if (isvalid) { + // dom.cl.remove(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', false); + // } else { + // dom.cl.add(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', true); + // } + // } + // } + // }); + // cfgMap.set('blacklist', blacklist); + cbtn.append(resetbtn, savebtn); + + const themeSec = makesection('Theme Colors', 'theme'); + for (const [k, v] of Object.entries(cfg.theme)) { + cfgMap.set(k, v); + const lb = make('label', 'hidden', { + textContent: k, + dataset: { + theme: k + } + }); + const inp = make('input', '', { + type: 'text', + defaultValue: '', + value: v ?? '', + placeholder: v ?? '', + dataset: { + theme: k + }, + onchange(evt) { + let isvalid = true; + try { + const val = evt.target.value; + const sty = container.root.style; + const str = `--mujs-${k}`; + const prop = sty.getPropertyValue(str); + if (isEmpty(val)) { + cfg.theme[k] = DEFAULT_CONFIG.theme[k]; + cfgMap.set(k, DEFAULT_CONFIG.theme[k]); + sty.removeProperty(str); + return; + } + if (prop === val) { + return; + } + sty.removeProperty(str); + sty.setProperty(str, val); + cfg.theme[k] = val; + cfgMap.set(k, val); + } catch (ex) { + err(ex); + isvalid = false; + } finally { + if (isvalid) { + dom.cl.remove(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', false); + } else { + dom.cl.add(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', true); + } } } + }); + lb.append(inp); + themeSec.append(lb); + } + + const listSec = makesection('Blacklist (WIP)', 'blacklist'); + const createList = (key, v = '', disabled = false, type = 'String') => { + let txt = key; + if (typeof key === 'string') { + if (key.startsWith('userjs-')) { + disabled = true; + const s = key.substring(7); + txt = `Built-in "${s}"`; + v = builtinList[s]; + }; + } else { + if (!key.enabled) { + return; + } } - }); - const theme = make('textarea', '', { - dataset: { - name: 'theme' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.theme, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.theme = JSON.parse(evt.target.value); - container.renderTheme(JSON.parse(evt.target.value)); - isvalid = true; - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); + + if (isRegExp(v)) { + v = v.toString(); + type = 'RegExp'; + } else { + v = JSON.stringify(v); + type = 'Object'; + } + + const lb = make('label', 'hidden', { + textContent: txt, + dataset: { + blacklist: key + } + }); + const inp = make('input', '', { + type: 'text', + defaultValue: '', + value: v ?? '', + placeholder: v ?? '', + dataset: { + blacklist: key + }, + onchange(evt) { + let isvalid = true; + try { + const val = evt.target.value; + if (isEmpty(val)) { + return; + } + // if (isRegExp(val)) { + // v = val.toString(); + // }; + isvalid = true; + } catch (ex) { + err(ex); + isvalid = false; + } finally { + if (isvalid) { + dom.cl.remove(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', false); + } else { + dom.cl.add(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', true); + } } } + }); + const selType = make('select', '', { + disabled, + dataset: { + blacklist: key + } + }); + if (disabled) { + inp.readOnly = true; + const o = make('option', '', { + value: type, + textContent: type + }); + selType.append(o); + } else { + for (const selV of ['String', 'RegExp', 'Object']) { + const o = make('option', '', { + value: selV, + textContent: selV + }); + selType.append(o); + }; } - }); - cfgMap.set('blacklist', blacklist); - cfgMap.set('theme', theme); - cbtn.append(resetbtn, savebtn); - cfgpage.append(blacklist, theme, cbtn); + selType.value = type; + lb.append(inp, selType); + listSec.append(lb); + }; + // const addList = make('mujs-add', '', { + // textContent: '+', + // dataset: { + // command: 'new-list' + // } + // }); + // const n = make('input', '', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Name', + // }); + // const inpValue = make('input', '', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Value', + // }); + // const label = make('label', 'new-list hidden', { + // dataset: { + // blacklist: 'new-list' + // } + // }); + // label.append(n, inpValue, addList); + // listSec.append(label); + // ael(addList, 'click', () => { + // if (isEmpty(n.value) || isEmpty(inpValue.value)) { + // return + // }; + // createList(n.value, n.value, inpValue.value); + // }); + + for (const key of cfg.blacklist) { + createList(key); + } + + cfgpage.append(cbtn); + // cfgpage.append(blacklist, theme, cbtn); }; // #endregion container.tab.custom = (host) => { MUList.host = host; - MUList.build(); + respHandles.build(); + // if (cfg.autofetch) { + // respHandles.build(); + // } + // MUList.build(); }; ael(mainframe, 'mouseenter', (evt) => { evt.preventDefault(); @@ -3580,7 +3816,11 @@ function primaryFN() { tabHost.title = ''; tabHost.textContent = ''; MUList.host = val; - MUList.build(); + respHandles.build(); + // if (cfg.autofetch) { + // respHandles.build(); + // } + // MUList.build(); return; } const value = container.getHost(val); @@ -3592,17 +3832,30 @@ function primaryFN() { tabHost.title = value; tabHost.textContent = value; MUList.host = value; - MUList.build(); + respHandles.build(); + // if (cfg.autofetch) { + // respHandles.build(); + // } + // MUList.build(); return; } }); - scheduler.postTask(makecfg, { priority: 'user-visible' }); - scheduler.postTask(MUList.build, { priority: 'background' }).then(timeoutFrame); + scheduler.postTask(makecfg, { priority: 'background' }); + + respHandles.build = async () => { + const time = await scheduler.postTask(MUList.build, { priority: 'background' }); + return timeoutFrame(time); + }; + + if (cfg.autofetch) { + respHandles.build(); + } dbg('Container', container); } catch (ex) { err(ex); container.remove(); } + return respHandles; } // #endregion /** @@ -3632,14 +3885,19 @@ const init = async () => { loadDOM((doc) => { try { if (window.location === null) { - throw new Error('"window.location" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); + throw new Error('"window.location" is null, reload the webpage or use a different one', { + cause: 'loadDOM' + }); } if (doc === null) { - throw new Error('"doc" is null, reload the webpage or use a different one', { cause: 'loadDOM' }); + throw new Error('"doc" is null, reload the webpage or use a different one', { + cause: 'loadDOM' + }); } - setTrust(); + trustedTypes.init(); sleazyRedirect(); - container.inject(primaryFN, doc); + + if (cfg.autoinject) container.inject(primaryFN, doc); Command.register(i18n$('userjs_inject'), () => { container.inject(primaryFN, doc); diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index 00a9859..ff0a09d 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "إغلاق Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index 3e51fdc..dc12aca 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Userscript+ schließen" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 87c1660..87d600a 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Close Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/en_GB/messages.json b/src/_locales/en_GB/messages.json index e824ab4..9ac0ef7 100644 --- a/src/_locales/en_GB/messages.json +++ b/src/_locales/en_GB/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Close Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json index eec7c40..104dae3 100644 --- a/src/_locales/es/messages.json +++ b/src/_locales/es/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Cerrar Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json index fdf5c44..6ca589f 100644 --- a/src/_locales/fr/messages.json +++ b/src/_locales/fr/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Fermer Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json index 398f3ec..9aa3c8f 100644 --- a/src/_locales/ja/messages.json +++ b/src/_locales/ja/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Userscript+ を閉じる" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json index edc9988..05da423 100644 --- a/src/_locales/nl/messages.json +++ b/src/_locales/nl/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Sluit Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/pl/messages.json b/src/_locales/pl/messages.json index 57e4ce7..2812a5a 100644 --- a/src/_locales/pl/messages.json +++ b/src/_locales/pl/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Zamknij Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/ru/messages.json b/src/_locales/ru/messages.json index cb00ae7..6c3dcbc 100644 --- a/src/_locales/ru/messages.json +++ b/src/_locales/ru/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "Закрыть Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/zh/messages.json b/src/_locales/zh/messages.json index d527783..6304bae 100644 --- a/src/_locales/zh/messages.json +++ b/src/_locales/zh/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "关闭 Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json index d527783..6304bae 100644 --- a/src/_locales/zh_CN/messages.json +++ b/src/_locales/zh_CN/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "关闭 Userscript+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json index e5cce7e..cba9b6d 100644 --- a/src/_locales/zh_TW/messages.json +++ b/src/_locales/zh_TW/messages.json @@ -139,5 +139,14 @@ }, "userjs_close": { "message": "關閉用戶腳本+" + }, + "userjs_sync": { + "message": "Sync with UserScript Manager" + }, + "userjs_autoinject": { + "message": "Inject on load" + }, + "auto_fetch": { + "message": "Fetch on load" } } diff --git a/src/sass/_main.scss b/src/sass/_main.scss index 192f688..e172f8d 100644 --- a/src/sass/_main.scss +++ b/src/sass/_main.scss @@ -672,6 +672,27 @@ mujs-body { } } + &.translated:not([data-good], [data-author]) { + mujs-a { + color: hsl(249, 56%, 65%); + + &:hover { + color: hsl(249, 56%, 85%); + } + } + + mu-jsbtn { + color: hsl(215, 47%, 85%); + background: hsl(249, 56%, 65%); + border-color: hsl(249, 56%, 65%); + + &:hover { + background: hsl(249, 56%, 65%); + border-color: hsl(249, 56%, 65%); + } + } + } + .mujs-ratings { &[data-el="good"] { border-color: hsl(120, 50%, 40%); @@ -823,6 +844,19 @@ mujs-body { background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; } + &[data-name='theme'], + &[data-name='blacklist'] { + display: flex; + justify-content: space-between; + flex-direction: column; + gap: 0.25em; + + // mujs-add { + // order: 999999999999; + // font-size: 20px; + // } + } + input[type='text']::-webkit-input-placeholder { color: var(--mujs-placeholder, hsl(81, 56%, 54%)); } @@ -844,8 +878,32 @@ mujs-body { } >label { - display: flex; - justify-content: space-between; + + // [data-theme] + &:not([data-blacklist]) { + display: flex; + justify-content: space-between; + } + + // &[data-theme], + &[data-blacklist] { + display: grid; + grid-auto-flow: column; + &:not(.new-list) { + grid-template-columns: repeat(2, 1fr); + } + } + + &.new-list { + order: 999999999999; + + mujs-add { + font-size: 20px; + } + } + + // display: flex; + // justify-content: space-between; input:not([type='checkbox']) { font-size: 14px; @@ -874,6 +932,7 @@ mujs-body { // color: var(--mujs-placeholder, hsl(81, 56%, 54%)); // } } + >input { width: 100%; width: -moz-available; @@ -1019,7 +1078,7 @@ mu-jsbtn { mujs-a, mu-jsbtn, .mujs-pointer, -.mujs-cfg mujs-section *:not(input[type='password'], input[type='text'], input[type='number']), +.mujs-cfg mujs-section *:not(input[type='password'], input[type='text'], input[type='number'], [data-theme], [data-blacklist]), .mainbtn, .mainframe, mujs-btn { diff --git a/src/typings/UserJS.d.ts b/src/typings/UserJS.d.ts index 25c80ad..1584f08 100644 --- a/src/typings/UserJS.d.ts +++ b/src/typings/UserJS.d.ts @@ -25,20 +25,7 @@ export interface safeHandles { * * This method is based on uBlock Origin [scriptlets.js](https://github.com/gorhill/uBlock/blob/master/assets/resources/scriptlets.js) */ -export declare function safeSelf(): { - // trustedTypes: { - // createPolicy(): void; - // }; - XMLHttpRequest: typeof XMLHttpRequest; - createElement: typeof document.createElement; - createElementNS: typeof document.createElementNS; - createTextNode: typeof document.createTextNode; - setTimeout: typeof setTimeout; - clearTimeout: typeof clearTimeout; - navigator: typeof navigator; - /** Taken from [scheduler-polyfill](https://github.com/GoogleChromeLabs/scheduler-polyfill) */ - scheduler: typeof scheduler; -}; +export declare function safeSelf(): safeHandles; export declare function loadCSS(css: string, name: string): HTMLStyleElement | undefined; diff --git a/src/typings/types.d.ts b/src/typings/types.d.ts index 873ba4c..f7f2188 100644 --- a/src/typings/types.d.ts +++ b/src/typings/types.d.ts @@ -100,6 +100,8 @@ export type UserJSEngine = { }; export type config = { + autofetch: boolean; + autoinject: boolean; /** * Sync config with UserScript manager */ From 262c6f97ee8538bfb6afcf3b67d60d81ae71604e Mon Sep 17 00:00:00 2001 From: Magic Date: Fri, 7 Feb 2025 16:43:29 -0800 Subject: [PATCH 05/35] v7.2.0 Signed-off-by: Magic --- CHANGELOG.user.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 43b6117..cac4ee8 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,6 +1,6 @@ # Changelog -## v7.1.2 +## v7.2.0 * New config "Inject on load", when disabled prevents this script from injecting the menu automatically. * You can still inject the menu through the context menu in your UserScript manager. @@ -11,6 +11,7 @@ * Improved design of theme section. * Improved design of blacklist section, adding new pages to the list is still incomplete. * Changed "Sync with GM" to "Sync with UserScript Manager". +* Make it so translated UserScripts are a different color in the list. * CSS adjustments. **Known Issues:** From e724c90419519275606548fcb6e859a8618dd3c2 Mon Sep 17 00:00:00 2001 From: Magic Date: Sat, 8 Feb 2025 14:44:28 -0800 Subject: [PATCH 06/35] v7.3.0 Signed-off-by: Magic --- CHANGELOG.user.md | 25 ++- README.md | 2 +- dist/magic-userjs.meta.js | 2 +- dist/magic-userjs.user.js | 434 +++++++++++++++++++++++++++----------- package.json | 2 +- src/UserJS/main.js | 429 ++++++++++++++++++++++++++----------- src/sass/_main.scss | 4 + src/typings/types.d.ts | 29 +++ wiki/README.md | 125 +++++++++++ 9 files changed, 799 insertions(+), 253 deletions(-) create mode 100644 wiki/README.md diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index cac4ee8..61e1794 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,5 +1,28 @@ # Changelog +## v7.3.0 + +* Re-organized config list. +* Added [GreasyFork Bullshit Filter](https://greasyfork.org/scripts/12179) into list. + * You can enable it under "List Filters" in the config. + * You can also do `filter:` in the search bar to quickly filter the list. + * Full list [here](https://github.com/magicoflolis/Userscript-Plus/tree/master/wiki/README.md) + * Example: `filter:ascii` => filters out non-ASCII scripts + +**Known Issues:** + +* "Filter out other languages" may not filter _every_ userscript that is not in your language. +* SVG elements don't load on every webpage, _can be blocked by the page, external script, or extensions._ + +**TODO:** + +* Finish translations. +* Finish blacklist section. +* Merge https://github.com/magicoflolis/Userscript-Plus/pull/59 +* Add sorting to the following: "Total installs", "Ratings", "Created date" + +--- + ## v7.2.0 * New config "Inject on load", when disabled prevents this script from injecting the menu automatically. @@ -11,7 +34,7 @@ * Improved design of theme section. * Improved design of blacklist section, adding new pages to the list is still incomplete. * Changed "Sync with GM" to "Sync with UserScript Manager". -* Make it so translated UserScripts are a different color in the list. +* Made it so translated UserScripts are a different color in the list. * CSS adjustments. **Known Issues:** diff --git a/README.md b/README.md index 183cfb0..bf9d7a0 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Finds available UserScripts for the current webpage, the power of [Greasy Fork]( **UserScript:** > [!IMPORTANT] -> The UserScript only works on `HTTPS`([https://example.com](https://example.com)) +> The UserScript only works on `HTTPS` sites! ([https://example.com](https://example.com)) * [Greasy Fork](https://greasyfork.org/scripts/421603) * [Open UserJS](https://openuserjs.org/scripts/Magic/Magic_Userscript+_Show_Site_All_UserJS) - outdated diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index 5733d26..c74560c 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.2.0 +// @version 7.3.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index ca3a993..e46b3fc 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.2.0 +// @version 7.3.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -1429,6 +1429,9 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg mujs-section > label.new-list mujs-add { font-size: 20px; } +.mujs-cfg mujs-section > label.sub-section { + padding: 0.2em; +} .mujs-cfg mujs-section > label input:not([type=checkbox]) { font-size: 14px; position: relative; @@ -1586,12 +1589,6 @@ const err = (...msg) => { ); const a = typeof alert !== 'undefined' && alert; for (const ex of msg) { - // typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined' - // const isE = Object.prototype.toString.call(ex).includes('Error'); - // if (isE && 'cause' in ex && a) { - // a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); - // } - // const isO = Object.prototype.toString.call(ex).includes('Object'); if (typeof ex === 'object' && 'cause' in ex && a) { a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); } @@ -1721,12 +1718,33 @@ const authorID = 166061; * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{{id}}` */ const goodUserJS = [ + 394820, + 438684, + 4870, + 394420, + 25068, + 483444, + 1682, + 22587, + 789, + 28497, + 386908, + 24204, + 404443, + 4336, + 368183, + 393396, + 473830, 12179, 423001, 376510, 23840, 40525, 6456, + 'https://openuserjs.org/install/Patabugen/Always_Remember_Me.user.js', + 'https://openuserjs.org/install/nokeya/Direct_links_out.user.js', + 'https://github.com/jijirae/y2monkey/raw/main/y2monkey.user.js', + 'https://github.com/jijirae/r2monkey/raw/main/r2monkey.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/Manga_OnlineViewer.user.js', 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' @@ -1746,9 +1764,6 @@ const getUAData = () => { if (userjs.isMobile !== undefined) { return userjs.isMobile; } - // if (typeof userjs.isMobile !== 'undefined') { - // return userjs.isMobile; - // } try { const { navigator } = safeSelf(); if (navigator) { @@ -1845,6 +1860,39 @@ const DEFAULT_CONFIG = { recommend: { author: true, others: true + }, + filters: { + ASCII: { + enabled: false, + name: 'Non-ASCII', + regExp: '[^\\x00-\\x7F\\s]+' + }, + Latin: { + enabled: false, + name: 'Non-Latin', + regExp: '[^\\u0000-\\u024F\\u2000-\\u214F\\s]+' + }, + Games: { + enabled: false, + name: 'Games', + flag: 'iu', + regExp: + 'Aimbot|AntiGame|Agar|agar\\.io|alis\\.io|angel\\.io|ExtencionRipXChetoMalo|AposBot|DFxLite|ZTx-Lite|AposFeedingBot|AposLoader|Balz|Blah Blah|Orc Clan Script|Astro\\s*Empires|^\\s*Attack|^\\s*Battle|BiteFight|Blood\\s*Wars|Bloble|Bonk|Bots|Bots4|Brawler|\\bBvS\\b|Business\\s*Tycoon|Castle\\s*Age|City\\s*Ville|chopcoin\\.io|Comunio|Conquer\\s*Club|CosmoPulse|cursors\\.io|Dark\\s*Orbit|Dead\\s*Frontier|Diep\\.io|\\bDOA\\b|doblons\\.io|DotD|Dossergame|Dragons\\s*of\\s*Atlantis|driftin\\.io|Dugout|\\bDS[a-z]+\\n|elites\\.io|Empire\\s*Board|eRep(ublik)?|Epicmafia|Epic.*War|ExoPlanet|Falcon Tools|Feuerwache|Farming|FarmVille|Fightinfo|Frontier\\s*Ville|Ghost\\s*Trapper|Gladiatus|Goalline|Gondal|gota\\.io|Grepolis|Hobopolis|\\bhwm(\\b|_)|Ikariam|\\bIT2\\b|Jellyneo|Kapi\\s*Hospital|Kings\\s*Age|Kingdoms?\\s*of|knastv(o|oe)gel|Knight\\s*Fight|\\b(Power)?KoC(Atta?ck)?\\b|\\bKOL\\b|Kongregate|Krunker|Last\\s*Emperor|Legends?\\s*of|Light\\s*Rising|lite\\.ext\\.io|Lockerz|\\bLoU\\b|Mafia\\s*(Wars|Mofo)|Menelgame|Mob\\s*Wars|Mouse\\s*Hunt|Molehill\\s*Empire|MooMoo|MyFreeFarm|narwhale\\.io|Neopets|NeoQuest|Nemexia|\\bOGame\\b|Ogar(io)?|Pardus|Pennergame|Pigskin\\s*Empire|PlayerScripts|pokeradar\\.io|Popmundo|Po?we?r\\s*(Bot|Tools)|PsicoTSI|Ravenwood|Schulterglatze|Skribbl|slither\\.io|slitherplus\\.io|slitheriogameplay|SpaceWars|splix\\.io|Survivio|\\bSW_[a-z]+\\n|\\bSnP\\b|The\\s*Crims|The\\s*West|torto\\.io|Travian|Treasure\\s*Isl(and|e)|Tribal\\s*Wars|TW.?PRO|Vampire\\s*Wars|vertix\\.io|War\\s*of\\s*Ninja|World\\s*of\\s*Tanks|West\\s*Wars|wings\\.io|\\bWoD\\b|World\\s*of\\s*Dungeons|wtf\\s*battles|Wurzelimperium|Yohoho|Zombs' + }, + SocialNetworks: { + enabled: false, + name: 'Social Networks', + flag: 'iu', + regExp: + 'Face\\s*book|Google(\\+| Plus)|\\bHabbo|Kaskus|\\bLepra|Leprosorium|MySpace|meinVZ|odnoklassniki|Одноклассники|Orkut|sch(ue|ü)ler(VZ|\\.cc)?|studiVZ|Unfriend|Valenth|VK|vkontakte|ВКонтакте|Qzone|Twitter|TweetDeck' + }, + Clutter: { + enabled: false, + name: 'Clutter', + flag: 'iu', + regExp: + "^\\s*(.{1,3})\\1+\\n|^\\s*(.+?)\\n+\\2\\n*$|^\\s*.{1,5}\\n|do\\s*n('|o)?t (install|download)|nicht installieren|(just )?(\\ban? |\\b)test(ing|s|\\d|\\b)|^\\s*.{0,4}test.{0,4}\\n|\\ntest(ing)?\\s*|^\\s*(\\{@|Smolka|Hacks)|\\[\\d{4,5}\\]|free\\s*download|theme|(night|dark) ?(mode)?" + } } }; //#region i18n @@ -2678,7 +2726,7 @@ class Container { mouse: new Timeout() }; - this.injFN = () => {} + this.injFN = () => {}; window.addEventListener('beforeunload', this.remove); } @@ -3382,9 +3430,6 @@ function primaryFN() { } } // dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); - // for (const [k, v] of Object.entries(cfg.blacklist)) { - // dom.prop(cfgMap.get(k), 'value', v); - // } for (const [k, v] of Object.entries(cfg.theme)) { dom.prop(cfgMap.get(k), 'value', v); } @@ -3664,16 +3709,10 @@ function primaryFN() { container.cache.clear(); if (config.autofetch) { respHandles.build(); - }; + } container.unsaved = false; container.rebuild = false; }); - // container.save(); - // sleazyRedirect(); - // container.cache.clear(); - // MUList.build(); - // container.unsaved = false; - // container.rebuild = false; } else { log(`Imported theme: { ${file.name} }`, result); cfg.theme = result; @@ -4336,6 +4375,39 @@ function primaryFN() { return tr; }; // #endregion + const loadFilters = () => { + const resp = []; + for (const v of Object.values(cfg.filters)) { + if (!v.enabled) { + continue; + } + resp.push(new RegExp(v.regExp, v.flag)); + } + return { + regExp: resp, + get(name) { + for (const v of Object.values(cfg.filters)) { + if (v.name === name) { + return new RegExp(v.regExp, v.flag) + }; + } + // return resp.find(r => r.name === name); + }, + match({ name, users }) { + if (isBlank(resp)) { + return true; + } + const strArr = [{ name }, ...users]; + for (const r of resp) { + const v = strArr.find((o) => o.name.match(r)); + if (v) { + return false; + } + } + return true; + } + }; + }; // #region List class List { engines; @@ -4402,6 +4474,7 @@ function primaryFN() { const customRecords = []; const host = this.host; const arr = []; + const bsFilter = loadFilters(); for (const engine of this.engines) { const cEngine = this.cache[`${engine.name}`]; @@ -4414,9 +4487,6 @@ function primaryFN() { updateCounter(cEngine.length, engine); continue; } - // if (!cfg.autofetch) { - // continue; - // } const respError = (error) => { if (!error.cause) error.cause = engine.name; if (error.message.startsWith('429')) { @@ -4552,7 +4622,10 @@ function primaryFN() { : Array.isArray(dataQ.query) ? dataQ.query : []; - const dataA = dq.filter(Boolean).filter((d) => !d.deleted); + const dataA = dq + .filter(Boolean) + .filter((d) => !d.deleted) + .filter(bsFilter.match); if (isBlank(dataA)) { return; } @@ -4634,6 +4707,9 @@ function primaryFN() { ] }) ); + if (bsFilter.match(ujs)) { + continue; + } if (cfg.codePreview && !ujs._mujs.code.data) { await ujs._mujs.code.request(); } @@ -4672,6 +4748,9 @@ function primaryFN() { ] }) ); + if (bsFilter.match(ujs)) { + continue; + } if (cfg.codePreview && !ujs._mujs.code.data) { await ujs._mujs.code.request(); } @@ -4754,6 +4833,20 @@ function primaryFN() { // #endregion // #region Make Config const makecfg = () => { + const cbtn = make('mu-js', 'mujs-sty-flex'); + const savebtn = make('mujs-btn', 'save', { + textContent: i18n$('save'), + dataset: { + command: 'save' + }, + disabled: false + }); + const resetbtn = make('mujs-btn', 'reset', { + textContent: i18n$('reset'), + dataset: { + command: 'reset' + } + }); const makesection = (name, tag) => { tag = tag ?? i18n$('no_license'); name = name ?? i18n$('no_license'); @@ -4786,11 +4879,23 @@ function primaryFN() { } } }); + lb.append(divDesc); sec.append(lb); cfgpage.append(sec); return sec; }; + + const sections = { + general: makesection('General', 'general'), + load: makesection('Automation', 'load'), + list: makesection('List', 'list'), + filters: makesection('List Filters', 'filters'), + blacklist: makesection('Blacklist (WIP)', 'blacklist'), + // engine: makesection('Search Engine', 'engine'), + theme: makesection('Theme Colors', 'theme') + }; + const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); @@ -4832,8 +4937,8 @@ function primaryFN() { return inp; } if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { - for (const engine of cfg.engines) { - if (engine.name !== nm) continue; + const engine = cfg.engines.find((engine) => engine.name === nm); + if (engine) { inp.checked = engine.enabled; inp.dataset.engine = engine.name; ael(inp, 'change', (evt) => { @@ -4899,41 +5004,79 @@ function primaryFN() { } return inp; }; - if (isGM) { - makerow(i18n$('userjs_sync'), 'checkbox', 'cache'); - makerow(i18n$('userjs_autoinject'), 'checkbox', 'autoinject'); - } - makerow(i18n$('auto_fetch'), 'checkbox', 'autofetch'); - makerow(i18n$('userjs_fullscreen'), 'checkbox', 'autoexpand', { - onchange(e) { - if (e.target.checked) { - dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + const mkSection = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { + cfgMap.set(text, value); + const lb = make('label', 'sub-section hidden', { + textContent: text, + dataset: { + [tag]: text + } + }); + const inp = make('input', '', { + type, + dataset: { + [tag]: text + }, + ...attrs + }); + + if (sections[tag]) { + sections[tag].append(lb); + } + + if (type === 'checkbox') { + const inlab = make('mu-js', 'mujs-inlab'); + const la = make('label', '', { + onclick() { + inp.dispatchEvent(new MouseEvent('click')); + } + }); + inlab.append(inp, la); + lb.append(inlab); + + const nm = /^(\w+)-(.+)/.exec(value); + if (nm) { + if (nm[1] === 'filters') { + inp.checked = cfg[nm[1]][nm[2]].enabled; + } else { + inp.checked = cfg[nm[1]][nm[2]]; + } } else { - dom.cl.remove([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + inp.checked = cfg[value]; } + ael(inp, 'change', (evt) => { + container.unsaved = true; + if (/filterlang/i.test(value)) { + container.rebuild = true; + } + if (nm) { + if (nm[1] === 'filters') { + cfg[nm[1]][nm[2]].enabled = evt.target.checked; + } else { + cfg[nm[1]][nm[2]] = evt.target.checked; + } + } else { + cfg[value] = evt.target.checked; + } + }); + } else { + if (type === 'text') { + inp.defaultValue = ''; + inp.value = value ?? ''; + inp.placeholder = value ?? ''; + } + + lb.append(inp); } - }); - makerow(i18n$('redirect'), 'checkbox', 'sleazyredirect'); - makerow(i18n$('filter'), 'checkbox', 'filterlang'); - makerow(i18n$('preview_code'), 'checkbox', 'codePreview'); - for (const inp of [ - makerow('Recommend author', 'checkbox', 'recommend-author'), - makerow('Recommend scripts', 'checkbox', 'recommend-others') - ]) { - const nm = inp.dataset.name === 'recommend-author' ? 'author' : 'others'; - inp.checked = cfg.recommend[nm]; - ael(inp, 'change', (evt) => { - container.unsaved = true; - cfg.recommend[nm] = evt.target.checked; - }); + + return lb; + }; + if (isGM) { + mkSection(i18n$('userjs_sync'), 'cache'); + mkSection(i18n$('userjs_autoinject'), 'autoinject', 'checkbox', 'load'); } - makerow('Greasy Fork', 'checkbox', 'greasyfork'); - makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); - makerow('Open UserJS', 'checkbox', 'openuserjs'); - makerow('GitHub API', 'checkbox', 'github'); - makerow(`${i18n$('dtime')} (ms)`, 'number', 'time', { + mkSection(i18n$('redirect'), 'sleazyredirect'); + mkSection(`${i18n$('dtime')} (ms)`, 'time', 'number', 'general', { defaultValue: 10000, value: cfg.time, min: 0, @@ -4960,54 +5103,35 @@ function primaryFN() { } } }); - const cbtn = make('mu-js', 'mujs-sty-flex'); - const savebtn = make('mujs-btn', 'save', { - textContent: i18n$('save'), - dataset: { - command: 'save' - }, - disabled: false - }); - const resetbtn = make('mujs-btn', 'reset', { - textContent: i18n$('reset'), - dataset: { - command: 'reset' + + mkSection(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); + mkSection(i18n$('userjs_fullscreen'), 'autoexpand', 'checkbox', 'load', { + onchange(e) { + if (e.target.checked) { + dom.cl.add([btnfullscreen, main], 'expanded'); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + } else { + dom.cl.remove([btnfullscreen, main], 'expanded'); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + } } }); - // const blacklist = make('textarea', '', { - // dataset: { - // name: 'blacklist' - // }, - // rows: '10', - // autocomplete: false, - // spellcheck: false, - // wrap: 'soft', - // value: JSON.stringify(cfg.blacklist, null, ' '), - // oninput(evt) { - // let isvalid = true; - // try { - // cfg.blacklist = JSON.parse(evt.target.value); - // isvalid = true; - // } catch (ex) { - // err(ex); - // isvalid = false; - // } finally { - // if (isvalid) { - // dom.cl.remove(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', false); - // } else { - // dom.cl.add(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', true); - // } - // } - // } - // }); - // cfgMap.set('blacklist', blacklist); - cbtn.append(resetbtn, savebtn); - const themeSec = makesection('Theme Colors', 'theme'); + mkSection(i18n$('filter'), 'filterlang', 'checkbox', 'list'); + mkSection(i18n$('preview_code'), 'codePreview', 'checkbox', 'list'); + mkSection('Recommend author', 'recommend-author', 'checkbox', 'list'); + mkSection('Recommend scripts', 'recommend-others', 'checkbox', 'list'); + + for (const [k, v] of Object.entries(cfg.filters)) { + mkSection(v.name, `filters-${k}`, 'checkbox', 'filters'); + } + + makerow('Greasy Fork', 'checkbox', 'greasyfork'); + makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); + makerow('Open UserJS', 'checkbox', 'openuserjs'); + makerow('GitHub API', 'checkbox', 'github'); + for (const [k, v] of Object.entries(cfg.theme)) { - cfgMap.set(k, v); const lb = make('label', 'hidden', { textContent: k, dataset: { @@ -5031,7 +5155,6 @@ function primaryFN() { const prop = sty.getPropertyValue(str); if (isEmpty(val)) { cfg.theme[k] = DEFAULT_CONFIG.theme[k]; - cfgMap.set(k, DEFAULT_CONFIG.theme[k]); sty.removeProperty(str); return; } @@ -5041,7 +5164,6 @@ function primaryFN() { sty.removeProperty(str); sty.setProperty(str, val); cfg.theme[k] = val; - cfgMap.set(k, val); } catch (ex) { err(ex); isvalid = false; @@ -5056,11 +5178,11 @@ function primaryFN() { } } }); + cfgMap.set(k, inp); lb.append(inp); - themeSec.append(lb); + sections.theme.append(lb); } - const listSec = makesection('Blacklist (WIP)', 'blacklist'); const createList = (key, v = '', disabled = false, type = 'String') => { let txt = key; if (typeof key === 'string') { @@ -5069,7 +5191,7 @@ function primaryFN() { const s = key.substring(7); txt = `Built-in "${s}"`; v = builtinList[s]; - }; + } } else { if (!key.enabled) { return; @@ -5105,9 +5227,6 @@ function primaryFN() { if (isEmpty(val)) { return; } - // if (isRegExp(val)) { - // v = val.toString(); - // }; isvalid = true; } catch (ex) { err(ex); @@ -5143,12 +5262,41 @@ function primaryFN() { textContent: selV }); selType.append(o); - }; + } } selType.value = type; lb.append(inp, selType); - listSec.append(lb); + sections.blacklist.append(lb); }; + // const blacklist = make('textarea', '', { + // dataset: { + // name: 'blacklist' + // }, + // rows: '10', + // autocomplete: false, + // spellcheck: false, + // wrap: 'soft', + // value: JSON.stringify(cfg.blacklist, null, ' '), + // oninput(evt) { + // let isvalid = true; + // try { + // cfg.blacklist = JSON.parse(evt.target.value); + // isvalid = true; + // } catch (ex) { + // err(ex); + // isvalid = false; + // } finally { + // if (isvalid) { + // dom.cl.remove(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', false); + // } else { + // dom.cl.add(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', true); + // } + // } + // } + // }); + // cfgMap.set('blacklist', blacklist); // const addList = make('mujs-add', '', { // textContent: '+', // dataset: { @@ -5185,17 +5333,13 @@ function primaryFN() { createList(key); } + cbtn.append(resetbtn, savebtn); cfgpage.append(cbtn); - // cfgpage.append(blacklist, theme, cbtn); }; // #endregion container.tab.custom = (host) => { MUList.host = host; respHandles.build(); - // if (cfg.autofetch) { - // respHandles.build(); - // } - // MUList.build(); }; ael(mainframe, 'mouseenter', (evt) => { evt.preventDefault(); @@ -5332,6 +5476,54 @@ function primaryFN() { } } } + } else if (val.match(/^filter:/)) { + const parts = /^\w+:(.+)/.exec(val); + if (parts) { + const bsFilter = loadFilters(); + const p = parts[1].trim().toLocaleLowerCase(); + for (const [key, value] of Object.entries(cfg.filters)) { + const k = key.trim().toLocaleLowerCase(); + const v = value.name.trim().toLocaleLowerCase(); + if (p.includes(k) || p.includes(v)) { + const reg = bsFilter.get(value.name); + if (reg) { + [...userjsCache.values()].filter(({ name, users, _mujs }) => { + const elem = _mujs.root; + if (!isElem(elem)) { + return false; + } + if (finds.has(elem)) { + return false; + } + const strArr = [{ name }, ...users]; + const v = strArr.find((o) => o.name.match(reg)); + if (v) { + return false; + } + finds.add(elem); + return true; + }); + } + } + } + } + } else if (val.match(/^recommend:/)) { + for (const v of userjsCache.values()) { + const elem = v._mujs.root; + if (!isElem(elem)) { + continue; + } + if (finds.has(elem)) { + continue; + } + if (v.users.find(u => u.id === authorID)) { + finds.add(elem); + } else if (goodUserJS.includes(v.url)) { + finds.add(elem); + } else if (goodUserJS.includes(v.id)) { + finds.add(elem); + } + } } else { const reg = new RegExp(val, 'gi'); for (const v of userjsCache.values()) { @@ -5383,10 +5575,6 @@ function primaryFN() { tabHost.textContent = ''; MUList.host = val; respHandles.build(); - // if (cfg.autofetch) { - // respHandles.build(); - // } - // MUList.build(); return; } const value = container.getHost(val); @@ -5399,10 +5587,6 @@ function primaryFN() { tabHost.textContent = value; MUList.host = value; respHandles.build(); - // if (cfg.autofetch) { - // respHandles.build(); - // } - // MUList.build(); return; } }); diff --git a/package.json b/package.json index d63164f..f4f73ec 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/magicoflolis/Userscript-Plus/issues" }, "userJS": { - "version": "7.2.0", + "version": "7.3.0", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", diff --git a/src/UserJS/main.js b/src/UserJS/main.js index 4d88413..ffb8ca4 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -20,12 +20,6 @@ const err = (...msg) => { ); const a = typeof alert !== 'undefined' && alert; for (const ex of msg) { - // typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined' - // const isE = Object.prototype.toString.call(ex).includes('Error'); - // if (isE && 'cause' in ex && a) { - // a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); - // } - // const isO = Object.prototype.toString.call(ex).includes('Object'); if (typeof ex === 'object' && 'cause' in ex && a) { a(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); } @@ -155,12 +149,33 @@ const authorID = 166061; * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{{id}}` */ const goodUserJS = [ + 394820, + 438684, + 4870, + 394420, + 25068, + 483444, + 1682, + 22587, + 789, + 28497, + 386908, + 24204, + 404443, + 4336, + 368183, + 393396, + 473830, 12179, 423001, 376510, 23840, 40525, 6456, + 'https://openuserjs.org/install/Patabugen/Always_Remember_Me.user.js', + 'https://openuserjs.org/install/nokeya/Direct_links_out.user.js', + 'https://github.com/jijirae/y2monkey/raw/main/y2monkey.user.js', + 'https://github.com/jijirae/r2monkey/raw/main/r2monkey.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/Manga_OnlineViewer.user.js', 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' @@ -180,9 +195,6 @@ const getUAData = () => { if (userjs.isMobile !== undefined) { return userjs.isMobile; } - // if (typeof userjs.isMobile !== 'undefined') { - // return userjs.isMobile; - // } try { const { navigator } = safeSelf(); if (navigator) { @@ -279,6 +291,39 @@ const DEFAULT_CONFIG = { recommend: { author: true, others: true + }, + filters: { + ASCII: { + enabled: false, + name: 'Non-ASCII', + regExp: '[^\\x00-\\x7F\\s]+' + }, + Latin: { + enabled: false, + name: 'Non-Latin', + regExp: '[^\\u0000-\\u024F\\u2000-\\u214F\\s]+' + }, + Games: { + enabled: false, + name: 'Games', + flag: 'iu', + regExp: + 'Aimbot|AntiGame|Agar|agar\\.io|alis\\.io|angel\\.io|ExtencionRipXChetoMalo|AposBot|DFxLite|ZTx-Lite|AposFeedingBot|AposLoader|Balz|Blah Blah|Orc Clan Script|Astro\\s*Empires|^\\s*Attack|^\\s*Battle|BiteFight|Blood\\s*Wars|Bloble|Bonk|Bots|Bots4|Brawler|\\bBvS\\b|Business\\s*Tycoon|Castle\\s*Age|City\\s*Ville|chopcoin\\.io|Comunio|Conquer\\s*Club|CosmoPulse|cursors\\.io|Dark\\s*Orbit|Dead\\s*Frontier|Diep\\.io|\\bDOA\\b|doblons\\.io|DotD|Dossergame|Dragons\\s*of\\s*Atlantis|driftin\\.io|Dugout|\\bDS[a-z]+\\n|elites\\.io|Empire\\s*Board|eRep(ublik)?|Epicmafia|Epic.*War|ExoPlanet|Falcon Tools|Feuerwache|Farming|FarmVille|Fightinfo|Frontier\\s*Ville|Ghost\\s*Trapper|Gladiatus|Goalline|Gondal|gota\\.io|Grepolis|Hobopolis|\\bhwm(\\b|_)|Ikariam|\\bIT2\\b|Jellyneo|Kapi\\s*Hospital|Kings\\s*Age|Kingdoms?\\s*of|knastv(o|oe)gel|Knight\\s*Fight|\\b(Power)?KoC(Atta?ck)?\\b|\\bKOL\\b|Kongregate|Krunker|Last\\s*Emperor|Legends?\\s*of|Light\\s*Rising|lite\\.ext\\.io|Lockerz|\\bLoU\\b|Mafia\\s*(Wars|Mofo)|Menelgame|Mob\\s*Wars|Mouse\\s*Hunt|Molehill\\s*Empire|MooMoo|MyFreeFarm|narwhale\\.io|Neopets|NeoQuest|Nemexia|\\bOGame\\b|Ogar(io)?|Pardus|Pennergame|Pigskin\\s*Empire|PlayerScripts|pokeradar\\.io|Popmundo|Po?we?r\\s*(Bot|Tools)|PsicoTSI|Ravenwood|Schulterglatze|Skribbl|slither\\.io|slitherplus\\.io|slitheriogameplay|SpaceWars|splix\\.io|Survivio|\\bSW_[a-z]+\\n|\\bSnP\\b|The\\s*Crims|The\\s*West|torto\\.io|Travian|Treasure\\s*Isl(and|e)|Tribal\\s*Wars|TW.?PRO|Vampire\\s*Wars|vertix\\.io|War\\s*of\\s*Ninja|World\\s*of\\s*Tanks|West\\s*Wars|wings\\.io|\\bWoD\\b|World\\s*of\\s*Dungeons|wtf\\s*battles|Wurzelimperium|Yohoho|Zombs' + }, + SocialNetworks: { + enabled: false, + name: 'Social Networks', + flag: 'iu', + regExp: + 'Face\\s*book|Google(\\+| Plus)|\\bHabbo|Kaskus|\\bLepra|Leprosorium|MySpace|meinVZ|odnoklassniki|Одноклассники|Orkut|sch(ue|ü)ler(VZ|\\.cc)?|studiVZ|Unfriend|Valenth|VK|vkontakte|ВКонтакте|Qzone|Twitter|TweetDeck' + }, + Clutter: { + enabled: false, + name: 'Clutter', + flag: 'iu', + regExp: + "^\\s*(.{1,3})\\1+\\n|^\\s*(.+?)\\n+\\2\\n*$|^\\s*.{1,5}\\n|do\\s*n('|o)?t (install|download)|nicht installieren|(just )?(\\ban? |\\b)test(ing|s|\\d|\\b)|^\\s*.{0,4}test.{0,4}\\n|\\ntest(ing)?\\s*|^\\s*(\\{@|Smolka|Hacks)|\\[\\d{4,5}\\]|free\\s*download|theme|(night|dark) ?(mode)?" + } } }; //#region i18n @@ -1112,7 +1157,7 @@ class Container { mouse: new Timeout() }; - this.injFN = () => {} + this.injFN = () => {}; window.addEventListener('beforeunload', this.remove); } @@ -1816,9 +1861,6 @@ function primaryFN() { } } // dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); - // for (const [k, v] of Object.entries(cfg.blacklist)) { - // dom.prop(cfgMap.get(k), 'value', v); - // } for (const [k, v] of Object.entries(cfg.theme)) { dom.prop(cfgMap.get(k), 'value', v); } @@ -2098,16 +2140,10 @@ function primaryFN() { container.cache.clear(); if (config.autofetch) { respHandles.build(); - }; + } container.unsaved = false; container.rebuild = false; }); - // container.save(); - // sleazyRedirect(); - // container.cache.clear(); - // MUList.build(); - // container.unsaved = false; - // container.rebuild = false; } else { log(`Imported theme: { ${file.name} }`, result); cfg.theme = result; @@ -2770,6 +2806,39 @@ function primaryFN() { return tr; }; // #endregion + const loadFilters = () => { + const resp = []; + for (const v of Object.values(cfg.filters)) { + if (!v.enabled) { + continue; + } + resp.push(new RegExp(v.regExp, v.flag)); + } + return { + regExp: resp, + get(name) { + for (const v of Object.values(cfg.filters)) { + if (v.name === name) { + return new RegExp(v.regExp, v.flag) + }; + } + // return resp.find(r => r.name === name); + }, + match({ name, users }) { + if (isBlank(resp)) { + return true; + } + const strArr = [{ name }, ...users]; + for (const r of resp) { + const v = strArr.find((o) => o.name.match(r)); + if (v) { + return false; + } + } + return true; + } + }; + }; // #region List class List { engines; @@ -2836,6 +2905,7 @@ function primaryFN() { const customRecords = []; const host = this.host; const arr = []; + const bsFilter = loadFilters(); for (const engine of this.engines) { const cEngine = this.cache[`${engine.name}`]; @@ -2848,9 +2918,6 @@ function primaryFN() { updateCounter(cEngine.length, engine); continue; } - // if (!cfg.autofetch) { - // continue; - // } const respError = (error) => { if (!error.cause) error.cause = engine.name; if (error.message.startsWith('429')) { @@ -2986,7 +3053,10 @@ function primaryFN() { : Array.isArray(dataQ.query) ? dataQ.query : []; - const dataA = dq.filter(Boolean).filter((d) => !d.deleted); + const dataA = dq + .filter(Boolean) + .filter((d) => !d.deleted) + .filter(bsFilter.match); if (isBlank(dataA)) { return; } @@ -3068,6 +3138,9 @@ function primaryFN() { ] }) ); + if (bsFilter.match(ujs)) { + continue; + } if (cfg.codePreview && !ujs._mujs.code.data) { await ujs._mujs.code.request(); } @@ -3106,6 +3179,9 @@ function primaryFN() { ] }) ); + if (bsFilter.match(ujs)) { + continue; + } if (cfg.codePreview && !ujs._mujs.code.data) { await ujs._mujs.code.request(); } @@ -3188,6 +3264,20 @@ function primaryFN() { // #endregion // #region Make Config const makecfg = () => { + const cbtn = make('mu-js', 'mujs-sty-flex'); + const savebtn = make('mujs-btn', 'save', { + textContent: i18n$('save'), + dataset: { + command: 'save' + }, + disabled: false + }); + const resetbtn = make('mujs-btn', 'reset', { + textContent: i18n$('reset'), + dataset: { + command: 'reset' + } + }); const makesection = (name, tag) => { tag = tag ?? i18n$('no_license'); name = name ?? i18n$('no_license'); @@ -3220,11 +3310,23 @@ function primaryFN() { } } }); + lb.append(divDesc); sec.append(lb); cfgpage.append(sec); return sec; }; + + const sections = { + general: makesection('General', 'general'), + load: makesection('Automation', 'load'), + list: makesection('List', 'list'), + filters: makesection('List Filters', 'filters'), + blacklist: makesection('Blacklist (WIP)', 'blacklist'), + // engine: makesection('Search Engine', 'engine'), + theme: makesection('Theme Colors', 'theme') + }; + const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); @@ -3266,8 +3368,8 @@ function primaryFN() { return inp; } if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { - for (const engine of cfg.engines) { - if (engine.name !== nm) continue; + const engine = cfg.engines.find((engine) => engine.name === nm); + if (engine) { inp.checked = engine.enabled; inp.dataset.engine = engine.name; ael(inp, 'change', (evt) => { @@ -3333,41 +3435,79 @@ function primaryFN() { } return inp; }; - if (isGM) { - makerow(i18n$('userjs_sync'), 'checkbox', 'cache'); - makerow(i18n$('userjs_autoinject'), 'checkbox', 'autoinject'); - } - makerow(i18n$('auto_fetch'), 'checkbox', 'autofetch'); - makerow(i18n$('userjs_fullscreen'), 'checkbox', 'autoexpand', { - onchange(e) { - if (e.target.checked) { - dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + const mkSection = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { + cfgMap.set(text, value); + const lb = make('label', 'sub-section hidden', { + textContent: text, + dataset: { + [tag]: text + } + }); + const inp = make('input', '', { + type, + dataset: { + [tag]: text + }, + ...attrs + }); + + if (sections[tag]) { + sections[tag].append(lb); + } + + if (type === 'checkbox') { + const inlab = make('mu-js', 'mujs-inlab'); + const la = make('label', '', { + onclick() { + inp.dispatchEvent(new MouseEvent('click')); + } + }); + inlab.append(inp, la); + lb.append(inlab); + + const nm = /^(\w+)-(.+)/.exec(value); + if (nm) { + if (nm[1] === 'filters') { + inp.checked = cfg[nm[1]][nm[2]].enabled; + } else { + inp.checked = cfg[nm[1]][nm[2]]; + } } else { - dom.cl.remove([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + inp.checked = cfg[value]; + } + ael(inp, 'change', (evt) => { + container.unsaved = true; + if (/filterlang/i.test(value)) { + container.rebuild = true; + } + if (nm) { + if (nm[1] === 'filters') { + cfg[nm[1]][nm[2]].enabled = evt.target.checked; + } else { + cfg[nm[1]][nm[2]] = evt.target.checked; + } + } else { + cfg[value] = evt.target.checked; + } + }); + } else { + if (type === 'text') { + inp.defaultValue = ''; + inp.value = value ?? ''; + inp.placeholder = value ?? ''; } + + lb.append(inp); } - }); - makerow(i18n$('redirect'), 'checkbox', 'sleazyredirect'); - makerow(i18n$('filter'), 'checkbox', 'filterlang'); - makerow(i18n$('preview_code'), 'checkbox', 'codePreview'); - for (const inp of [ - makerow('Recommend author', 'checkbox', 'recommend-author'), - makerow('Recommend scripts', 'checkbox', 'recommend-others') - ]) { - const nm = inp.dataset.name === 'recommend-author' ? 'author' : 'others'; - inp.checked = cfg.recommend[nm]; - ael(inp, 'change', (evt) => { - container.unsaved = true; - cfg.recommend[nm] = evt.target.checked; - }); + + return lb; + }; + if (isGM) { + mkSection(i18n$('userjs_sync'), 'cache'); + mkSection(i18n$('userjs_autoinject'), 'autoinject', 'checkbox', 'load'); } - makerow('Greasy Fork', 'checkbox', 'greasyfork'); - makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); - makerow('Open UserJS', 'checkbox', 'openuserjs'); - makerow('GitHub API', 'checkbox', 'github'); - makerow(`${i18n$('dtime')} (ms)`, 'number', 'time', { + mkSection(i18n$('redirect'), 'sleazyredirect'); + mkSection(`${i18n$('dtime')} (ms)`, 'time', 'number', 'general', { defaultValue: 10000, value: cfg.time, min: 0, @@ -3394,54 +3534,35 @@ function primaryFN() { } } }); - const cbtn = make('mu-js', 'mujs-sty-flex'); - const savebtn = make('mujs-btn', 'save', { - textContent: i18n$('save'), - dataset: { - command: 'save' - }, - disabled: false - }); - const resetbtn = make('mujs-btn', 'reset', { - textContent: i18n$('reset'), - dataset: { - command: 'reset' + + mkSection(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); + mkSection(i18n$('userjs_fullscreen'), 'autoexpand', 'checkbox', 'load', { + onchange(e) { + if (e.target.checked) { + dom.cl.add([btnfullscreen, main], 'expanded'); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + } else { + dom.cl.remove([btnfullscreen, main], 'expanded'); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + } } }); - // const blacklist = make('textarea', '', { - // dataset: { - // name: 'blacklist' - // }, - // rows: '10', - // autocomplete: false, - // spellcheck: false, - // wrap: 'soft', - // value: JSON.stringify(cfg.blacklist, null, ' '), - // oninput(evt) { - // let isvalid = true; - // try { - // cfg.blacklist = JSON.parse(evt.target.value); - // isvalid = true; - // } catch (ex) { - // err(ex); - // isvalid = false; - // } finally { - // if (isvalid) { - // dom.cl.remove(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', false); - // } else { - // dom.cl.add(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', true); - // } - // } - // } - // }); - // cfgMap.set('blacklist', blacklist); - cbtn.append(resetbtn, savebtn); - const themeSec = makesection('Theme Colors', 'theme'); + mkSection(i18n$('filter'), 'filterlang', 'checkbox', 'list'); + mkSection(i18n$('preview_code'), 'codePreview', 'checkbox', 'list'); + mkSection('Recommend author', 'recommend-author', 'checkbox', 'list'); + mkSection('Recommend scripts', 'recommend-others', 'checkbox', 'list'); + + for (const [k, v] of Object.entries(cfg.filters)) { + mkSection(v.name, `filters-${k}`, 'checkbox', 'filters'); + } + + makerow('Greasy Fork', 'checkbox', 'greasyfork'); + makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); + makerow('Open UserJS', 'checkbox', 'openuserjs'); + makerow('GitHub API', 'checkbox', 'github'); + for (const [k, v] of Object.entries(cfg.theme)) { - cfgMap.set(k, v); const lb = make('label', 'hidden', { textContent: k, dataset: { @@ -3465,7 +3586,6 @@ function primaryFN() { const prop = sty.getPropertyValue(str); if (isEmpty(val)) { cfg.theme[k] = DEFAULT_CONFIG.theme[k]; - cfgMap.set(k, DEFAULT_CONFIG.theme[k]); sty.removeProperty(str); return; } @@ -3475,7 +3595,6 @@ function primaryFN() { sty.removeProperty(str); sty.setProperty(str, val); cfg.theme[k] = val; - cfgMap.set(k, val); } catch (ex) { err(ex); isvalid = false; @@ -3490,11 +3609,11 @@ function primaryFN() { } } }); + cfgMap.set(k, inp); lb.append(inp); - themeSec.append(lb); + sections.theme.append(lb); } - const listSec = makesection('Blacklist (WIP)', 'blacklist'); const createList = (key, v = '', disabled = false, type = 'String') => { let txt = key; if (typeof key === 'string') { @@ -3503,7 +3622,7 @@ function primaryFN() { const s = key.substring(7); txt = `Built-in "${s}"`; v = builtinList[s]; - }; + } } else { if (!key.enabled) { return; @@ -3539,9 +3658,6 @@ function primaryFN() { if (isEmpty(val)) { return; } - // if (isRegExp(val)) { - // v = val.toString(); - // }; isvalid = true; } catch (ex) { err(ex); @@ -3577,12 +3693,41 @@ function primaryFN() { textContent: selV }); selType.append(o); - }; + } } selType.value = type; lb.append(inp, selType); - listSec.append(lb); + sections.blacklist.append(lb); }; + // const blacklist = make('textarea', '', { + // dataset: { + // name: 'blacklist' + // }, + // rows: '10', + // autocomplete: false, + // spellcheck: false, + // wrap: 'soft', + // value: JSON.stringify(cfg.blacklist, null, ' '), + // oninput(evt) { + // let isvalid = true; + // try { + // cfg.blacklist = JSON.parse(evt.target.value); + // isvalid = true; + // } catch (ex) { + // err(ex); + // isvalid = false; + // } finally { + // if (isvalid) { + // dom.cl.remove(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', false); + // } else { + // dom.cl.add(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', true); + // } + // } + // } + // }); + // cfgMap.set('blacklist', blacklist); // const addList = make('mujs-add', '', { // textContent: '+', // dataset: { @@ -3619,17 +3764,13 @@ function primaryFN() { createList(key); } + cbtn.append(resetbtn, savebtn); cfgpage.append(cbtn); - // cfgpage.append(blacklist, theme, cbtn); }; // #endregion container.tab.custom = (host) => { MUList.host = host; respHandles.build(); - // if (cfg.autofetch) { - // respHandles.build(); - // } - // MUList.build(); }; ael(mainframe, 'mouseenter', (evt) => { evt.preventDefault(); @@ -3766,6 +3907,54 @@ function primaryFN() { } } } + } else if (val.match(/^filter:/)) { + const parts = /^\w+:(.+)/.exec(val); + if (parts) { + const bsFilter = loadFilters(); + const p = parts[1].trim().toLocaleLowerCase(); + for (const [key, value] of Object.entries(cfg.filters)) { + const k = key.trim().toLocaleLowerCase(); + const v = value.name.trim().toLocaleLowerCase(); + if (p.includes(k) || p.includes(v)) { + const reg = bsFilter.get(value.name); + if (reg) { + [...userjsCache.values()].filter(({ name, users, _mujs }) => { + const elem = _mujs.root; + if (!isElem(elem)) { + return false; + } + if (finds.has(elem)) { + return false; + } + const strArr = [{ name }, ...users]; + const v = strArr.find((o) => o.name.match(reg)); + if (v) { + return false; + } + finds.add(elem); + return true; + }); + } + } + } + } + } else if (val.match(/^recommend:/)) { + for (const v of userjsCache.values()) { + const elem = v._mujs.root; + if (!isElem(elem)) { + continue; + } + if (finds.has(elem)) { + continue; + } + if (v.users.find(u => u.id === authorID)) { + finds.add(elem); + } else if (goodUserJS.includes(v.url)) { + finds.add(elem); + } else if (goodUserJS.includes(v.id)) { + finds.add(elem); + } + } } else { const reg = new RegExp(val, 'gi'); for (const v of userjsCache.values()) { @@ -3817,10 +4006,6 @@ function primaryFN() { tabHost.textContent = ''; MUList.host = val; respHandles.build(); - // if (cfg.autofetch) { - // respHandles.build(); - // } - // MUList.build(); return; } const value = container.getHost(val); @@ -3833,10 +4018,6 @@ function primaryFN() { tabHost.textContent = value; MUList.host = value; respHandles.build(); - // if (cfg.autofetch) { - // respHandles.build(); - // } - // MUList.build(); return; } }); diff --git a/src/sass/_main.scss b/src/sass/_main.scss index e172f8d..7834a03 100644 --- a/src/sass/_main.scss +++ b/src/sass/_main.scss @@ -902,6 +902,10 @@ mujs-body { } } + &.sub-section { + padding: 0.20em; + } + // display: flex; // justify-content: space-between; diff --git a/src/typings/types.d.ts b/src/typings/types.d.ts index f7f2188..893ca62 100644 --- a/src/typings/types.d.ts +++ b/src/typings/types.d.ts @@ -168,6 +168,7 @@ export type config = { 'position-left': string; 'position-right': string; 'font-family': string; + // [key: string ]: string; }; /** * Highlight UserScripts recommended by the author or UserScripts created by the author @@ -176,6 +177,34 @@ export type config = { author: boolean; others: boolean; }; + filters: { + [name: string ]: { + enabled: boolean; + name: string; + flag?: string; + regExp: string; + }; + // 'Non-ASCII': { + // enabled: boolean; + // regExp: string; + // }; + // 'Non-Latin': { + // enabled: boolean; + // regExp: string; + // }; + // Games: { + // enabled: boolean; + // regExp: string; + // }; + // 'Social Networks': { + // enabled: boolean; + // regExp: string; + // }; + // Clutter: { + // enabled: boolean; + // regExp: string; + // }; + }; }; export declare function objToStr(obj: O): string; diff --git a/wiki/README.md b/wiki/README.md new file mode 100644 index 0000000..c4a70f4 --- /dev/null +++ b/wiki/README.md @@ -0,0 +1,125 @@ +# Wiki Page (Under Construction) + +## New Tab + +Syntax: `*` - Shortcut for userscipts that apply to `All sites` + +Syntax: `` + +```txt +# Example +google.com +``` + +--- + +Syntax: `mujs:` + +```txt +# Available +settings + +# Example +mujs:settings +``` + +--- + +## Search Bar + +By default it will search by name and description, you can refine your searches using the examples listed below. + +Syntax: `filter:` + +```txt +# Available +ascii +latin +games +socialnetworks +clutter + +# Example +filter:ascii +``` + +--- + +Syntax: `code_url:` or `url:` + +```txt +# Example +code_url:google.com +``` + +--- + +Syntax: `author:` or `users:` + +```txt +# Example +author:magicoflolis +``` + +--- + +Syntax: `locale:` or `i18n:` + +```txt +# Example +locale:en +``` + +--- + +Syntax: `id:` + +```txt +# Example +id:421603 +``` + +--- + +Syntax: `license:` + +```txt +# Example +license:MIT +``` + +--- + +Syntax: `name:` + +```txt +# Example +name:Userscript+ +``` + +--- + +Syntax: `description:` + +```txt +# Example +description:Finds available userscripts for the current webpage. +``` + +--- + +Syntax: `search_engine:` or `engine:` + +```txt +# Example +search_engine:greasyfork +``` + +--- + +Syntax: `recommend:` + +```txt +# Example +recommend: +``` From d5884cecd379ceeef437795130394cb07860f260 Mon Sep 17 00:00:00 2001 From: Magic Date: Mon, 17 Feb 2025 11:31:27 -0800 Subject: [PATCH 07/35] Updated .editorconfig --- .editorconfig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index 5f50c69..51bd461 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,12 @@ +# top-most EditorConfig file root = true +# Unix-style newlines with a newline ending every file [*] -charset = utf-8 +end_of_line = lf +insert_final_newline = true indent_style = space indent_size = 2 -end_of_line = crlf -insert_final_newline = true -trim_trailing_whitespace = true \ No newline at end of file + +[*.{js,json,ts,tsx}] +charset = utf-8 \ No newline at end of file From 0e4b2bdac7dea522f0930f98c28cad0393654f23 Mon Sep 17 00:00:00 2001 From: Magic Date: Mon, 17 Feb 2025 11:32:05 -0800 Subject: [PATCH 08/35] Updated .gitignore Signed-off-by: Magic --- .gitignore | 121 ++--------------------------------------------------- 1 file changed, 4 insertions(+), 117 deletions(-) diff --git a/.gitignore b/.gitignore index a548d45..c61cb6a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,140 +2,27 @@ haters/ build +node_modules + Notes .history -web-ext-artifacts -tests web-ext +web-ext-artifacts web-server +*.ini -# Logs -logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* .pnpm-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - -# TypeScript cache *.tsbuildinfo -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - # dotenv environment variable files .env .env.development.local .env.test.local .env.production.local .env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp -.cache - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* From b66378eb0f232a2ef7317552284493e2335288f4 Mon Sep 17 00:00:00 2001 From: Sam Stelle Date: Thu, 20 Feb 2025 19:07:28 -0800 Subject: [PATCH 09/35] Add dataset values for date fields in user script table to fix sorting issue for stupid American date format. --- src/UserJS/main.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/UserJS/main.js b/src/UserJS/main.js index ffb8ca4..d2a5228 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -1393,7 +1393,7 @@ class Container { this.tab.create(this.host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent; + const getCellValue = (tr, idx) => tr.children[idx].dataset.value || tr.children[idx].innerText || tr.children[idx].textContent; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) @@ -2613,7 +2613,10 @@ function primaryFN() { textContent: ujs.daily_installs }); const fupdated = make('td', 'mujs-list', { - textContent: language.toDate(ujs.code_updated_at) + textContent: language.toDate(ujs.code_updated_at), + dataset: { + value: (new Date(ujs.code_updated_at)).toISOString() + } }); const fname = make('td', 'mujs-name'); const fmore = make('mujs-column', 'mujs-list hidden', { @@ -2637,7 +2640,10 @@ function primaryFN() { textContent: `${i18n$('version_number')}: ${ujs.version}` }); const fcreated = make('mu-js', 'mujs-list', { - textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}` + textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`, + dataset: { + value: (new Date(ujs.created_at)).toISOString() + } }); const flicense = make('mu-js', 'mujs-list', { title: ujs.license ?? i18n$('no_license'), From 960239c899509537d895e24f3853c4b8bedc1de6 Mon Sep 17 00:00:00 2001 From: Magic Date: Tue, 25 Feb 2025 14:37:09 -0800 Subject: [PATCH 10/35] Updated eslint.config.js Signed-off-by: Magic --- eslint.config.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 7c77b70..68f464d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,5 +1,5 @@ -import js from '@eslint/js'; import globals from 'globals'; +import pluginJs from '@eslint/js'; import eslintConfigPrettier from 'eslint-config-prettier'; const userJSGlobals = { @@ -9,7 +9,7 @@ const userJSGlobals = { languageList: 'readonly', translations: 'readonly', userjs: 'writable', - ...globals.es2023, + ...globals.es2024, ...globals.browser, ...globals.greasemonkey }; @@ -19,7 +19,7 @@ const webextGlobals = { webext: 'readonly', brws: 'readonly', userjs: 'writable', - ...globals.es2023, + ...globals.es2024, ...globals.browser, ...globals.webextensions }; @@ -42,7 +42,7 @@ const rules = { }; export default [ - js.configs.recommended, + pluginJs.configs.recommended, eslintConfigPrettier, { files: ['src/js/*.js'], @@ -84,7 +84,7 @@ export default [ ecmaVersion: 'latest', sourceType: 'module', globals: { - ...globals.es2021, + ...globals.es2024, ...globals.node }, parserOptions From 942a8ea344c5774281e7a8851aa486354d81ff85 Mon Sep 17 00:00:00 2001 From: Magic Date: Tue, 25 Feb 2025 15:02:48 -0800 Subject: [PATCH 11/35] UserJS v7.4.0 Signed-off-by: Magic --- CHANGELOG.user.md | 29 + dist/magic-userjs.meta.js | 7 +- dist/magic-userjs.user.js | 1573 ++++++++++++++++++------------------- package.json | 45 +- pnpm-lock.yaml | 486 ++++++------ src/UserJS/header.js | 11 +- src/UserJS/main.js | 1557 ++++++++++++++++++------------------ src/sass/_main.scss | 1 + src/typings/UserJS.d.ts | 87 +- src/typings/types.d.ts | 90 ++- 10 files changed, 1987 insertions(+), 1899 deletions(-) diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 61e1794..81b66f2 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,5 +1,34 @@ # Changelog +## v7.4.0 + +* Merged https://github.com/magicoflolis/Userscript-Plus/pull/59 +* Added `githubusercontent.com` to `@connect`. +* Added `autoSort` to config. +* Added sorting to the following: "Total installs", "Ratings", "Created date". + * Still in the early stages, but functional +* Reworked counter system. +* Tweaked cache system. + * Reduced how often the script will cache something. +* Cleaned up code. +* Fixed minor issues. + +**Known Issues:** + +* Enabling a engine requires the page to be reloaded, while disabling a engine does not. + * This is caused by the cache system. +* "Filter out other languages" may not filter _every_ userscript that is not in your language. +* SVG elements don't load on every webpage, _can be blocked by the page, external script, or extensions._ + +**TODO:** + +* Finish translations. +* Finish blacklist section. +* Finish config section. +* Merge https://github.com/magicoflolis/Userscript-Plus/pull/64 + +--- + ## v7.3.0 * Re-organized config list. diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index c74560c..6dd5d1d 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.3.0 +// @version 7.4.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -40,20 +40,25 @@ // @connect greasyfork.org // @connect sleazyfork.org // @connect github.com +// @connect githubusercontent.com // @connect openuserjs.org +// @grant GM_addValueChangeListener // @grant GM_addElement // @grant GM_info // @grant GM_getValue // @grant GM_openInTab // @grant GM_setValue // @grant GM_registerMenuCommand +// @grant GM_removeValueChangeListener // @grant GM_xmlhttpRequest +// @grant GM.addValueChangeListener // @grant GM.addElement // @grant GM.info // @grant GM.getValue // @grant GM.openInTab // @grant GM.setValue // @grant GM.registerMenuCommand +// @grant GM.removeValueChangeListener // @grant GM.xmlHttpRequest // @match https://*/* // @noframes diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index e46b3fc..a624bdd 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.3.0 +// @version 7.4.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -40,20 +40,25 @@ // @connect greasyfork.org // @connect sleazyfork.org // @connect github.com +// @connect githubusercontent.com // @connect openuserjs.org +// @grant GM_addValueChangeListener // @grant GM_addElement // @grant GM_info // @grant GM_getValue // @grant GM_openInTab // @grant GM_setValue // @grant GM_registerMenuCommand +// @grant GM_removeValueChangeListener // @grant GM_xmlhttpRequest +// @grant GM.addValueChangeListener // @grant GM.addElement // @grant GM.info // @grant GM.getValue // @grant GM.openInTab // @grant GM.setValue // @grant GM.registerMenuCommand +// @grant GM.removeValueChangeListener // @grant GM.xmlHttpRequest // @match https://*/* // @noframes @@ -89,6 +94,15 @@ if ( if (!(typeof userjs === 'object' && userjs.UserJS)) { return; } +const createPolicy = () => { + // Native implementation exists + if (window.trustedTypes && window.trustedTypes.createPolicy) { + window.trustedTypes.createPolicy('default', { + createHTML: (string) => string + }); + } +}; +createPolicy(); /** * Uncompressed locales + compiler * @@ -1688,29 +1702,6 @@ function safeSelf() { return userjs.safeSelf; } -const trustedTypes = { - policy: false, - init() { - if (this.policy) { - return this.policy; - } - this.policy = true; - try { - // Native implementation exists - if (window.trustedTypes && window.trustedTypes.createPolicy) { - window.trustedTypes.createPolicy('default', { - createHTML: (string) => string - }); - } - } catch (ex) { - ex.cause = 'trustedTypes.init()'; - err(ex); - } - return this.policy; - } -}; -trustedTypes.init(); - const BLANK_PAGE = 'about:blank'; // Lets highlight me :) const authorID = 166061; @@ -1718,6 +1709,7 @@ const authorID = 166061; * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{{id}}` */ const goodUserJS = [ + 33005, 394820, 438684, 4870, @@ -1749,11 +1741,9 @@ const goodUserJS = [ 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' ]; -/** - * Remove UserJS from banned accounts - */ +/** Remove UserJS from banned accounts */ const badUserJS = [478597]; -// Unsupport webpages for each engine +/** Unsupport host for search engines */ const engineUnsupported = { greasyfork: ['pornhub.com'], sleazyfork: ['pornhub.com'], @@ -1795,12 +1785,15 @@ const builtinList = { pathname: '/hentai/.+/read/page/.+' } }; +// #region DEFAULT_CONFIG /** * @type { import("../typings/types.d.ts").config } */ const DEFAULT_CONFIG = { autofetch: true, autoinject: true, + autoSort: 'daily_installs', + clearTabCache: true, cache: true, codePreview: false, autoexpand: false, @@ -1895,48 +1888,46 @@ const DEFAULT_CONFIG = { } } }; -//#region i18n +// #endregion +// #region i18n class i18nHandler { constructor() { - /** @type { string[] } */ - this.cache = []; - - const { navigator } = safeSelf(); - const { languages } = navigator; - for (const nlang of languages) { - const lg = nlang.split('-')[0]; - if (this.cache.indexOf(lg) === -1) { - this.cache.push(lg); - } + if (userjs.pool !== undefined) { + return userjs.pool; } - - const current = navigator.language.split('-')[0] ?? 'en'; - if (!this.cache.includes(current)) { - this.cache.push(current); + userjs.pool = new Map(); + for (const [k, v] of Object.entries(translations)) { + if (!userjs.pool.has(k)) userjs.pool.set(k, v); } } + /** + * @param {string | Date | number} str + */ toDate(str = '') { const { navigator } = safeSelf(); - return new Intl.DateTimeFormat(navigator.language).format(new Date(str)); + return new Intl.DateTimeFormat(navigator.language).format( + typeof str === 'string' ? new Date(str) : str + ); } + /** + * @param {number | bigint} number + */ toNumber(number) { const { navigator } = safeSelf(); return new Intl.NumberFormat(navigator.language).format(number); } - i18n$(...keys) { + /** + * @type { import("../typings/UserJS.d.ts").i18n$ } + */ + i18n$(key) { const { navigator } = safeSelf(); const current = navigator.language.split('-')[0] ?? 'en'; - const list = translations[cfg.language] ?? translations[current]; - const arr = []; - for (const key of keys) { - arr.push(list[key]); - } - return arr.length !== 1 ? arr : arr[0]; + return userjs.pool.get(current)?.[key] ?? 'Unknown'; } } const language = new i18nHandler(); const { i18n$ } = language; -//#endregion +// #endregion // #region Utilities const union = (...arr) => [...new Set(arr.flat())]; /** @@ -1965,20 +1956,6 @@ const qsA = (selectors, root) => { * @type { import("../typings/types.d.ts").objToStr } */ const objToStr = (obj) => Object.prototype.toString.call(obj); -/** - * @type { import("../typings/types.d.ts").strToURL } - */ -const strToURL = (str) => { - const WIN_LOCATION = window.location ?? BLANK_PAGE; - try { - str = str ?? WIN_LOCATION; - return objToStr(str).includes('URL') ? str : new URL(str); - } catch (ex) { - ex.cause = 'strToURL'; - err(ex); - } - return WIN_LOCATION; -}; /** * @type { import("../typings/types.d.ts").isRegExp } */ @@ -2064,6 +2041,7 @@ const ael = (el, type, listener, options = {}) => { elem.addEventListener(type, listener, options); } } catch (ex) { + ex.cause = 'ael'; err(ex); } }; @@ -2179,26 +2157,12 @@ const dom = { }, cl: { add(target, token) { - if (Array.isArray(token)) { - for (const elem of normalizeTarget(target)) { - elem.classList.add(...token); - } - } else { - for (const elem of normalizeTarget(target)) { - elem.classList.add(token); - } - } + token = Array.isArray(token) ? token : [token]; + return normalizeTarget(target).some((elem) => elem.classList.add(...token)); }, remove(target, token) { - if (Array.isArray(token)) { - for (const elem of normalizeTarget(target)) { - elem.classList.remove(...token); - } - } else { - for (const elem of normalizeTarget(target)) { - elem.classList.remove(token); - } - } + token = Array.isArray(token) ? token : [token]; + return normalizeTarget(target).some((elem) => elem.classList.remove(...token)); }, toggle(target, token, force) { let r; @@ -2208,12 +2172,7 @@ const dom = { return r; }, has(target, token) { - for (const elem of normalizeTarget(target)) { - if (elem.classList.contains(token)) { - return true; - } - } - return false; + return normalizeTarget(target).some((elem) => elem.classList.contains(token)); } } }; @@ -2330,6 +2289,7 @@ const iconSVG = { try { if (typeof iconSVG[type].html === 'string') { svgElem.innerHTML = iconSVG[type].html; + dom.attr(svgElem, 'id', `mujs_${type ?? 'Unknown'}`); } // eslint-disable-next-line no-unused-vars } catch (ex) { @@ -2348,6 +2308,7 @@ const iconSVG = { */ const StorageSystem = { prefix: 'MUJS', + events: new Set(), getItem(key) { return window.localStorage.getItem(key); }, @@ -2360,8 +2321,47 @@ const StorageSystem = { remove(key) { window.localStorage.removeItem(key); }, + addListener(name, callback) { + if (isGM) { + let GMType; + if (isFN(GM.addValueChangeListener)) { + GMType = GM.addValueChangeListener(name, callback); + } else if (isFN(GM_addValueChangeListener)) { + GMType = GM_addValueChangeListener(name, callback); + } + if (GMType) { + return this.events.add(GMType) && GMType; + } + } + return ( + this.events.add(callback) && + window.addEventListener('storage', (evt) => { + const { key, oldValue, newValue } = evt; + if (key === name) callback(key, oldValue, newValue, false); + }) + ); + }, + attach() { + window.addEventListener('beforeunload', () => { + for (const e of this.events) { + if (isGM && typeof e === 'number' && !Number.isNaN(e)) { + if (isFN(GM.removeValueChangeListener)) { + GM.removeValueChangeListener(e); + } else if (isFN(GM_addValueChangeListener)) { + GM_removeValueChangeListener(e); + } + } else { + window.removeEventListener('storage', e); + } + this.events.delete(e); + } + }); + }, async setValue(key, v) { - v = typeof v === 'string' ? v : JSON.stringify(v ?? {}); + if (!v) { + return; + } + v = typeof v === 'string' ? v : JSON.stringify(v); if (isGM) { if (isFN(GM.setValue)) { await GM.setValue(key, v); @@ -2430,9 +2430,6 @@ const Network = { method, ...data }; - if (params.hermes) { - delete params.hermes; - } if (isGM && !useFetch) { if (params.credentials) { Object.assign(params, { @@ -2483,8 +2480,8 @@ const Network = { } else if (responseType.match(/clone/)) { resolve(check('clone')); } else if (responseType.match(/document/)) { - const domParser = new DOMParser(); const respTxt = check('text'); + const domParser = new DOMParser(); if (respTxt instanceof Promise) { respTxt.then((txt) => { const doc = domParser.parseFromString(txt, 'text/html'); @@ -2580,33 +2577,45 @@ const Network = { return txt.replaceAll(/\W/g, ''); } }; -const sleazyRedirect = () => { - const locObj = window.top.location; - const { hostname } = locObj; - const gfSite = /greasyfork\.org/.test(hostname); - if (!gfSite && cfg.sleazyredirect) { - return; - } - const otherSite = gfSite ? 'sleazyfork' : 'greasyfork'; - if (!qs('span.sign-in-link')) { - return; - } - if (!/scripts\/\d+/.test(locObj.href)) { - return; - } - if ( - !qs('#script-info') && - (otherSite == 'greasyfork' || qs('div.width-constraint>section>p>a')) - ) { - const str = locObj.href.replace( - /\/\/([^.]+\.)?(greasyfork|sleazyfork)\.org/, - '//$1' + otherSite + '.org' - ); - info(`Redirecting to "${str}"`); - if (isFN(locObj.assign)) { - locObj.assign(str); - } else { - locObj.href = str; +const Counter = { + cnt: { + total: { + count: 0 + } + }, + set(engine) { + if (!this.cnt[engine.name]) { + const counter = make('count-frame', engine.enabled ? '' : 'hidden', { + dataset: { + counter: engine.name + }, + title: engine.query ? decodeURIComponent(engine.query) : engine.url, + textContent: '0' + }); + this.cnt[engine.name] = { + root: counter, + count: 0 + }; + return counter; + } + return this.cnt[engine.name].root; + }, + update(count, engine) { + this.cnt[engine.name].count += count; + this.cnt.total.count += count; + this.updateAll(); + }, + updateAll() { + for (const v of Object.values(this.cnt)) dom.text(v.root, v.count); + }, + reset() { + for (const [k, v] of Object.entries(this.cnt)) { + dom.text(v.root, 0); + v.count = 0; + const engine = cfg.engines.find((engine) => k === engine.name); + if (engine) { + dom.cl[engine.enabled ? 'remove' : 'add'](v.root, 'hidden'); + } } } }; @@ -2629,17 +2638,16 @@ class Container { unsaved; isBlacklisted; rebuild; - counters; opacityMin; opacityMax; constructor(url) { this.remove = this.remove.bind(this); this.refresh = this.refresh.bind(this); - this.updateCounter = this.updateCounter.bind(this); - this.updateCounters = this.updateCounters.bind(this); this.showError = this.showError.bind(this); + this.toArr = this.toArr.bind(this); + this.toElem = this.toElem.bind(this); - this.webpage = strToURL(url); + this.webpage = this.strToURL(url); this.host = this.getHost(this.webpage.host); this.domain = this.getDomain(this.webpage.host); this.ready = false; @@ -2647,7 +2655,7 @@ class Container { this.shadowRoot = undefined; this.supported = isFN(make('main-userjs').attachShadow); this.frame = this.supported - ? make('main-userjs', '', { + ? make('main-userjs', { dataset: { insertedBy: $info.script.name, role: 'primary-container' @@ -2677,9 +2685,9 @@ class Container { }); if (this.supported) { this.shadowRoot = this.frame.attachShadow({ - mode: 'open', - clonable: false, - delegatesfocus: false + mode: 'closed' + // clonable: false, + // delegatesfocus: false }); this.ready = true; } @@ -2689,9 +2697,6 @@ class Container { this.unsaved = false; this.isBlacklisted = false; this.rebuild = false; - this.counters = { - total: 0 - }; this.opacityMin = '0.15'; this.opacityMax = '1'; this.elementsReady = this.init(); @@ -2775,41 +2780,24 @@ class Container { initFn() { this.renderTheme(cfg.theme); - for (const engine of cfg.engines) { - if (engine.enabled) { - const counter = make('count-frame', '', { - dataset: { - counter: engine.name - }, - title: engine.query ? decodeURIComponent(engine.query) : engine.url, - textContent: '0' - }); - this.countframe.append(counter); - } - this.counters[engine.name] = 0; - } - - const cfgpage = this.cfgpage; - const table = this.table; - const exBtn = this.exBtn; - const supported = this.supported; - const frame = this.frame; - const refresh = this.refresh; - const cache = this.cache; - const cHost = this.host; - const urlBar = this.urlBar; + Counter.cnt.total.root = this.mainbtn; + for (const engine of cfg.engines) this.countframe.append(Counter.set(engine)); + const { cfgpage, table, exBtn, supported, frame, refresh, cache, urlBar, host } = this; class Tabs { /** * @param { HTMLElement } root */ constructor(root) { - this.Tab = new Map(); + /** + * @type { Set } + */ + this.pool = new Set(); this.blank = BLANK_PAGE; this.protocal = 'mujs:'; - this.protoReg = new RegExp(`${this.protocal}(.+)`); + this.protoReg = new RegExp(`${this.protocal}(.+)`, 'i'); this.el = { - add: make('mujs-addtab', '', { + add: make('mujs-addtab', { textContent: '+', dataset: { command: 'new-tab' @@ -2822,43 +2810,23 @@ class Container { this.el.root.append(this.el.head); this.custom = () => {}; } - hasTab(...params) { - for (const p of params) { - if (!this.Tab.has(p)) { - return false; - } - const content = normalizeTarget(this.Tab.get(p)).filter((t) => p === t.dataset.host); - if (isBlank(content)) { - return false; - } - } - return true; - } - storeTab(host) { - const h = host ?? this.blank; - if (!this.Tab.has(h)) { - this.Tab.set(h, new Set()); - } - return this.Tab.get(h); + /** + * @param {string} hostname + */ + getTab(hostname) { + return [...this.pool].find(({ dataset }) => hostname === dataset.host); } - cache(host, ...tabs) { - const h = host ?? this.blank; - const tabCache = this.storeTab(h); - for (const t of normalizeTarget(tabs)) { - if (tabCache.has(t)) { - continue; - } - tabCache.add(t); - } - this.Tab.set(h, tabCache); - return tabCache; + getActive() { + return [...this.pool].find((tab) => tab.classList.contains('active')); } - intFN(host) { - if (!host.startsWith(this.protocal)) { + /** + * @param {string} hostname + */ + intFN(hostname) { + if (!hostname.startsWith(this.protocal)) { return; } - const type = host.match(this.protoReg)[1]; - if (type === 'settings') { + if (hostname.match(this.protoReg)[1] === 'settings') { dom.cl.remove([cfgpage, exBtn], 'hidden'); dom.cl.add(table, 'hidden'); if (!supported) { @@ -2866,67 +2834,60 @@ class Container { } } } + /** + * @param {HTMLElement} tab + * @param {boolean} [build] + */ active(tab, build = true) { - for (const t of normalizeTarget(tab, false)) { - dom.cl.add([cfgpage, exBtn], 'hidden'); - dom.cl.remove(table, 'hidden'); - dom.cl.remove(qsA('mujs-tab', this.el.head), 'active'); - dom.cl.add(t, 'active'); - if (!build) { - continue; - } - const host = t.dataset.host ?? this.blank; - if (host === this.blank) { - refresh(); - } else if (host.startsWith(this.protocal)) { - this.intFN(host); - } else { - this.custom(host); - } + if (!this.pool.has(tab)) this.pool.add(tab); + dom.cl.add([cfgpage, exBtn], 'hidden'); + dom.cl.remove(table, 'hidden'); + dom.cl.remove([...this.pool], 'active'); + dom.cl.add(tab, 'active'); + if (!build) { + return; + } + const host = tab.dataset.host ?? this.blank; + if (host === this.blank) { + refresh(); + } else if (host.startsWith(this.protocal)) { + this.intFN(host); + } else { + this.custom(host); } } /** @param { HTMLElement } tab */ close(tab) { - for (const t of normalizeTarget(tab, false)) { - const host = t.dataset.host; - if (cache.has(host)) { - cache.delete(host); - } - if (dom.cl.has(t, 'active')) { - refresh(); + if (this.pool.has(tab)) this.pool.delete(tab); + const host = tab.dataset.host; + if (cfg.clearTabCache && cache.has(host)) cache.delete(host); + if (tab.classList.contains('active')) refresh(); + const sibling = tab.nextElementSibling ?? tab.previousElementSibling; + if (sibling) { + if (sibling.dataset.command !== 'new-tab') { + this.active(sibling); } - const sibling = t.previousElementSibling ?? t.nextElementSibling; - if (sibling) { - if (sibling.dataset.command !== 'new-tab') { - this.active(sibling); - } - } - if (this.Tab.has(host)) { - this.Tab.delete(host); - } - t.remove(); } + tab.remove(); } - create(host = undefined) { - if (typeof host === 'string') { - if (host.startsWith(this.protocal) && this.hasTab(host)) { - this.active(this.Tab.get(host)); - return; - } - const content = normalizeTarget(this.storeTab(host)).filter( - (t) => host === t.dataset.host - ); - if (!isEmpty(content)) { + /** + * @param {string} [hostname] + */ + create(hostname = undefined) { + if (typeof hostname === 'string') { + const createdTab = this.getTab(hostname); + if (this.protoReg.test(hostname) && createdTab) { + this.active(createdTab); return; } } - const tab = make('mujs-tab', '', { + const tab = make('mujs-tab', { dataset: { command: 'switch-tab' }, style: `order: ${this.el.head.childElementCount};` }); - const tabClose = make('mu-js', '', { + const tabClose = make('mu-js', { dataset: { command: 'close-tab' }, @@ -2937,29 +2898,28 @@ class Container { tab.append(tabHost, tabClose); this.el.head.append(tab); this.active(tab, false); - this.cache(host, tab); - if (isNull(host)) { + if (isNull(hostname)) { refresh(); urlBar.placeholder = i18n$('newTab'); tab.dataset.host = this.blank; tabHost.title = i18n$('newTab'); tabHost.textContent = i18n$('newTab'); - } else if (host.startsWith(this.protocal)) { - const type = host.match(this.protoReg)[1]; - tab.dataset.host = host || cHost; + } else if (hostname.startsWith(this.protocal)) { + const type = hostname.match(this.protoReg)[1]; + tab.dataset.host = hostname || host; tabHost.title = type || tab.dataset.host; tabHost.textContent = tabHost.title; - this.intFN(host); + this.intFN(hostname); } else { - tab.dataset.host = host || cHost; - tabHost.title = host || cHost; + tab.dataset.host = hostname || host; + tabHost.title = hostname || host; tabHost.textContent = tabHost.title; } return tab; } } this.tab = new Tabs(this.toolbar); - this.tab.create(this.host); + this.tab.create(host); const tabbody = this.tabbody; const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent; @@ -3101,9 +3061,9 @@ class Container { command: 'navigation' } }); - const makeTHead = (rows) => { + const makeTHead = (rows = []) => { const tr = make('tr'); - for (const r of normalizeTarget(rows)) { + for (const r of rows) { const tparent = make('th', r.class ?? '', r); tr.append(tparent); } @@ -3158,6 +3118,7 @@ class Container { this.unsaved = false; await StorageSystem.setValue('Config', cfg); info('Saved config:', cfg); + this.redirect(); return cfg; } /** @@ -3197,7 +3158,7 @@ class Container { return sty; } } - const sty = make('style', '', { + const sty = make('style', { textContent: css, dataset: { insertedBy: $info.script.name, @@ -3251,7 +3212,7 @@ class Container { return this.isBlacklisted; } getInfo(url) { - const webpage = strToURL(url || this.webpage); + const webpage = this.strToURL(url || this.webpage); const host = this.getHost(webpage.host); const domain = this.getDomain(webpage.host); return { @@ -3329,6 +3290,10 @@ class Container { } this.promptElem.append(el); } + /** + * @template {string | Error} E + * @param {...E} ex + */ showError(...ex) { err(...ex); const error = make('mu-js', 'error'); @@ -3345,34 +3310,74 @@ class Container { error.appendChild(createTextNode(str)); this.footer.append(error); } - updateCounter(count, engine) { - this.counters[engine.name] += count; - this.counters.total += count; - this.updateCounters(); + toArr() { + return Array.from(this.userjsCache.values()).filter(({ _mujs }) => { + return isElem(_mujs.root) && _mujs.info.engine.enabled; + }); } - updateCounters() { - for (const [k, v] of Object.entries(this.counters)) { - if (k === 'total') { - continue; - } - const c = qs(`count-frame[data-counter="${k}"]`, this.countframe); - if (c) { - dom.text(c, v); - } - } - dom.text(this.mainbtn, this.counters.total); + toElem() { + return this.toArr().map(({ _mujs }) => { + return _mujs.root; + }); } refresh() { this.urlBar.placeholder = i18n$('newTab'); - this.counters.total = 0; - for (const engine of cfg.engines) { - this.counters[engine.name] = 0; - } - this.updateCounters(); - dom.cl.remove(qsA('tr[data-engine]', this.tabbody), 'hidden'); + Counter.reset(); + dom.cl.remove(this.toElem(), 'hidden'); dom.cl.remove(qsA('mujs-section[data-name]', this.cfgpage), 'hidden'); dom.prop([this.tabbody, this.rateContainer, this.footer], 'innerHTML', ''); } + /** + * @template {string | URL} S + * @param {S} str + * @returns {URL} + */ + strToURL(str) { + const WIN_LOCATION = window.location ?? BLANK_PAGE; + try { + str = str ?? WIN_LOCATION; + return objToStr(str).includes('URL') ? str : new URL(str); + } catch (ex) { + ex.cause = 'strToURL'; + this.showError(ex); + } + return WIN_LOCATION; + } + /** + * Redirects sleazyfork userscripts from greasyfork.org to sleazyfork.org + * + * Taken from: https://greasyfork.org/scripts/23840 + */ + redirect() { + const locObj = window.top.location; + const { hostname } = locObj; + const gfSite = /greasyfork\.org/.test(hostname); + if (!gfSite && cfg.sleazyredirect) { + return; + } + const otherSite = gfSite ? 'sleazyfork' : 'greasyfork'; + if (!qs('span.sign-in-link')) { + return; + } + if (!/scripts\/\d+/.test(locObj.href)) { + return; + } + if ( + !qs('#script-info') && + (otherSite == 'greasyfork' || qs('div.width-constraint>section>p>a')) + ) { + const str = locObj.href.replace( + /\/\/([^.]+\.)?(greasyfork|sleazyfork)\.org/, + '//$1' + otherSite + '.org' + ); + info(`Redirecting to "${str}"`); + if (isFN(locObj.assign)) { + locObj.assign(str); + } else { + locObj.href = str; + } + } + } } const container = new Container(); // #endregion @@ -3389,8 +3394,6 @@ function primaryFN() { rateContainer, footer, tabbody, - toolbar, - tabhead, cfgpage, fsearch, btnfullscreen, @@ -3400,8 +3403,6 @@ function primaryFN() { btnissue, btngreasy, tab, - userjsCache, - updateCounter, showError } = container; const frameTimeout = container.timeouts.frame; @@ -3471,7 +3472,7 @@ function primaryFN() { } else if (prmpt !== prmptChoice) { installCode = dataset.userjs.replace(/\.user\.css$/, '.user.js'); } - const dlBtn = make('a', '', { + const dlBtn = make('a', { onclick(evt) { evt.preventDefault(); doInstallProcess(evt.target); @@ -3541,7 +3542,6 @@ function primaryFN() { dom.prop(rateContainer, 'innerHTML', ''); if (!dom.prop(target, 'disabled')) { const config = await container.save(); - sleazyRedirect(); if (container.rebuild) { container.cache.clear(); if (config.autofetch) { @@ -3621,7 +3621,7 @@ function primaryFN() { const apTo = (name, elem, root) => { const n = dataUserJS._mujs.code[name]; if (isEmpty(n)) { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: i18n$('listing_none') }); elem.append(el); @@ -3631,7 +3631,7 @@ function primaryFN() { dom.cl.remove(root, 'hidden'); for (const c of n) { if (typeof c === 'string' && c.startsWith('http')) { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: c, dataset: { command: 'open-tab', @@ -3642,7 +3642,7 @@ function primaryFN() { } else if (isObj(c)) { if (name === 'resource') { for (const [k, v] of Object.entries(c)) { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: k ?? 'ERROR' }); if (v.startsWith('http')) { @@ -3652,7 +3652,7 @@ function primaryFN() { elem.append(el); } } else { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: c.text }); if (c.domain) { @@ -3662,15 +3662,17 @@ function primaryFN() { elem.append(el); } } else { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: c }); elem.append(el); } } }; - const m = qsA('mujs-column[data-el="matches"]', target.parentElement.parentElement); - for (const e of normalizeTarget(m)) { + for (const e of qsA( + 'mujs-column[data-el="matches"]', + target.parentElement.parentElement + )) { apTo(e.dataset.type, qs('.mujs-grants', e), e); } } else if (/export-/.test(cmd)) { @@ -3705,7 +3707,6 @@ function primaryFN() { container.rebuild = true; rebuildCfg(); container.save().then((config) => { - sleazyRedirect(); container.cache.clear(); if (config.autofetch) { respHandles.build(); @@ -4038,42 +4039,23 @@ function primaryFN() { // return [...new Set(a)].filter((v) => arr.every((b) => b.includes(v))); // } } - const mergeTemplate = (obj = {}) => { - const template = { - id: 0, - bad_ratings: 0, - good_ratings: 0, - ok_ratings: 0, - daily_installs: 0, - total_installs: 0, - name: 'NOT FOUND', - description: 'NOT FOUND', - version: '0.0.0', - url: BLANK_PAGE, - code_url: BLANK_PAGE, - created_at: Date.now(), - code_updated_at: Date.now(), - locale: 'NOT FOUND', - deleted: false, - users: [ - { - id: 0, - name: 'NOT FOUND', - url: BLANK_PAGE - } - ] - }; - /** @type {ObjectConstructor["hasOwn"]} */ - const hasOwn = - Object.hasOwn || - function hasOwn(it, key) { - return Object.prototype.hasOwnProperty.call(it, key); - }; - for (const key in template) { - if (hasOwn(obj, key)) continue; - obj[key] = template[key]; - } - return obj; + const template = { + id: 0, + bad_ratings: 0, + good_ratings: 0, + ok_ratings: 0, + daily_installs: 0, + total_installs: 0, + name: 'NOT FOUND', + description: 'NOT FOUND', + version: '0.0.0', + url: BLANK_PAGE, + code_url: BLANK_PAGE, + created_at: Date.now(), + code_updated_at: Date.now(), + locale: 'NOT FOUND', + deleted: false, + users: [] }; const mkList = (txt = '', obj = {}) => { if (!obj.root || !obj.type) { @@ -4095,7 +4077,7 @@ function primaryFN() { const list = obj.list ?? []; if (isEmpty(list)) { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: i18n$('listing_none') }); applyList.append(elem); @@ -4104,7 +4086,7 @@ function primaryFN() { } for (const c of list) { if (typeof c === 'string' && c.startsWith('http')) { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: c, dataset: { command: 'open-tab', @@ -4115,7 +4097,7 @@ function primaryFN() { } else if (isObj(c)) { if (type === 'resource') { for (const [k, v] of Object.entries(c)) { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: k ?? 'ERROR' }); if (v.startsWith('http')) { @@ -4125,7 +4107,7 @@ function primaryFN() { applyList.append(elem); } } else { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: c.text }); if (c.domain) { @@ -4135,7 +4117,7 @@ function primaryFN() { applyList.append(elem); } } else { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: c }); applyList.append(elem); @@ -4165,7 +4147,6 @@ function primaryFN() { * @param { string } engine */ const createjs = (ujs, engine) => { - ujs = mergeTemplate(ujs); // Lets not add this UserJS to the list if (ujs.id === 421603) { return; @@ -4257,7 +4238,7 @@ function primaryFN() { userjs: ujs.code_url } }); - const scriptDownload = make('mu-jsbtn', '', { + const scriptDownload = make('mu-jsbtn', { innerHTML: `${iconSVG.load('install')} ${i18n$('saveFile')}`, dataset: { command: 'download-userjs', @@ -4279,7 +4260,7 @@ function primaryFN() { spellcheck: false, wrap: 'soft' }); - const loadCode = make('mu-jsbtn', '', { + const loadCode = make('mu-jsbtn', { innerHTML: `${iconSVG.load('search')} ${i18n$('preview_code')}`, dataset: { command: 'load-userjs', @@ -4299,7 +4280,7 @@ function primaryFN() { } } for (const u of ujs.users) { - const user = make('mujs-a', '', { + const user = make('mujs-a', { innerHTML: u.name, title: u.url, dataset: { @@ -4362,63 +4343,73 @@ function primaryFN() { codeArea.value = code_obj.get_code_block(); } - if (ujs._mujs.code?.translated) { - tr.classList.add('translated'); - } + if (ujs._mujs.code?.translated) tr.classList.add('translated'); - for (const e of [fname, uframe, fdaily, fupdated, eframe]) { - tr.append(e); - } - tabbody.append(tr); + for (const e of [fname, uframe, fdaily, fupdated, eframe]) tr.append(e); ujs._mujs.root = tr; return tr; }; // #endregion const loadFilters = () => { - const resp = []; - for (const v of Object.values(cfg.filters)) { - if (!v.enabled) { - continue; - } - resp.push(new RegExp(v.regExp, v.flag)); - } - return { - regExp: resp, - get(name) { - for (const v of Object.values(cfg.filters)) { - if (v.name === name) { - return new RegExp(v.regExp, v.flag) - }; + /** @type {Map} */ + const pool = new Map(); + const handles = { + pool, + enabled() { + return [...pool.values()].filter((o) => o.enabled); + }, + refresh() { + if (!Object.is(pool.size, 0)) pool.clear(); + for (const [key, value] of Object.entries(cfg.filters)) { + if (!pool.has(key)) + pool.set(key, { + ...value, + reg: new RegExp(value.regExp, value.flag), + keyReg: new RegExp(key.trim().toLocaleLowerCase(), 'gi'), + valueReg: new RegExp(value.name.trim().toLocaleLowerCase(), 'gi') + }); } - // return resp.find(r => r.name === name); + return this; + }, + get(str) { + return [...pool.values()].find((v) => v.keyReg.test(str) || v.valueReg.test(str)); }, + /** + * @param { import("../typings/types.d.ts").GSForkQuery } param0 + */ match({ name, users }) { - if (isBlank(resp)) { - return true; - } - const strArr = [{ name }, ...users]; - for (const r of resp) { - const v = strArr.find((o) => o.name.match(r)); - if (v) { - return false; - } + const p = handles.enabled(); + if (Object.is(p.length, 0)) return true; + for (const v of p) { + if ([{ name }, ...users].find((o) => o.name.match(v.reg))) return false; } return true; } }; + for (const [key, value] of Object.entries(cfg.filters)) { + if (!pool.has(key)) + pool.set(key, { + ...value, + reg: new RegExp(value.regExp, value.flag), + keyReg: new RegExp(key.trim().toLocaleLowerCase(), 'gi'), + valueReg: new RegExp(value.name.trim().toLocaleLowerCase(), 'gi') + }); + } + return handles.refresh(); }; // #region List class List { engines; - cache; intHost; - constructor(host = undefined) { + constructor(hostname = undefined) { this.build = this.build.bind(this); - if (isEmpty(host)) host = container.host; + this.toArr = this.toArr.bind(this); + this.groupBy = this.groupBy.bind(this); + this.sortRecords = this.sortRecords.bind(this); + if (isEmpty(hostname)) hostname = container.host; this.engines = cfg.engines; - this.cache = container.cache.get(host); - this.host = host; + this.host = hostname; } set host(hostname) { @@ -4431,27 +4422,24 @@ function primaryFN() { } container.cache.set(hostname, engineTemplate); } - if (container.checkBlacklist(hostname)) { + this.blacklisted = container.checkBlacklist(hostname); + if (this.blacklisted) { showError(`Blacklisted "${hostname}"`); timeoutFrame(); - this.blacklisted = true; - } else { - this.blacklisted = false; } - const isSupported = (name) => { - for (const [k, v] of Object.entries(engineUnsupported)) { - if (k !== name) { - continue; - } - if (v.includes(hostname)) { - return false; - } + this.engines = cfg.engines.filter((e) => { + if (!e.enabled) { + return false; + } + const v = engineUnsupported[e.name] ?? []; + if (v.includes(hostname)) { + showError(`Engine: "${e.name}" unsupported on "${hostname}"`); + timeoutFrame(); + return false; } return true; - }; - this.engines = cfg.engines.filter((e) => e.enabled && isSupported(e.name)); - this.cache = container.cache.get(hostname); + }); } get host() { @@ -4462,235 +4450,228 @@ function primaryFN() { build() { try { container.refresh(); - if (this.blacklisted) { - return; - } - if (isEmpty(this.engines)) { + const { blacklisted, engines, host, toArr } = this; + if (blacklisted || isEmpty(engines)) { container.opacityMin = '0'; mainframe.style.opacity = container.opacityMin; return; } - info(' Building list', { cache: this.cache, engines: this.engines }); - const customRecords = []; - const host = this.host; - const arr = []; + const fetchRecords = []; const bsFilter = loadFilters(); + const hostCache = toArr(); - for (const engine of this.engines) { - const cEngine = this.cache[`${engine.name}`]; - if (!isEmpty(cEngine)) { - for (const ujs of cEngine) { - if (isElem(ujs._mujs.root)) { - tabbody.append(ujs._mujs.root); + info('Building list', { hostCache, engines }); + + if (isBlank(hostCache)) { + for (const engine of engines) { + info(`Fetching from "${engine.name}" for "${host}"`); + const respError = (error) => { + if (!error.cause) error.cause = engine.name; + if (error.message.startsWith('429')) { + showError(`Engine: "${engine.name}" Too many requests...`); + return; } - } - updateCounter(cEngine.length, engine); - continue; - } - const respError = (error) => { - if (!error.cause) error.cause = engine.name; - if (error.message.startsWith('429')) { - showError(`Engine: "${engine.name}" Too many requests...`); - return; - } - showError(`Engine: "${engine.name}"`, error.message); - }; - const _mujs = (d) => { - const obj = { - ...d, - _mujs: { - root: {}, - info: { - engine, - host - }, - code: { - antifeatures: [], - grant: [], - match: [], - meta: {}, - request: async function (translate = false, code_url) { - if (this.data) { - return this; - } - this.data = ''; - /** @type { string } */ - const code = await Network.req(code_url ?? d.code_url, 'GET', 'text').catch( - showError - ); - if (typeof code !== 'string') { - return this; - } - Object.assign(this, { - data: code, - code_size: [Network.format(code.length)] - }); - const grantSet = new Set(); - const afSet = new Set(); - const code_obj = new ParseUserJS(code); - const meta = code_obj.parse_meta(); - const applies_to_names = code_obj.calculate_applies_to_names(); + showError(`Engine: "${engine.name}"`, error.message); + }; + const _mujs = (d) => { + const obj = { + ...template, + ...d, + _mujs: { + root: {}, + info: { + engine, + host + }, + code: { + antifeatures: [], + grant: [], + match: [], + meta: {}, + request: async function (translate = false, code_url) { + if (this.data) { + return this; + } + this.data = ''; + /** @type { string } */ + const code = await Network.req(code_url ?? d.code_url, 'GET', 'text').catch( + showError + ); + if (typeof code !== 'string') { + return this; + } + Object.assign(this, { + data: code, + code_size: [Network.format(code.length)] + }); + const grantSet = new Set(); + const afSet = new Set(); + const code_obj = new ParseUserJS(code); + const meta = code_obj.parse_meta(); + const applies_to_names = code_obj.calculate_applies_to_names(); - if (translate) { - for (const lng of language.cache) { - if (meta[`name:${lng}`]) { - Object.assign(obj, { - name: meta[`name:${lng}`] - }); - this.translated = true; - } - if (meta[`description:${lng}`]) { - Object.assign(obj, { - description: meta[`description:${lng}`] - }); - this.translated = true; + if (translate) { + for (const k of userjs.pool.keys()) { + if (meta[`name:${k}`]) { + Object.assign(obj, { + name: meta[`name:${k}`] + }); + this.translated = true; + } + if (meta[`description:${k}`]) { + Object.assign(obj, { + description: meta[`description:${k}`] + }); + this.translated = true; + } } } - } - for (const [key, value] of Object.entries(meta)) { - if (/grant/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (grantSet.has(v)) { - continue; + for (const [key, value] of Object.entries(meta)) { + if (/grant/.test(key)) { + for (const v of normalizeTarget(value, false)) { + if (grantSet.has(v)) { + continue; + } + grantSet.add(v); } - grantSet.add(v); - } - } else if (/antifeature/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (afSet.has(v)) { - continue; + } else if (/antifeature/.test(key)) { + for (const v of normalizeTarget(value, false)) { + if (afSet.has(v)) { + continue; + } + afSet.add(v); } - afSet.add(v); } } - } - if (typeof meta.require === 'string') { - const s = meta.require; - meta.require = [s]; - } - if (meta.resource) { - const obj = {}; - if (typeof meta.resource === 'string') { - const reg = /(.+)\s+(.+)/.exec(meta.resource); - if (reg) { - obj[reg[1].trim()] = reg[2]; - } - } else { - for (const r of meta.resource) { - const reg = /(.+)\s+(http.+)/.exec(r); + if (typeof meta.require === 'string') { + const s = meta.require; + meta.require = [s]; + } + if (meta.resource) { + const obj = {}; + if (typeof meta.resource === 'string') { + const reg = /(.+)\s+(.+)/.exec(meta.resource); if (reg) { obj[reg[1].trim()] = reg[2]; } + } else { + for (const r of meta.resource) { + const reg = /(.+)\s+(http.+)/.exec(r); + if (reg) { + obj[reg[1].trim()] = reg[2]; + } + } } + meta.resource = obj; } - meta.resource = obj; - } - Object.assign(this, { - meta, - match: applies_to_names, - grant: [...grantSet], - antifeatures: [...afSet] - }); + Object.assign(this, { + meta, + match: applies_to_names, + grant: [...grantSet], + antifeatures: [...afSet] + }); - return this; + return this; + } } } - } + }; + return obj; }; - return obj; - }; - const toQuery = (fallback) => { - if (engine.query) { - return decodeURIComponent(engine.query).replace(/\{host\}/g, host); - } - return fallback; - }; - /** - * @param { import("../typings/types.d.ts").GSFork } dataQ - */ - const forkFN = async (dataQ) => { - if (!dataQ) { - showError('Invalid data received from the server, check internet connection'); - return; - } /** - * @type { import("../typings/types.d.ts").GSForkQuery[] } + * Prior to UserScript v7.0.0 + * @template {string} F + * @param {F} fallback + * @returns {F} */ - const dq = Array.isArray(dataQ) - ? dataQ - : Array.isArray(dataQ.query) - ? dataQ.query - : []; - const dataA = dq - .filter(Boolean) - .filter((d) => !d.deleted) - .filter(bsFilter.match); - if (isBlank(dataA)) { - return; - } - const data = dataA.map(_mujs); - const otherLng = []; + const toQuery = (fallback) => { + if (engine.query) { + return decodeURIComponent(engine.query).replace(/\{host\}/g, host); + } + return fallback; + }; /** - * @param {import("../typings/types.d.ts").GSForkQuery} d - * @returns {boolean} + * @param { import("../typings/types.d.ts").GSFork } dataQ */ - const inUserLanguage = (d) => { - const dlocal = d.locale.split('-')[0] ?? d.locale; - if (language.cache.includes(dlocal)) { - return true; + const forkFN = async (dataQ) => { + if (!dataQ) { + showError('Invalid data received from the server, check internet connection'); + return; } - otherLng.push(d); - return false; - }; - const filterLang = data.filter((d) => { - if (cfg.filterlang && !inUserLanguage(d)) { - return false; + /** + * @type { import("../typings/types.d.ts").GSForkQuery[] } + */ + const dq = Array.isArray(dataQ) + ? dataQ + : Array.isArray(dataQ.query) + ? dataQ.query + : []; + const dataA = dq + .filter(Boolean) + .filter((d) => !d.deleted) + .filter(bsFilter.match); + if (isBlank(dataA)) { + return; } - return true; - }); - let finalList = filterLang; - const hds = []; - for (const ujs of otherLng) { - const c = await ujs._mujs.code.request(true); - if (c.translated) { - hds.push(ujs); + const data = dataA.map(_mujs); + const otherLng = []; + /** + * @param {import("../typings/types.d.ts").GSForkQuery} d + * @returns {boolean} + */ + const inUserLanguage = (d) => { + if (userjs.pool.has(d.locale.split('-')[0] ?? d.locale)) { + return true; + } + otherLng.push(d); + return false; + }; + const filterLang = data.filter((d) => { + if (cfg.filterlang && !inUserLanguage(d)) { + return false; + } + return true; + }); + let finalList = filterLang; + const hds = []; + for (const ujs of otherLng) { + const c = await ujs._mujs.code.request(true); + if (c.translated) { + hds.push(ujs); + } } - } - finalList = union(hds, filterLang); + finalList = union(hds, filterLang); - for (const ujs of finalList) { - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); - } - createjs(ujs, engine.name); - } - this.cache[engine.name].push(...finalList); - updateCounter(finalList.length, engine); - }; - /** - * @param {Document} htmlDocument - */ - const openuserjs = async (htmlDocument) => { - try { - if (!htmlDocument) { - showError('Invalid data received from the server, TODO fix this'); - return; + for (const ujs of finalList) { + if (cfg.codePreview && !ujs._mujs.code.data) { + await ujs._mujs.code.request(); + } + createjs(ujs, engine.name); } - const selected = htmlDocument.documentElement; - if (/openuserjs/gi.test(engine.name)) { - for (const i of qsA('.col-sm-8 .tr-link', selected)) { - while (isNull(qs('.script-version', i))) { - await new Promise((resolve) => requestAnimationFrame(resolve)); - } - const fixurl = dom - .prop(qs('.tr-link-a', i), 'href') - .replace( - new RegExp(document.location.origin, 'gi'), - 'https://openuserjs.org' - ); - const ujs = mergeTemplate( - _mujs({ + }; + /** + * @param {Document} htmlDocument + */ + const openuserjs = async (htmlDocument) => { + try { + if (!htmlDocument) { + showError('Invalid data received from the server, TODO fix this'); + return; + } + const selected = htmlDocument.documentElement; + if (/openuserjs/gi.test(engine.name)) { + for (const i of qsA('.col-sm-8 .tr-link', selected)) { + while (isNull(qs('.script-version', i))) { + await new Promise((resolve) => requestAnimationFrame(resolve)); + } + const fixurl = dom + .prop(qs('.tr-link-a', i), 'href') + .replace( + new RegExp(document.location.origin, 'gi'), + 'https://openuserjs.org' + ); + const ujs = _mujs({ name: dom.text(qs('.tr-link-a', i)), description: dom.text(qs('p', i)), version: dom.text(qs('.script-version', i)), @@ -4705,33 +4686,28 @@ function primaryFN() { url: dom.prop(qs('.inline-block a', i), 'href') } ] - }) - ); - if (bsFilter.match(ujs)) { - continue; - } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + }); + if (bsFilter.match(ujs)) { + continue; + } + if (cfg.codePreview && !ujs._mujs.code.data) { + await ujs._mujs.code.request(); + } + createjs(ujs, engine.name); } - createjs(ujs, engine.name); - customRecords.push(ujs); } + } catch (ex) { + showError(ex); } - this.cache[engine.name].push(...customRecords); - updateCounter(customRecords.length, engine); - } catch (ex) { - showError(ex); - } - }; - const gitFN = async (data) => { - try { - if (isBlank(data.items)) { - showError('Invalid data received from the server, TODO fix this'); - return; - } - for (const r of data.items) { - const ujs = mergeTemplate( - _mujs({ + }; + const gitFN = async (data) => { + try { + if (isBlank(data.items)) { + showError('Invalid data received from the server, TODO fix this'); + return; + } + for (const r of data.items) { + const ujs = _mujs({ name: r.name, description: isEmpty(r.repository.description) ? i18n$('no_license') @@ -4746,87 +4722,118 @@ function primaryFN() { url: r.repository.owner.html_url } ] - }) - ); - if (bsFilter.match(ujs)) { - continue; - } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + }); + if (bsFilter.match(ujs)) { + continue; + } + if (cfg.codePreview && !ujs._mujs.code.data) { + await ujs._mujs.code.request(); + } + createjs(ujs, engine.name); } - createjs(ujs, engine.name); - customRecords.push(ujs); + } catch (ex) { + showError(ex); } - this.cache[engine.name].push(...customRecords); - updateCounter(data.items.length, engine); - } catch (ex) { - showError(ex); - } - }; - let netFN; - if (/github/gi.test(engine.name)) { - if (isEmpty(engine.token)) { - showError(`"${engine.name}" requires a token to use`); - continue; - } - netFN = Network.req( - toQuery( - `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` - ), - 'GET', - 'json', - { - headers: { - Accept: 'application/vnd.github+json', - Authorization: `Bearer ${engine.token}`, - 'X-GitHub-Api-Version': '2022-11-28' - } + }; + let netFN; + if (/github/gi.test(engine.name)) { + if (isEmpty(engine.token)) { + showError(`"${engine.name}" requires a token to use`); + continue; } - ) - .then(gitFN) - .then(() => { - Network.req('https://api.github.com/rate_limit', 'GET', 'json', { + netFN = Network.req( + toQuery( + `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` + ), + 'GET', + 'json', + { headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${engine.token}`, 'X-GitHub-Api-Version': '2022-11-28' } - }) - .then((data) => { - for (const [key, value] of Object.entries(data.resources.code_search)) { - const txt = make('mujs-row', 'rate-info', { - textContent: `${key.toUpperCase()}: ${value}` - }); - rateContainer.append(txt); + } + ) + .then(gitFN) + .then(() => { + Network.req('https://api.github.com/rate_limit', 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' } }) - .catch(respError); - }); - } else if (/openuserjs/gi.test(engine.name)) { - netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document').then( - openuserjs - ); - } else { - netFN = Network.req( - toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) - ).then(forkFN); - } - if (netFN) { - arr.push(netFN.catch(respError)); + .then((data) => { + for (const [key, value] of Object.entries(data.resources.code_search)) { + const txt = make('mujs-row', 'rate-info', { + textContent: `${key.toUpperCase()}: ${value}` + }); + rateContainer.append(txt); + } + }) + .catch(respError); + }); + } else if (/openuserjs/gi.test(engine.name)) { + netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document').then( + openuserjs + ); + } else { + netFN = Network.req( + toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) + ).then(forkFN); + } + if (netFN) { + fetchRecords.push(netFN.catch(respError)); + } } + } else { + for (const ujs of hostCache) tabbody.append(ujs._mujs.root); } urlBar.placeholder = i18n$('search_placeholder'); urlBar.value = ''; - Promise.allSettled(arr).then(() => { - tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); - tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); - }); + if (isBlank(fetchRecords)) { + this.sortRecords(); + return; + } + Promise.allSettled(fetchRecords).then(this.sortRecords).catch(showError); } catch (ex) { showError(ex); } } + + sortRecords() { + const arr = this.toArr(); + for (const ujs of arr.flat().sort((a, b) => { + const sortType = cfg.autoSort ?? 'daily_installs'; + return b[sortType] - a[sortType]; + })) { + if (isElem(ujs._mujs.root)) tabbody.append(ujs._mujs.root); + } + for (const [name, value] of Object.entries(this.groupBy(arr))) + Counter.update(value.length, { name }); + } + + toArr() { + const h = this.intHost; + return container.toArr().filter(({ _mujs }) => _mujs.info.host === h); + } + + groupBy(arr) { + const callback = ({ _mujs }) => _mujs.info.engine.name; + if (isFN(Object.groupBy)) { + return Object.groupBy(arr, callback); + } + /** [Object.groupBy polyfill](https://gist.github.com/gtrabanco/7c97bd41aa74af974fa935bfb5044b6e) */ + return arr.reduce((acc = {}, ...args) => { + const key = callback(...args); + acc[key] ??= []; + acc[key].push(args[0]); + return acc; + }, {}); + } // #endregion } const MUList = new List(); @@ -4850,17 +4857,17 @@ function primaryFN() { const makesection = (name, tag) => { tag = tag ?? i18n$('no_license'); name = name ?? i18n$('no_license'); - const sec = make('mujs-section', '', { + const sec = make('mujs-section', { dataset: { name: tag } }); - const lb = make('label', '', { + const lb = make('label', { dataset: { command: tag } }); - const divDesc = make('mu-js', '', { + const divDesc = make('mu-js', { textContent: name }); ael(sec, 'click', (evt) => { @@ -4899,13 +4906,13 @@ function primaryFN() { const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); - const sec = make('mujs-section', '', { + const sec = make('mujs-section', { dataset: { name: nm } }); const lb = make('label'); - const divDesc = make('mu-js', '', { + const divDesc = make('mu-js', { textContent: desc }); lb.append(divDesc); @@ -4914,7 +4921,7 @@ function primaryFN() { if (isNull(type)) { return lb; } - const inp = make('input', '', { + const inp = make('input', { type, dataset: { name: nm @@ -4926,7 +4933,7 @@ function primaryFN() { } if (type === 'checkbox') { const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', '', { + const la = make('label', { onclick() { inp.dispatchEvent(new MouseEvent('click')); } @@ -4949,7 +4956,7 @@ function primaryFN() { if (engine.query) { const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); - const urlInp = make('input', '', { + const urlInp = make('input', { type: 'text', defaultValue: '', value: decodeURIComponent(engine.query) ?? '', @@ -4971,7 +4978,7 @@ function primaryFN() { sec.append(urlInp); } if (engine.name === 'github') { - const ghToken = make('input', '', { + const ghToken = make('input', { type: 'text', defaultValue: '', value: engine.token ?? '', @@ -5012,7 +5019,29 @@ function primaryFN() { [tag]: text } }); - const inp = make('input', '', { + if (type === 'select') { + const inp = make('select', { + dataset: { + [tag]: text + }, + ...attrs + }); + for (const selV of Object.keys(template)) { + if (selV === 'deleted' || selV === 'users') continue; + const o = make('option', { + value: selV, + textContent: selV + }); + inp.append(o); + } + inp.value = cfg[value]; + lb.append(inp); + if (sections[tag]) { + sections[tag].append(lb); + } + return lb; + } + const inp = make('input', { type, dataset: { [tag]: text @@ -5026,7 +5055,7 @@ function primaryFN() { if (type === 'checkbox') { const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', '', { + const la = make('label', { onclick() { inp.dispatchEvent(new MouseEvent('click')); } @@ -5116,7 +5145,9 @@ function primaryFN() { } } }); + mkSection('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); + mkSection('Default Sort', 'autoSort', 'select', 'list'); mkSection(i18n$('filter'), 'filterlang', 'checkbox', 'list'); mkSection(i18n$('preview_code'), 'codePreview', 'checkbox', 'list'); mkSection('Recommend author', 'recommend-author', 'checkbox', 'list'); @@ -5138,7 +5169,7 @@ function primaryFN() { theme: k } }); - const inp = make('input', '', { + const inp = make('input', { type: 'text', defaultValue: '', value: v ?? '', @@ -5212,7 +5243,7 @@ function primaryFN() { blacklist: key } }); - const inp = make('input', '', { + const inp = make('input', { type: 'text', defaultValue: '', value: v ?? '', @@ -5242,7 +5273,7 @@ function primaryFN() { } } }); - const selType = make('select', '', { + const selType = make('select', { disabled, dataset: { blacklist: key @@ -5250,14 +5281,14 @@ function primaryFN() { }); if (disabled) { inp.readOnly = true; - const o = make('option', '', { + const o = make('option', { value: type, textContent: type }); selType.append(o); } else { for (const selV of ['String', 'RegExp', 'Object']) { - const o = make('option', '', { + const o = make('option', { value: selV, textContent: selV }); @@ -5268,7 +5299,7 @@ function primaryFN() { lb.append(inp, selType); sections.blacklist.append(lb); }; - // const blacklist = make('textarea', '', { + // const blacklist = make('textarea', { // dataset: { // name: 'blacklist' // }, @@ -5297,19 +5328,19 @@ function primaryFN() { // } // }); // cfgMap.set('blacklist', blacklist); - // const addList = make('mujs-add', '', { + // const addList = make('mujs-add', { // textContent: '+', // dataset: { // command: 'new-list' // } // }); - // const n = make('input', '', { + // const n = make('input', { // type: 'text', // defaultValue: '', // value: '', // placeholder: 'Name', // }); - // const inpValue = make('input', '', { + // const inpValue = make('input', { // type: 'text', // defaultValue: '', // value: '', @@ -5375,15 +5406,16 @@ function primaryFN() { * @type { string } */ const val = evt.target.value; + const section = qsA('mujs-section[data-name]', cfgpage); if (isEmpty(val)) { - dom.cl.remove(qsA('tr[data-engine]', tabbody), 'hidden'); - dom.cl.remove(qsA('mujs-section[data-name]', cfgpage), 'hidden'); + dom.cl.remove(container.toElem(), 'hidden'); + dom.cl.remove(section, 'hidden'); return; } const finds = new Set(); if (!dom.cl.has(cfgpage, 'hidden')) { const reg = new RegExp(val, 'gi'); - for (const elem of qsA('mujs-section[data-name]', cfgpage)) { + for (const elem of section) { if (!isElem(elem)) { continue; } @@ -5394,10 +5426,13 @@ function primaryFN() { finds.add(elem); } } - dom.cl.add(qsA('mujs-section[data-name]', cfgpage), 'hidden'); + dom.cl.add(section, 'hidden'); dom.cl.remove([...finds], 'hidden'); return; } + const cacheValues = container.toArr().filter(({ _mujs }) => { + return !finds.has(_mujs.root); + }); /** * @param {RegExpMatchArray} regExp * @param {keyof import("../typings/types.d.ts").GSForkQuery} key @@ -5405,43 +5440,29 @@ function primaryFN() { const ezQuery = (regExp, key) => { const q_value = val.replace(regExp, ''); const reg = new RegExp(q_value, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } + for (const v of cacheValues) { let k = v[key]; if (typeof k === 'number') { k = `${v[key]}`; } if (k && k.match(reg)) { - finds.add(elem); + finds.add(v._mujs.root); } } }; if (val.match(/^(code_url|url):/)) { ezQuery(/^(code_url|url):/, 'code_url'); } else if (val.match(/^(author|users?):/)) { - const q_value = val.replace(/^(author|users?):/, ''); - const reg = new RegExp(q_value, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v.users) { + const parts = /^[\w_]+:(.+)/.exec(val); + if (parts) { + const reg = new RegExp(parts[1], 'gi'); + for (const v of cacheValues.filter((v) => !isEmpty(v.users))) { for (const user of v.users) { for (const value of Object.values(user)) { if (typeof value === 'string' && value.match(reg)) { - finds.add(elem); + finds.add(v._mujs.root); } else if (typeof value === 'number' && `${value}`.match(reg)) { - finds.add(elem); + finds.add(v._mujs.root); } } } @@ -5458,96 +5479,52 @@ function primaryFN() { } else if (val.match(/^description:/)) { ezQuery(/^description:/, 'description'); } else if (val.match(/^(search_engine|engine):/)) { - const q_value = val.replace(/^(search_engine|engine):/, ''); - const reg = new RegExp(q_value, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v._mujs.info.engine) { - for (const value of Object.values(v._mujs.info.engine)) { - if (typeof value === 'string' && value.match(reg)) { - finds.add(elem); - } + const parts = /^[\w_]+:(\w+)/.exec(val); + if (parts) { + const reg = new RegExp(parts[1], 'gi'); + for (const { _mujs } of cacheValues) { + if (!_mujs.info.engine.name.match(reg)) { + continue; } + finds.add(_mujs.root); } } } else if (val.match(/^filter:/)) { const parts = /^\w+:(.+)/.exec(val); if (parts) { const bsFilter = loadFilters(); - const p = parts[1].trim().toLocaleLowerCase(); - for (const [key, value] of Object.entries(cfg.filters)) { - const k = key.trim().toLocaleLowerCase(); - const v = value.name.trim().toLocaleLowerCase(); - if (p.includes(k) || p.includes(v)) { - const reg = bsFilter.get(value.name); - if (reg) { - [...userjsCache.values()].filter(({ name, users, _mujs }) => { - const elem = _mujs.root; - if (!isElem(elem)) { - return false; - } - if (finds.has(elem)) { - return false; - } - const strArr = [{ name }, ...users]; - const v = strArr.find((o) => o.name.match(reg)); - if (v) { - return false; - } - finds.add(elem); - return true; - }); + const filterType = bsFilter.get(parts[1].trim().toLocaleLowerCase()); + if (filterType) { + const { reg } = filterType; + for (const { name, users, _mujs } of cacheValues) { + if ([{ name }, ...users].find((o) => o.name.match(reg))) { + continue; } + finds.add(_mujs.root); } } } } else if (val.match(/^recommend:/)) { - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v.users.find(u => u.id === authorID)) { - finds.add(elem); - } else if (goodUserJS.includes(v.url)) { - finds.add(elem); - } else if (goodUserJS.includes(v.id)) { - finds.add(elem); + for (const { url, id, users, _mujs } of cacheValues) { + if ( + users.find((u) => u.id === authorID) || + goodUserJS.includes(url) || + goodUserJS.includes(id) + ) { + finds.add(_mujs.root); } } } else { const reg = new RegExp(val, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v.name && v.name.match(reg)) { - finds.add(elem); - } - if (v.description && v.description.match(reg)) { - finds.add(elem); - } + for (const v of cacheValues) { + if (v.name && v.name.match(reg)) finds.add(v._mujs.root); + if (v.description && v.description.match(reg)) finds.add(v._mujs.root); const code_data = v._mujs.code.data; if (code_data) { const code_obj = new ParseUserJS(code_data); const meta = code_obj.parse_meta(code_data); for (const key of Object.keys(meta)) { - if (/name|desc/i.test(key) && key.match(reg)) { - finds.add(elem); - } + if (/name|desc/i.test(key) && key.match(reg)) finds.add(v._mujs.root); } } } @@ -5558,16 +5535,19 @@ function primaryFN() { ael(urlBar, 'change', (evt) => { evt.preventDefault(); const val = evt.target.value; - if (urlBar.placeholder === i18n$('newTab') && qs('mujs-tab.active', toolbar)) { - const tabElem = qs('mujs-tab.active', toolbar); - const tabHost = qs('mujs-host', tabElem); - if (val.startsWith(tab.protocal)) { + const tabElem = tab.getActive(); + if (urlBar.placeholder === i18n$('newTab') && tabElem) { + const tabHost = tabElem.firstElementChild; + if (tab.protoReg.test(val)) { + const createdTab = tab.getTab(val); tab.close(tabElem); - if (tab.hasTab(val)) { - tab.active(tab.Tab.get(val)); + if (createdTab) { + tab.active(createdTab); } else { tab.create(val); } + evt.target.placeholder = i18n$('search_placeholder'); + evt.target.value = ''; return; } else if (val === '*') { tabElem.dataset.host = val; @@ -5587,7 +5567,6 @@ function primaryFN() { tabHost.textContent = value; MUList.host = value; respHandles.build(); - return; } }); scheduler.postTask(makecfg, { priority: 'background' }); @@ -5613,20 +5592,19 @@ function primaryFN() { * @param { (this: F, doc: Document) => * } onDomReady */ const loadDOM = (onDomReady) => { - if (!isFN(onDomReady)) { - return; - } - if (document.readyState === 'interactive' || document.readyState === 'complete') { - onDomReady(document); - return; + if (isFN(onDomReady)) { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + onDomReady(document); + } else { + document.addEventListener('DOMContentLoaded', (evt) => onDomReady(evt.target), { + once: true + }); + } } - document.addEventListener('DOMContentLoaded', (evt) => onDomReady(evt.target), { - once: true - }); }; -const init = async () => { - const stored = await StorageSystem.getValue('Config', DEFAULT_CONFIG); +const init = async (prefix = 'Config') => { + const stored = await StorageSystem.getValue(prefix, DEFAULT_CONFIG); cfg = { ...DEFAULT_CONFIG, ...stored @@ -5644,8 +5622,7 @@ const init = async () => { cause: 'loadDOM' }); } - trustedTypes.init(); - sleazyRedirect(); + container.redirect(); if (cfg.autoinject) container.inject(primaryFN, doc); @@ -5662,4 +5639,4 @@ const init = async () => { }; init(); -})(); \ No newline at end of file +})(); diff --git a/package.json b/package.json index f4f73ec..2773e46 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/magicoflolis/Userscript-Plus/issues" }, "userJS": { - "version": "7.3.0", + "version": "7.4.0", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", @@ -61,22 +61,27 @@ "greasyfork.org", "sleazyfork.org", "github.com", + "githubusercontent.com", "openuserjs.org" ], "grant": [ + "GM_addValueChangeListener", "GM_addElement", "GM_info", "GM_getValue", "GM_openInTab", "GM_setValue", "GM_registerMenuCommand", + "GM_removeValueChangeListener", "GM_xmlhttpRequest", + "GM.addValueChangeListener", "GM.addElement", "GM.info", "GM.getValue", "GM.openInTab", "GM.setValue", "GM.registerMenuCommand", + "GM.removeValueChangeListener", "GM.xmlHttpRequest" ], "exclude": [], @@ -105,12 +110,14 @@ "web-run:firefox-android": "web-ext run --config=./tools/web-ext.js -t firefox-android --firefox-apk org.mozilla.firefox" }, "devDependencies": { + "@eslint/js": "^9.20.0", "@swc/cli": "^0.6.0", - "@swc/core": "^1.10.14", - "@types/chrome": "0.0.301", + "@swc/core": "^1.10.16", + "@types/chrome": "0.0.304", + "@types/eslint-config-prettier": "^6.11.3", "@types/firefox-webext-browser": "120.0.4", "@types/greasemonkey": "4.0.7", - "@types/node": "^22.13.1", + "@types/node": "^22.13.4", "@types/tampermonkey": "^5.0.4", "@types/trusted-types": "^2.0.7", "@types/webpack": "^5.28.5", @@ -121,21 +128,21 @@ "crx3": "^1.1.3", "css-loader": "^7.1.2", "dotenv": "^16.4.7", - "eslint": "^9.19.0", + "eslint": "^9.20.1", "eslint-config-prettier": "^10.0.1", - "globals": "^15.14.0", + "globals": "^15.15.0", "http-server": "^14.1.1", "mini-css-extract-plugin": "^2.9.2", "path-browserify": "^1.0.1", - "prettier": "^3.4.2", - "sass-embedded": "^1.83.4", - "sass-loader": "^16.0.4", + "prettier": "^3.5.1", + "sass-embedded": "^1.85.0", + "sass-loader": "^16.0.5", "swc-loader": "^0.2.6", "terser-webpack-plugin": "^5.3.11", "typescript": "^5.7.3", "watchpack": "^2.4.2", "web-ext": "^8.4.0", - "webpack": "^5.97.1", + "webpack": "^5.98.0", "webpack-cli": "^6.0.1", "webpack-merge": "^6.0.1" }, @@ -154,11 +161,21 @@ "violentmonkey" ], "webExt": { - "sourceDir": "./build/firefox/", - "artifactsDir": "./build" + "artifactsDir": "./build", + "build": { + "overwriteDest": true + }, + "sourceDir": "./build/firefox" }, "engines": { - "node": ">=20" + "node": ">=18", + "pnpm": ">=9" }, - "packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4" + "packageManager": "pnpm@10.3.0+sha512.ee592eda8815a8a293c206bb0917c4bb0ff274c50def7cbc17be05ec641fc2d1b02490ce660061356bd0d126a4d7eb2ec8830e6959fb8a447571c631d5a2442d", + "pnpm": { + "onlyBuiltDependencies": [ + "@swc/core", + "spawn-sync" + ] + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b8ed7a9..546bb2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,15 +8,21 @@ importers: .: devDependencies: + '@eslint/js': + specifier: ^9.20.0 + version: 9.20.0 '@swc/cli': specifier: ^0.6.0 - version: 0.6.0(@swc/core@1.10.14) + version: 0.6.0(@swc/core@1.10.16) '@swc/core': - specifier: ^1.10.14 - version: 1.10.14 + specifier: ^1.10.16 + version: 1.10.16 '@types/chrome': - specifier: 0.0.301 - version: 0.0.301 + specifier: 0.0.304 + version: 0.0.304 + '@types/eslint-config-prettier': + specifier: ^6.11.3 + version: 6.11.3 '@types/firefox-webext-browser': specifier: 120.0.4 version: 120.0.4 @@ -24,8 +30,8 @@ importers: specifier: 4.0.7 version: 4.0.7 '@types/node': - specifier: ^22.13.1 - version: 22.13.1 + specifier: ^22.13.4 + version: 22.13.4 '@types/tampermonkey': specifier: ^5.0.4 version: 5.0.4 @@ -34,7 +40,7 @@ importers: version: 2.0.7 '@types/webpack': specifier: ^5.28.5 - version: 5.28.5(@swc/core@1.10.14)(webpack-cli@6.0.1) + version: 5.28.5(@swc/core@1.10.16)(webpack-cli@6.0.1) '@violentmonkey/types': specifier: 0.2.0 version: 0.2.0 @@ -46,49 +52,49 @@ importers: version: 9.1.2 copy-webpack-plugin: specifier: ^12.0.2 - version: 12.0.2(webpack@5.97.1) + version: 12.0.2(webpack@5.98.0) crx3: specifier: ^1.1.3 version: 1.1.3 css-loader: specifier: ^7.1.2 - version: 7.1.2(webpack@5.97.1) + version: 7.1.2(webpack@5.98.0) dotenv: specifier: ^16.4.7 version: 16.4.7 eslint: - specifier: ^9.19.0 - version: 9.19.0 + specifier: ^9.20.1 + version: 9.20.1 eslint-config-prettier: specifier: ^10.0.1 - version: 10.0.1(eslint@9.19.0) + version: 10.0.1(eslint@9.20.1) globals: - specifier: ^15.14.0 - version: 15.14.0 + specifier: ^15.15.0 + version: 15.15.0 http-server: specifier: ^14.1.1 version: 14.1.1 mini-css-extract-plugin: specifier: ^2.9.2 - version: 2.9.2(webpack@5.97.1) + version: 2.9.2(webpack@5.98.0) path-browserify: specifier: ^1.0.1 version: 1.0.1 prettier: - specifier: ^3.4.2 - version: 3.4.2 + specifier: ^3.5.1 + version: 3.5.1 sass-embedded: - specifier: ^1.83.4 - version: 1.83.4 + specifier: ^1.85.0 + version: 1.85.0 sass-loader: - specifier: ^16.0.4 - version: 16.0.4(sass-embedded@1.83.4)(webpack@5.97.1) + specifier: ^16.0.5 + version: 16.0.5(sass-embedded@1.85.0)(webpack@5.98.0) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.14)(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.16)(webpack@5.98.0) terser-webpack-plugin: specifier: ^5.3.11 - version: 5.3.11(@swc/core@1.10.14)(webpack@5.97.1) + version: 5.3.11(@swc/core@1.10.16)(webpack@5.98.0) typescript: specifier: ^5.7.3 version: 5.7.3 @@ -99,11 +105,11 @@ importers: specifier: ^8.4.0 version: 8.4.0 webpack: - specifier: ^5.97.1 - version: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + specifier: ^5.98.0 + version: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) webpack-cli: specifier: ^6.0.1 - version: 6.0.1(webpack@5.97.1) + version: 6.0.1(webpack@5.98.0) webpack-merge: specifier: ^6.0.1 version: 6.0.1 @@ -168,6 +174,10 @@ packages: resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.11.0': + resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -180,8 +190,8 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@9.19.0': - resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} + '@eslint/js@9.20.0': + resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.5': @@ -299,68 +309,68 @@ packages: chokidar: optional: true - '@swc/core-darwin-arm64@1.10.14': - resolution: {integrity: sha512-Dh4VyrhDDb05tdRmqJ/MucOPMTnrB4pRJol18HVyLlqu1HOT5EzonUniNTCdQbUXjgdv5UVJSTE1lYTzrp+myA==} + '@swc/core-darwin-arm64@1.10.16': + resolution: {integrity: sha512-iikIxwqCQ4Bvz79vJ4ELh26efPf1u5D9TFdmXSJUBs7C3mmMHvk5zyWD9A9cTowXiW6WHs2gE58U1R9HOTTIcg==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.10.14': - resolution: {integrity: sha512-KpzotL/I0O12RE3tF8NmQErINv0cQe/0mnN/Q50ESFzB5kU6bLgp2HMnnwDTm/XEZZRJCNe0oc9WJ5rKbAJFRQ==} + '@swc/core-darwin-x64@1.10.16': + resolution: {integrity: sha512-R2Eb9aktWd62vPfW9H/c/OaQ0e94iURibBo4uzUUcgxNNmB4+wb6piKbHxGdr/5bEsT+vJ1lwZFSRzfb45E7DA==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.10.14': - resolution: {integrity: sha512-20yRXZjMJVz1wp1TcscKiGTVXistG+saIaxOmxSNQia1Qun3hSWLL+u6+5kXbfYGr7R2N6kqSwtZbIfJI25r9Q==} + '@swc/core-linux-arm-gnueabihf@1.10.16': + resolution: {integrity: sha512-mkqN3HBAMnuiSGZ/k2utScuH8rAPshvNj0T1LjBWon+X9DkMNHSA+aMLdWsy0yZKF1zjOPc4L3Uq2l2wzhUlzA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.10.14': - resolution: {integrity: sha512-Gy7cGrNkiMfPxQyLGxdgXPwyWzNzbHuWycJFcoKBihxZKZIW8hkPBttkGivuLC+0qOgsV2/U+S7tlvAju7FtmQ==} + '@swc/core-linux-arm64-gnu@1.10.16': + resolution: {integrity: sha512-PH/+q/L5nVZJ91CU07CL6Q9Whs6iR6nneMZMAgtVF9Ix8ST0cWVItdUhs6D38kFklCFhaOrpHhS01HlMJ72vWw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.10.14': - resolution: {integrity: sha512-+oYVqJvFw62InZ8PIy1rBACJPC2WTe4vbVb9kM1jJj2D7dKLm9acnnYIVIDsM5Wo7Uab8RvPHXVbs19IBurzuw==} + '@swc/core-linux-arm64-musl@1.10.16': + resolution: {integrity: sha512-1169+C9XbydKKc6Ec1XZxTGKtHjZHDIFn0r+Nqp/QSVwkORrOY1Vz2Hdu7tn/lWMg36ZkGePS+LnnyV67s/7yg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.10.14': - resolution: {integrity: sha512-OmEbVEKQFLQVHwo4EJl9osmlulURy46k232Opfpn/1ji0t2KcNCci3POsnfMuoZjLkGJv8vGNJdPQxX+CP+wSA==} + '@swc/core-linux-x64-gnu@1.10.16': + resolution: {integrity: sha512-n2rV0XwkjoHn4MDJmpYp5RBrnyi94/6GsJVpbn6f+/eqSrZn3mh3dT7pdZc9zCN1Qp9eDHo+uI6e/wgvbL22uA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.10.14': - resolution: {integrity: sha512-OZW+Icm8DMPqHbhdxplkuG8qrNnPk5i7xJOZWYi1y5bTjgGFI4nEzrsmmeHKMdQTaWwsFrm3uK1rlyQ48MmXmg==} + '@swc/core-linux-x64-musl@1.10.16': + resolution: {integrity: sha512-EevCpwreBrkPrJjQVIbiM81lK42ukNNSlBmrSRxxbx2V9VGmOd5qxX0cJBn0TRRSLIPi62BuMS76F9iYjqsjgg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.10.14': - resolution: {integrity: sha512-sTvc+xrDQXy3HXZFtTEClY35Efvuc3D+busYm0+rb1+Thau4HLRY9WP+sOKeGwH9/16rzfzYEqD7Ds8A9ykrHw==} + '@swc/core-win32-arm64-msvc@1.10.16': + resolution: {integrity: sha512-BvE7RWAnKJeELVQWLok6env5I4GUVBTZSvaSN/VPgxnTjF+4PsTeQptYx0xCYhp5QCv68wWYsBnZKuPDS+SBsw==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.10.14': - resolution: {integrity: sha512-j2iQ4y9GWTKtES5eMU0sDsFdYni7IxME7ejFej25Tv3Fq4B+U9tgtYWlJwh1858nIWDXelHiKcSh/UICAyVMdQ==} + '@swc/core-win32-ia32-msvc@1.10.16': + resolution: {integrity: sha512-7Jf/7AeCgbLR/JsQgMJuacHIq4Jeie3knf6+mXxn8aCvRypsOTIEu0eh7j24SolOboxK1ijqJ86GyN1VA2Rebg==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.10.14': - resolution: {integrity: sha512-TYtWkUSMkjs0jGPeWdtWbex4B+DlQZmN/ySVLiPI+EltYCLEXsFMkVFq6aWn48dqFHggFK0UYfvDrJUR2c3Qxg==} + '@swc/core-win32-x64-msvc@1.10.16': + resolution: {integrity: sha512-p0blVm0R8bjaTtmW+FoPmLxLSQdRNbqhuWcR/8g80OzMSkka9mk5/J3kn/5JRVWh+MaR9LHRHZc1Q1L8zan13g==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.10.14': - resolution: {integrity: sha512-WSrnE6JRnH20ZYjOOgSS4aOaPv9gxlkI2KRkN24kagbZnPZMnN8bZZyzw1rrLvwgpuRGv17Uz+hflosbR+SP6w==} + '@swc/core@1.10.16': + resolution: {integrity: sha512-nOINg/OUcZazCW7B55QV2/UB8QAqz9FYe4+z229+4RYboBTZ102K7ebOEjY5sKn59JgAkhjZTz+5BKmXpDFopw==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '*' @@ -381,8 +391,11 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@types/chrome@0.0.301': - resolution: {integrity: sha512-BljW7InXXOfDYr4nG79y5lnaklrZ0gmeTwCUkuCXK2+69dHnZIrg13KhXJE/HrcFUmy8NG/EK+RTGScsh/Hbiw==} + '@types/chrome@0.0.304': + resolution: {integrity: sha512-ms9CLILU+FEMK7gcmgz/Mtn2E81YQWiMIzCFF8ktp98EVNIIfoqaDTD4+ailOCq1sGjbnEmfJxQ1FAsQtk5M3A==} + + '@types/eslint-config-prettier@6.11.3': + resolution: {integrity: sha512-3wXCiM8croUnhg9LdtZUJQwNcQYGWxxdOWDjPe1ykCqJFPVpzAKfs/2dgSoCtAvdPeaponcWPI7mPcGGp9dkKQ==} '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -420,8 +433,8 @@ packages: '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - '@types/node@22.13.1': - resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==} + '@types/node@22.13.4': + resolution: {integrity: sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==} '@types/tampermonkey@5.0.4': resolution: {integrity: sha512-HEJ0O5CkDZSwIgd9Zip4xM8o7gZC8zBmJuH1YEXNINIC+aCWEXD10pnpo3NQG5IWHx+Xr4fMSGq1jqeKXH2lpA==} @@ -617,11 +630,6 @@ packages: ajv: optional: true - ajv-keywords@3.5.2: - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - ajv-keywords@5.1.0: resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} peerDependencies: @@ -1130,8 +1138,8 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true - eslint@9.19.0: - resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} + eslint@9.20.1: + resolution: {integrity: sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1369,8 +1377,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.14.0: - resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} globby@14.0.1: @@ -2053,8 +2061,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + prettier@3.5.1: + resolution: {integrity: sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==} engines: {node: '>=14'} hasBin: true @@ -2211,133 +2219,133 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sass-embedded-android-arm64@1.83.4: - resolution: {integrity: sha512-tgX4FzmbVqnQmD67ZxQDvI+qFNABrboOQgwsG05E5bA/US42zGajW9AxpECJYiMXVOHmg+d81ICbjb0fsVHskw==} + sass-embedded-android-arm64@1.85.0: + resolution: {integrity: sha512-4itDzRwezwrW8+YzMLIwHtMeH+qrBNdBsRn9lTVI15K+cNLC8z5JWJi6UCZ8TNNZr9LDBfsh5jUdjSub0yF7jg==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [android] - sass-embedded-android-arm@1.83.4: - resolution: {integrity: sha512-9Z4pJAOgEkXa3VDY/o+U6l5XvV0mZTJcSl0l/mSPHihjAHSpLYnOW6+KOWeM8dxqrsqTYcd6COzhanI/a++5Gw==} + sass-embedded-android-arm@1.85.0: + resolution: {integrity: sha512-pPBT7Ad6G8Mlao8ypVNXW2ya7I/Bhcny+RYZ/EmrunEXfhzCNp4PWV2VAweitPO9RnPIJwvUTkLc8Fu6K3nVmw==} engines: {node: '>=14.0.0'} cpu: [arm] os: [android] - sass-embedded-android-ia32@1.83.4: - resolution: {integrity: sha512-RsFOziFqPcfZXdFRULC4Ayzy9aK6R6FwQ411broCjlOBX+b0gurjRadkue3cfUEUR5mmy0KeCbp7zVKPLTK+5Q==} + sass-embedded-android-ia32@1.85.0: + resolution: {integrity: sha512-bwqKq95hzbGbMTeXCMQhH7yEdc2xJVwIXj7rGdD3McvyFWbED6362XRFFPI5YyjfD2wRJd9yWLh/hn+6VyjcYA==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [android] - sass-embedded-android-riscv64@1.83.4: - resolution: {integrity: sha512-EHwh0nmQarBBrMRU928eTZkFGx19k/XW2YwbPR4gBVdWLkbTgCA5aGe8hTE6/1zStyx++3nDGvTZ78+b/VvvLg==} + sass-embedded-android-riscv64@1.85.0: + resolution: {integrity: sha512-Fgkgay+5EePJXZFHR5Vlkutnsmox2V6nX4U3mfGbSN1xjLRm8F5ST72V2s5Z0mnIFpGvEu/v7hfptgViqMvaxg==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [android] - sass-embedded-android-x64@1.83.4: - resolution: {integrity: sha512-0PgQNuPWYy1jEOEPDVsV89KfqOsMLIp9CSbjBY7jRcwRhyVAcigqrUG6bDeNtojHUYKA1kU+Eh/85WxOHUOgBw==} + sass-embedded-android-x64@1.85.0: + resolution: {integrity: sha512-/bG3JgTn3eoIDHCiJNVkLeJgUesat4ghxqYmKMZUJx++4e6iKCDj8XwQTJAgm+QDrsPKXHBacHEANJ9LEAuTqg==} engines: {node: '>=14.0.0'} cpu: [x64] os: [android] - sass-embedded-darwin-arm64@1.83.4: - resolution: {integrity: sha512-rp2ywymWc3nymnSnAFG5R/8hvxWCsuhK3wOnD10IDlmNB7o4rzKby1c+2ZfpQGowlYGWsWWTgz8FW2qzmZsQRw==} + sass-embedded-darwin-arm64@1.85.0: + resolution: {integrity: sha512-plp8TyMz97YFBCB3ndftEvoW29vyfsSBJILM5U84cGzr06SvLh/Npjj8psfUeRw+upEk1zkFtw5u61sRCdgwIw==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [darwin] - sass-embedded-darwin-x64@1.83.4: - resolution: {integrity: sha512-kLkN2lXz9PCgGfDS8Ev5YVcl/V2173L6379en/CaFuJJi7WiyPgBymW7hOmfCt4uO4R1y7CP2Uc08DRtZsBlAA==} + sass-embedded-darwin-x64@1.85.0: + resolution: {integrity: sha512-LP8Zv8DG57Gn6PmSwWzC0gEZUsGdg36Ps3m0i1fVTOelql7N3HZIrlPYRjJvidL8ZlB3ISxNANebTREUHn/wkQ==} engines: {node: '>=14.0.0'} cpu: [x64] os: [darwin] - sass-embedded-linux-arm64@1.83.4: - resolution: {integrity: sha512-E0zjsZX2HgESwyqw31EHtI39DKa7RgK7nvIhIRco1d0QEw227WnoR9pjH3M/ZQy4gQj3GKilOFHM5Krs/omeIA==} + sass-embedded-linux-arm64@1.85.0: + resolution: {integrity: sha512-JRIRKVOY5Y8M1zlUOv9AQGju4P6lj8i5vLJZsVYVN/uY8Cd2dDJZPC8EOhjntp+IpF8AOGIHqCeCkHBceIyIjA==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - sass-embedded-linux-arm@1.83.4: - resolution: {integrity: sha512-nL90ryxX2lNmFucr9jYUyHHx21AoAgdCL1O5Ltx2rKg2xTdytAGHYo2MT5S0LIeKLa/yKP/hjuSvrbICYNDvtA==} + sass-embedded-linux-arm@1.85.0: + resolution: {integrity: sha512-18xOAEfazJt1MMVS2TRHV94n81VyMnywOoJ7/S7I79qno/zx26OoqqP4XvH107xu8+mZ9Gg54LrUH6ZcgHk08g==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] - sass-embedded-linux-ia32@1.83.4: - resolution: {integrity: sha512-ew5HpchSzgAYbQoriRh8QhlWn5Kw2nQ2jHoV9YLwGKe3fwwOWA0KDedssvDv7FWnY/FCqXyymhLd6Bxae4Xquw==} + sass-embedded-linux-ia32@1.85.0: + resolution: {integrity: sha512-4JH+h+gLt9So22nNPQtsKojEsLzjld9ol3zWcOtMGclv+HojZGbCuhJUrLUcK72F8adXYsULmWhJPKROLIwYMA==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] - sass-embedded-linux-musl-arm64@1.83.4: - resolution: {integrity: sha512-IzMgalf6MZOxgp4AVCgsaWAFDP/IVWOrgVXxkyhw29fyAEoSWBJH4k87wyPhEtxSuzVHLxKNbc8k3UzdWmlBFg==} + sass-embedded-linux-musl-arm64@1.85.0: + resolution: {integrity: sha512-aoQjUjK28bvdw9XKTjQeayn8oWQ2QqvoTD11myklGd3IHH7Jj0nwXUstI4NxDueCKt3wghuZoIQkjOheReQxlg==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - sass-embedded-linux-musl-arm@1.83.4: - resolution: {integrity: sha512-0RrJRwMrmm+gG0VOB5b5Cjs7Sd+lhqpQJa6EJNEaZHljJokEfpE5GejZsGMRMIQLxEvVphZnnxl6sonCGFE/QQ==} + sass-embedded-linux-musl-arm@1.85.0: + resolution: {integrity: sha512-Z1j4ageDVFihqNUBnm89fxY46pY0zD/Clp1D3ZdI7S+D280+AEpbm5vMoH8LLhBQfQLf2w7H++SZGpQwrisudQ==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] - sass-embedded-linux-musl-ia32@1.83.4: - resolution: {integrity: sha512-LLb4lYbcxPzX4UaJymYXC+WwokxUlfTJEFUv5VF0OTuSsHAGNRs/rslPtzVBTvMeG9TtlOQDhku1F7G6iaDotA==} + sass-embedded-linux-musl-ia32@1.85.0: + resolution: {integrity: sha512-/cJCSXOfXmQFH8deE+3U9x+BSz8i0d1Tt9gKV/Gat1Xm43Oumw8pmZgno+cDuGjYQInr9ryW5121pTMlj/PBXQ==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] - sass-embedded-linux-musl-riscv64@1.83.4: - resolution: {integrity: sha512-zoKlPzD5Z13HKin1UGR74QkEy+kZEk2AkGX5RelRG494mi+IWwRuWCppXIovor9+BQb9eDWPYPoMVahwN5F7VA==} + sass-embedded-linux-musl-riscv64@1.85.0: + resolution: {integrity: sha512-l+FJxMXkmg42RZq5RFKXg4InX0IA7yEiPHe4kVSdrczP7z3NLxk+W9wVkPnoRKYIMe1qZPPQ25y0TgI4HNWouA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - sass-embedded-linux-musl-x64@1.83.4: - resolution: {integrity: sha512-hB8+/PYhfEf2zTIcidO5Bpof9trK6WJjZ4T8g2MrxQh8REVtdPcgIkoxczRynqybf9+fbqbUwzXtiUao2GV+vQ==} + sass-embedded-linux-musl-x64@1.85.0: + resolution: {integrity: sha512-M9ffjcYfFcRvkFA6V3DpOS955AyvmpvPAhL/xNK45d/ma1n1ehTWpd24tVeKiNK5CZkNjjMEfyw2fHa6MpqmEA==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - sass-embedded-linux-riscv64@1.83.4: - resolution: {integrity: sha512-83fL4n+oeDJ0Y4KjASmZ9jHS1Vl9ESVQYHMhJE0i4xDi/P3BNarm2rsKljq/QtrwGpbqwn8ujzOu7DsNCMDSHA==} + sass-embedded-linux-riscv64@1.85.0: + resolution: {integrity: sha512-yqPXQWfM+qiIPkfn++48GOlbmSvUZIyL9nwFstBk0k4x40UhbhilfknqeTUpxoHfQzylTGVhrm5JE7MjM+LNZA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - sass-embedded-linux-x64@1.83.4: - resolution: {integrity: sha512-NlnGdvCmTD5PK+LKXlK3sAuxOgbRIEoZfnHvxd157imCm/s2SYF/R28D0DAAjEViyI8DovIWghgbcqwuertXsA==} + sass-embedded-linux-x64@1.85.0: + resolution: {integrity: sha512-NTDeQFZcuVR7COoaRy8pZD6/+QznwBR8kVFsj7NpmvX9aJ7TX/q+OQZHX7Bfb3tsfKXhf1YZozegPuYxRnMKAQ==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - sass-embedded-win32-arm64@1.83.4: - resolution: {integrity: sha512-J2BFKrEaeSrVazU2qTjyQdAk+MvbzJeTuCET0uAJEXSKtvQ3AzxvzndS7LqkDPbF32eXAHLw8GVpwcBwKbB3Uw==} + sass-embedded-win32-arm64@1.85.0: + resolution: {integrity: sha512-gO0VAuxC4AdV+uZYJESRWVVHQWCGzNs0C3OKCAdH4r1vGRugooMi7J/5wbwUdXDA1MV9ICfhlKsph2n3GiPdqA==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [win32] - sass-embedded-win32-ia32@1.83.4: - resolution: {integrity: sha512-uPAe9T/5sANFhJS5dcfAOhOJy8/l2TRYG4r+UO3Wp4yhqbN7bggPvY9c7zMYS0OC8tU/bCvfYUDFHYMCl91FgA==} + sass-embedded-win32-ia32@1.85.0: + resolution: {integrity: sha512-PCyn6xeFIBUgBceNypuf73/5DWF2VWPlPqPuBprPsTvpZOMUJeBtP+Lf4mnu3dNy1z76mYVnpaCnQmzZ0zHZaA==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [win32] - sass-embedded-win32-x64@1.83.4: - resolution: {integrity: sha512-C9fkDY0jKITdJFij4UbfPFswxoXN9O/Dr79v17fJnstVwtUojzVJWKHUXvF0Zg2LIR7TCc4ju3adejKFxj7ueA==} + sass-embedded-win32-x64@1.85.0: + resolution: {integrity: sha512-AknE2jLp6OBwrR5hQ8pDsG94KhJCeSheFJ2xgbnk8RUjZX909JiNbgh2sNt9LG+RXf4xZa55dDL537gZoCx/iw==} engines: {node: '>=14.0.0'} cpu: [x64] os: [win32] - sass-embedded@1.83.4: - resolution: {integrity: sha512-Hf2burRA/y5PGxsg6jB9UpoK/xZ6g/pgrkOcdl6j+rRg1Zj8XhGKZ1MTysZGtTPUUmiiErqzkP5+Kzp95yv9GQ==} + sass-embedded@1.85.0: + resolution: {integrity: sha512-x3Vv54g0jv1aPSW8OTA/0GzQCs/HMQOjIkLtZJ3Xsn/I4vnyjKbVTQmFTax9bQjldqLEEkdbvy6ES/cOOnYNwA==} engines: {node: '>=16.0.0'} hasBin: true - sass-loader@16.0.4: - resolution: {integrity: sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==} + sass-loader@16.0.5: + resolution: {integrity: sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==} engines: {node: '>= 18.12.0'} peerDependencies: '@rspack/core': 0.x || 1.x @@ -2360,10 +2368,6 @@ packages: sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} - schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} - schema-utils@4.2.0: resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} engines: {node: '>= 12.13.0'} @@ -2751,8 +2755,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.97.1: - resolution: {integrity: sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==} + webpack@5.98.0: + resolution: {integrity: sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -2904,9 +2908,9 @@ snapshots: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.4.0(eslint@9.19.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.20.1)': dependencies: - eslint: 9.19.0 + eslint: 9.20.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -2923,6 +2927,10 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@0.11.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -2953,7 +2961,7 @@ snapshots: '@eslint/js@8.57.1': {} - '@eslint/js@9.19.0': {} + '@eslint/js@9.20.0': {} '@eslint/object-schema@2.1.5': {} @@ -3043,9 +3051,9 @@ snapshots: '@sindresorhus/merge-streams@2.3.0': {} - '@swc/cli@0.6.0(@swc/core@1.10.14)': + '@swc/cli@0.6.0(@swc/core@1.10.16)': dependencies: - '@swc/core': 1.10.14 + '@swc/core': 1.10.16 '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 @@ -3056,51 +3064,51 @@ snapshots: slash: 3.0.0 source-map: 0.7.4 - '@swc/core-darwin-arm64@1.10.14': + '@swc/core-darwin-arm64@1.10.16': optional: true - '@swc/core-darwin-x64@1.10.14': + '@swc/core-darwin-x64@1.10.16': optional: true - '@swc/core-linux-arm-gnueabihf@1.10.14': + '@swc/core-linux-arm-gnueabihf@1.10.16': optional: true - '@swc/core-linux-arm64-gnu@1.10.14': + '@swc/core-linux-arm64-gnu@1.10.16': optional: true - '@swc/core-linux-arm64-musl@1.10.14': + '@swc/core-linux-arm64-musl@1.10.16': optional: true - '@swc/core-linux-x64-gnu@1.10.14': + '@swc/core-linux-x64-gnu@1.10.16': optional: true - '@swc/core-linux-x64-musl@1.10.14': + '@swc/core-linux-x64-musl@1.10.16': optional: true - '@swc/core-win32-arm64-msvc@1.10.14': + '@swc/core-win32-arm64-msvc@1.10.16': optional: true - '@swc/core-win32-ia32-msvc@1.10.14': + '@swc/core-win32-ia32-msvc@1.10.16': optional: true - '@swc/core-win32-x64-msvc@1.10.14': + '@swc/core-win32-x64-msvc@1.10.16': optional: true - '@swc/core@1.10.14': + '@swc/core@1.10.16': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.17 optionalDependencies: - '@swc/core-darwin-arm64': 1.10.14 - '@swc/core-darwin-x64': 1.10.14 - '@swc/core-linux-arm-gnueabihf': 1.10.14 - '@swc/core-linux-arm64-gnu': 1.10.14 - '@swc/core-linux-arm64-musl': 1.10.14 - '@swc/core-linux-x64-gnu': 1.10.14 - '@swc/core-linux-x64-musl': 1.10.14 - '@swc/core-win32-arm64-msvc': 1.10.14 - '@swc/core-win32-ia32-msvc': 1.10.14 - '@swc/core-win32-x64-msvc': 1.10.14 + '@swc/core-darwin-arm64': 1.10.16 + '@swc/core-darwin-x64': 1.10.16 + '@swc/core-linux-arm-gnueabihf': 1.10.16 + '@swc/core-linux-arm64-gnu': 1.10.16 + '@swc/core-linux-arm64-musl': 1.10.16 + '@swc/core-linux-x64-gnu': 1.10.16 + '@swc/core-linux-x64-musl': 1.10.16 + '@swc/core-win32-arm64-msvc': 1.10.16 + '@swc/core-win32-ia32-msvc': 1.10.16 + '@swc/core-win32-x64-msvc': 1.10.16 '@swc/counter@0.1.3': {} @@ -3114,11 +3122,13 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@types/chrome@0.0.301': + '@types/chrome@0.0.304': dependencies: '@types/filesystem': 0.0.32 '@types/har-format': 1.2.10 + '@types/eslint-config-prettier@6.11.3': {} + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -3151,7 +3161,7 @@ snapshots: '@types/minimatch@3.0.5': {} - '@types/node@22.13.1': + '@types/node@22.13.4': dependencies: undici-types: 6.20.0 @@ -3159,11 +3169,11 @@ snapshots: '@types/trusted-types@2.0.7': {} - '@types/webpack@5.28.5(@swc/core@1.10.14)(webpack-cli@6.0.1)': + '@types/webpack@5.28.5(@swc/core@1.10.16)(webpack-cli@6.0.1)': dependencies: - '@types/node': 22.13.1 + '@types/node': 22.13.4 tapable: 2.2.1 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -3172,7 +3182,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.13.1 + '@types/node': 22.13.4 '@ungap/structured-clone@1.2.0': {} @@ -3254,20 +3264,20 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': + '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.98.0)': dependencies: - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.97.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.98.0) - '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': + '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.98.0)': dependencies: - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.97.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.98.0) - '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.97.1)': + '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.98.0)': dependencies: - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.97.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.98.0) '@xhmikosr/archive-type@7.0.0': dependencies: @@ -3414,10 +3424,6 @@ snapshots: optionalDependencies: ajv: 8.17.1 - ajv-keywords@3.5.2(ajv@6.12.6): - dependencies: - ajv: 6.12.6 - ajv-keywords@5.1.0(ajv@8.12.0): dependencies: ajv: 8.12.0 @@ -3630,7 +3636,7 @@ snapshots: chrome-launcher@1.1.2: dependencies: - '@types/node': 22.13.1 + '@types/node': 22.13.4 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.1 @@ -3727,7 +3733,7 @@ snapshots: dependencies: safe-buffer: 5.2.1 - copy-webpack-plugin@12.0.2(webpack@5.97.1): + copy-webpack-plugin@12.0.2(webpack@5.98.0): dependencies: fast-glob: 3.3.2 glob-parent: 6.0.2 @@ -3735,7 +3741,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) core-util-is@1.0.3: {} @@ -3759,7 +3765,7 @@ snapshots: pbf: 3.2.1 yazl: 2.5.1 - css-loader@7.1.2(webpack@5.97.1): + css-loader@7.1.2(webpack@5.98.0): dependencies: icss-utils: 5.1.0(postcss@8.4.35) postcss: 8.4.35 @@ -3770,7 +3776,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.5.4 optionalDependencies: - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) css-select@5.1.0: dependencies: @@ -3891,9 +3897,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.0.1(eslint@9.19.0): + eslint-config-prettier@10.0.1(eslint@9.20.1): dependencies: - eslint: 9.19.0 + eslint: 9.20.1 eslint-plugin-no-unsanitized@4.1.2(eslint@8.57.1): dependencies: @@ -3961,14 +3967,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.19.0: + eslint@9.20.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.19.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.20.1) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.1 - '@eslint/core': 0.10.0 + '@eslint/core': 0.11.0 '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.19.0 + '@eslint/js': 9.20.0 '@eslint/plugin-kit': 0.2.5 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 @@ -4231,7 +4237,7 @@ snapshots: globals@14.0.0: {} - globals@15.14.0: {} + globals@15.15.0: {} globby@14.0.1: dependencies: @@ -4456,7 +4462,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.13.1 + '@types/node': 22.13.4 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -4580,11 +4586,11 @@ snapshots: mimic-response@4.0.0: {} - mini-css-extract-plugin@2.9.2(webpack@5.97.1): + mini-css-extract-plugin@2.9.2(webpack@5.98.0): dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) minimatch@3.1.2: dependencies: @@ -4868,7 +4874,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.4.2: {} + prettier@3.5.1: {} process-nextick-args@2.0.1: {} @@ -5008,67 +5014,67 @@ snapshots: safer-buffer@2.1.2: {} - sass-embedded-android-arm64@1.83.4: + sass-embedded-android-arm64@1.85.0: optional: true - sass-embedded-android-arm@1.83.4: + sass-embedded-android-arm@1.85.0: optional: true - sass-embedded-android-ia32@1.83.4: + sass-embedded-android-ia32@1.85.0: optional: true - sass-embedded-android-riscv64@1.83.4: + sass-embedded-android-riscv64@1.85.0: optional: true - sass-embedded-android-x64@1.83.4: + sass-embedded-android-x64@1.85.0: optional: true - sass-embedded-darwin-arm64@1.83.4: + sass-embedded-darwin-arm64@1.85.0: optional: true - sass-embedded-darwin-x64@1.83.4: + sass-embedded-darwin-x64@1.85.0: optional: true - sass-embedded-linux-arm64@1.83.4: + sass-embedded-linux-arm64@1.85.0: optional: true - sass-embedded-linux-arm@1.83.4: + sass-embedded-linux-arm@1.85.0: optional: true - sass-embedded-linux-ia32@1.83.4: + sass-embedded-linux-ia32@1.85.0: optional: true - sass-embedded-linux-musl-arm64@1.83.4: + sass-embedded-linux-musl-arm64@1.85.0: optional: true - sass-embedded-linux-musl-arm@1.83.4: + sass-embedded-linux-musl-arm@1.85.0: optional: true - sass-embedded-linux-musl-ia32@1.83.4: + sass-embedded-linux-musl-ia32@1.85.0: optional: true - sass-embedded-linux-musl-riscv64@1.83.4: + sass-embedded-linux-musl-riscv64@1.85.0: optional: true - sass-embedded-linux-musl-x64@1.83.4: + sass-embedded-linux-musl-x64@1.85.0: optional: true - sass-embedded-linux-riscv64@1.83.4: + sass-embedded-linux-riscv64@1.85.0: optional: true - sass-embedded-linux-x64@1.83.4: + sass-embedded-linux-x64@1.85.0: optional: true - sass-embedded-win32-arm64@1.83.4: + sass-embedded-win32-arm64@1.85.0: optional: true - sass-embedded-win32-ia32@1.83.4: + sass-embedded-win32-ia32@1.85.0: optional: true - sass-embedded-win32-x64@1.83.4: + sass-embedded-win32-x64@1.85.0: optional: true - sass-embedded@1.83.4: + sass-embedded@1.85.0: dependencies: '@bufbuild/protobuf': 2.2.0 buffer-builder: 0.2.0 @@ -5079,42 +5085,36 @@ snapshots: sync-child-process: 1.0.2 varint: 6.0.0 optionalDependencies: - sass-embedded-android-arm: 1.83.4 - sass-embedded-android-arm64: 1.83.4 - sass-embedded-android-ia32: 1.83.4 - sass-embedded-android-riscv64: 1.83.4 - sass-embedded-android-x64: 1.83.4 - sass-embedded-darwin-arm64: 1.83.4 - sass-embedded-darwin-x64: 1.83.4 - sass-embedded-linux-arm: 1.83.4 - sass-embedded-linux-arm64: 1.83.4 - sass-embedded-linux-ia32: 1.83.4 - sass-embedded-linux-musl-arm: 1.83.4 - sass-embedded-linux-musl-arm64: 1.83.4 - sass-embedded-linux-musl-ia32: 1.83.4 - sass-embedded-linux-musl-riscv64: 1.83.4 - sass-embedded-linux-musl-x64: 1.83.4 - sass-embedded-linux-riscv64: 1.83.4 - sass-embedded-linux-x64: 1.83.4 - sass-embedded-win32-arm64: 1.83.4 - sass-embedded-win32-ia32: 1.83.4 - sass-embedded-win32-x64: 1.83.4 - - sass-loader@16.0.4(sass-embedded@1.83.4)(webpack@5.97.1): + sass-embedded-android-arm: 1.85.0 + sass-embedded-android-arm64: 1.85.0 + sass-embedded-android-ia32: 1.85.0 + sass-embedded-android-riscv64: 1.85.0 + sass-embedded-android-x64: 1.85.0 + sass-embedded-darwin-arm64: 1.85.0 + sass-embedded-darwin-x64: 1.85.0 + sass-embedded-linux-arm: 1.85.0 + sass-embedded-linux-arm64: 1.85.0 + sass-embedded-linux-ia32: 1.85.0 + sass-embedded-linux-musl-arm: 1.85.0 + sass-embedded-linux-musl-arm64: 1.85.0 + sass-embedded-linux-musl-ia32: 1.85.0 + sass-embedded-linux-musl-riscv64: 1.85.0 + sass-embedded-linux-musl-x64: 1.85.0 + sass-embedded-linux-riscv64: 1.85.0 + sass-embedded-linux-x64: 1.85.0 + sass-embedded-win32-arm64: 1.85.0 + sass-embedded-win32-ia32: 1.85.0 + sass-embedded-win32-x64: 1.85.0 + + sass-loader@16.0.5(sass-embedded@1.85.0)(webpack@5.98.0): dependencies: neo-async: 2.6.2 optionalDependencies: - sass-embedded: 1.83.4 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + sass-embedded: 1.85.0 + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) sax@1.2.4: {} - schema-utils@3.3.0: - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - schema-utils@4.2.0: dependencies: '@types/json-schema': 7.0.11 @@ -5298,11 +5298,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swc-loader@0.2.6(@swc/core@1.10.14)(webpack@5.97.1): + swc-loader@0.2.6(@swc/core@1.10.16)(webpack@5.98.0): dependencies: - '@swc/core': 1.10.14 + '@swc/core': 1.10.16 '@swc/counter': 0.1.3 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) sync-child-process@1.0.2: dependencies: @@ -5318,16 +5318,16 @@ snapshots: fast-fifo: 1.3.2 streamx: 2.21.1 - terser-webpack-plugin@5.3.11(@swc/core@1.10.14)(webpack@5.97.1): + terser-webpack-plugin@5.3.11(@swc/core@1.10.16)(webpack@5.98.0): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) optionalDependencies: - '@swc/core': 1.10.14 + '@swc/core': 1.10.16 terser@5.37.0: dependencies: @@ -5483,12 +5483,12 @@ snapshots: - supports-color - utf-8-validate - webpack-cli@6.0.1(webpack@5.97.1): + webpack-cli@6.0.1(webpack@5.98.0): dependencies: '@discoveryjs/json-ext': 0.6.3 - '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.97.1) - '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.97.1) - '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.97.1) + '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.98.0) + '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.98.0) + '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.98.0) colorette: 2.0.19 commander: 12.1.0 cross-spawn: 7.0.3 @@ -5497,7 +5497,7 @@ snapshots: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1) + webpack: 5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1) webpack-merge: 6.0.1 webpack-merge@6.0.1: @@ -5508,7 +5508,7 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.97.1(@swc/core@1.10.14)(webpack-cli@6.0.1): + webpack@5.98.0(@swc/core@1.10.16)(webpack-cli@6.0.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.6 @@ -5528,13 +5528,13 @@ snapshots: loader-runner: 4.3.0 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 3.3.0 + schema-utils: 4.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.14)(webpack@5.97.1) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.16)(webpack@5.98.0) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 6.0.1(webpack@5.97.1) + webpack-cli: 6.0.1(webpack@5.98.0) transitivePeerDependencies: - '@swc/core' - esbuild diff --git a/src/UserJS/header.js b/src/UserJS/header.js index 1df7454..9b48860 100644 --- a/src/UserJS/header.js +++ b/src/UserJS/header.js @@ -29,6 +29,15 @@ if ( if (!(typeof userjs === 'object' && userjs.UserJS)) { return; } +const createPolicy = () => { + // Native implementation exists + if (window.trustedTypes && window.trustedTypes.createPolicy) { + window.trustedTypes.createPolicy('default', { + createHTML: (string) => string + }); + } +}; +createPolicy(); /** * Uncompressed locales + compiler * @@ -45,4 +54,4 @@ const translations = [[languageList]]; const main_css = `[[mainCSS]]`; /******************************************************************************/ [[code]] -})(); \ No newline at end of file +})(); diff --git a/src/UserJS/main.js b/src/UserJS/main.js index ffb8ca4..01bd3e7 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -119,29 +119,6 @@ function safeSelf() { return userjs.safeSelf; } -const trustedTypes = { - policy: false, - init() { - if (this.policy) { - return this.policy; - } - this.policy = true; - try { - // Native implementation exists - if (window.trustedTypes && window.trustedTypes.createPolicy) { - window.trustedTypes.createPolicy('default', { - createHTML: (string) => string - }); - } - } catch (ex) { - ex.cause = 'trustedTypes.init()'; - err(ex); - } - return this.policy; - } -}; -trustedTypes.init(); - const BLANK_PAGE = 'about:blank'; // Lets highlight me :) const authorID = 166061; @@ -149,6 +126,7 @@ const authorID = 166061; * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{{id}}` */ const goodUserJS = [ + 33005, 394820, 438684, 4870, @@ -180,11 +158,9 @@ const goodUserJS = [ 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' ]; -/** - * Remove UserJS from banned accounts - */ +/** Remove UserJS from banned accounts */ const badUserJS = [478597]; -// Unsupport webpages for each engine +/** Unsupport host for search engines */ const engineUnsupported = { greasyfork: ['pornhub.com'], sleazyfork: ['pornhub.com'], @@ -226,12 +202,15 @@ const builtinList = { pathname: '/hentai/.+/read/page/.+' } }; +// #region DEFAULT_CONFIG /** * @type { import("../typings/types.d.ts").config } */ const DEFAULT_CONFIG = { autofetch: true, autoinject: true, + autoSort: 'daily_installs', + clearTabCache: true, cache: true, codePreview: false, autoexpand: false, @@ -326,48 +305,46 @@ const DEFAULT_CONFIG = { } } }; -//#region i18n +// #endregion +// #region i18n class i18nHandler { constructor() { - /** @type { string[] } */ - this.cache = []; - - const { navigator } = safeSelf(); - const { languages } = navigator; - for (const nlang of languages) { - const lg = nlang.split('-')[0]; - if (this.cache.indexOf(lg) === -1) { - this.cache.push(lg); - } + if (userjs.pool !== undefined) { + return userjs.pool; } - - const current = navigator.language.split('-')[0] ?? 'en'; - if (!this.cache.includes(current)) { - this.cache.push(current); + userjs.pool = new Map(); + for (const [k, v] of Object.entries(translations)) { + if (!userjs.pool.has(k)) userjs.pool.set(k, v); } } + /** + * @param {string | Date | number} str + */ toDate(str = '') { const { navigator } = safeSelf(); - return new Intl.DateTimeFormat(navigator.language).format(new Date(str)); + return new Intl.DateTimeFormat(navigator.language).format( + typeof str === 'string' ? new Date(str) : str + ); } + /** + * @param {number | bigint} number + */ toNumber(number) { const { navigator } = safeSelf(); return new Intl.NumberFormat(navigator.language).format(number); } - i18n$(...keys) { + /** + * @type { import("../typings/UserJS.d.ts").i18n$ } + */ + i18n$(key) { const { navigator } = safeSelf(); const current = navigator.language.split('-')[0] ?? 'en'; - const list = translations[cfg.language] ?? translations[current]; - const arr = []; - for (const key of keys) { - arr.push(list[key]); - } - return arr.length !== 1 ? arr : arr[0]; + return userjs.pool.get(current)?.[key] ?? 'Unknown'; } } const language = new i18nHandler(); const { i18n$ } = language; -//#endregion +// #endregion // #region Utilities const union = (...arr) => [...new Set(arr.flat())]; /** @@ -396,20 +373,6 @@ const qsA = (selectors, root) => { * @type { import("../typings/types.d.ts").objToStr } */ const objToStr = (obj) => Object.prototype.toString.call(obj); -/** - * @type { import("../typings/types.d.ts").strToURL } - */ -const strToURL = (str) => { - const WIN_LOCATION = window.location ?? BLANK_PAGE; - try { - str = str ?? WIN_LOCATION; - return objToStr(str).includes('URL') ? str : new URL(str); - } catch (ex) { - ex.cause = 'strToURL'; - err(ex); - } - return WIN_LOCATION; -}; /** * @type { import("../typings/types.d.ts").isRegExp } */ @@ -495,6 +458,7 @@ const ael = (el, type, listener, options = {}) => { elem.addEventListener(type, listener, options); } } catch (ex) { + ex.cause = 'ael'; err(ex); } }; @@ -610,26 +574,12 @@ const dom = { }, cl: { add(target, token) { - if (Array.isArray(token)) { - for (const elem of normalizeTarget(target)) { - elem.classList.add(...token); - } - } else { - for (const elem of normalizeTarget(target)) { - elem.classList.add(token); - } - } + token = Array.isArray(token) ? token : [token]; + return normalizeTarget(target).some((elem) => elem.classList.add(...token)); }, remove(target, token) { - if (Array.isArray(token)) { - for (const elem of normalizeTarget(target)) { - elem.classList.remove(...token); - } - } else { - for (const elem of normalizeTarget(target)) { - elem.classList.remove(token); - } - } + token = Array.isArray(token) ? token : [token]; + return normalizeTarget(target).some((elem) => elem.classList.remove(...token)); }, toggle(target, token, force) { let r; @@ -639,12 +589,7 @@ const dom = { return r; }, has(target, token) { - for (const elem of normalizeTarget(target)) { - if (elem.classList.contains(token)) { - return true; - } - } - return false; + return normalizeTarget(target).some((elem) => elem.classList.contains(token)); } } }; @@ -761,6 +706,7 @@ const iconSVG = { try { if (typeof iconSVG[type].html === 'string') { svgElem.innerHTML = iconSVG[type].html; + dom.attr(svgElem, 'id', `mujs_${type ?? 'Unknown'}`); } // eslint-disable-next-line no-unused-vars } catch (ex) { @@ -779,6 +725,7 @@ const iconSVG = { */ const StorageSystem = { prefix: 'MUJS', + events: new Set(), getItem(key) { return window.localStorage.getItem(key); }, @@ -791,8 +738,47 @@ const StorageSystem = { remove(key) { window.localStorage.removeItem(key); }, + addListener(name, callback) { + if (isGM) { + let GMType; + if (isFN(GM.addValueChangeListener)) { + GMType = GM.addValueChangeListener(name, callback); + } else if (isFN(GM_addValueChangeListener)) { + GMType = GM_addValueChangeListener(name, callback); + } + if (GMType) { + return this.events.add(GMType) && GMType; + } + } + return ( + this.events.add(callback) && + window.addEventListener('storage', (evt) => { + const { key, oldValue, newValue } = evt; + if (key === name) callback(key, oldValue, newValue, false); + }) + ); + }, + attach() { + window.addEventListener('beforeunload', () => { + for (const e of this.events) { + if (isGM && typeof e === 'number' && !Number.isNaN(e)) { + if (isFN(GM.removeValueChangeListener)) { + GM.removeValueChangeListener(e); + } else if (isFN(GM_addValueChangeListener)) { + GM_removeValueChangeListener(e); + } + } else { + window.removeEventListener('storage', e); + } + this.events.delete(e); + } + }); + }, async setValue(key, v) { - v = typeof v === 'string' ? v : JSON.stringify(v ?? {}); + if (!v) { + return; + } + v = typeof v === 'string' ? v : JSON.stringify(v); if (isGM) { if (isFN(GM.setValue)) { await GM.setValue(key, v); @@ -861,9 +847,6 @@ const Network = { method, ...data }; - if (params.hermes) { - delete params.hermes; - } if (isGM && !useFetch) { if (params.credentials) { Object.assign(params, { @@ -914,8 +897,8 @@ const Network = { } else if (responseType.match(/clone/)) { resolve(check('clone')); } else if (responseType.match(/document/)) { - const domParser = new DOMParser(); const respTxt = check('text'); + const domParser = new DOMParser(); if (respTxt instanceof Promise) { respTxt.then((txt) => { const doc = domParser.parseFromString(txt, 'text/html'); @@ -1011,33 +994,45 @@ const Network = { return txt.replaceAll(/\W/g, ''); } }; -const sleazyRedirect = () => { - const locObj = window.top.location; - const { hostname } = locObj; - const gfSite = /greasyfork\.org/.test(hostname); - if (!gfSite && cfg.sleazyredirect) { - return; - } - const otherSite = gfSite ? 'sleazyfork' : 'greasyfork'; - if (!qs('span.sign-in-link')) { - return; - } - if (!/scripts\/\d+/.test(locObj.href)) { - return; - } - if ( - !qs('#script-info') && - (otherSite == 'greasyfork' || qs('div.width-constraint>section>p>a')) - ) { - const str = locObj.href.replace( - /\/\/([^.]+\.)?(greasyfork|sleazyfork)\.org/, - '//$1' + otherSite + '.org' - ); - info(`Redirecting to "${str}"`); - if (isFN(locObj.assign)) { - locObj.assign(str); - } else { - locObj.href = str; +const Counter = { + cnt: { + total: { + count: 0 + } + }, + set(engine) { + if (!this.cnt[engine.name]) { + const counter = make('count-frame', engine.enabled ? '' : 'hidden', { + dataset: { + counter: engine.name + }, + title: engine.query ? decodeURIComponent(engine.query) : engine.url, + textContent: '0' + }); + this.cnt[engine.name] = { + root: counter, + count: 0 + }; + return counter; + } + return this.cnt[engine.name].root; + }, + update(count, engine) { + this.cnt[engine.name].count += count; + this.cnt.total.count += count; + this.updateAll(); + }, + updateAll() { + for (const v of Object.values(this.cnt)) dom.text(v.root, v.count); + }, + reset() { + for (const [k, v] of Object.entries(this.cnt)) { + dom.text(v.root, 0); + v.count = 0; + const engine = cfg.engines.find((engine) => k === engine.name); + if (engine) { + dom.cl[engine.enabled ? 'remove' : 'add'](v.root, 'hidden'); + } } } }; @@ -1060,17 +1055,16 @@ class Container { unsaved; isBlacklisted; rebuild; - counters; opacityMin; opacityMax; constructor(url) { this.remove = this.remove.bind(this); this.refresh = this.refresh.bind(this); - this.updateCounter = this.updateCounter.bind(this); - this.updateCounters = this.updateCounters.bind(this); this.showError = this.showError.bind(this); + this.toArr = this.toArr.bind(this); + this.toElem = this.toElem.bind(this); - this.webpage = strToURL(url); + this.webpage = this.strToURL(url); this.host = this.getHost(this.webpage.host); this.domain = this.getDomain(this.webpage.host); this.ready = false; @@ -1078,7 +1072,7 @@ class Container { this.shadowRoot = undefined; this.supported = isFN(make('main-userjs').attachShadow); this.frame = this.supported - ? make('main-userjs', '', { + ? make('main-userjs', { dataset: { insertedBy: $info.script.name, role: 'primary-container' @@ -1108,9 +1102,9 @@ class Container { }); if (this.supported) { this.shadowRoot = this.frame.attachShadow({ - mode: 'open', - clonable: false, - delegatesfocus: false + mode: 'closed' + // clonable: false, + // delegatesfocus: false }); this.ready = true; } @@ -1120,9 +1114,6 @@ class Container { this.unsaved = false; this.isBlacklisted = false; this.rebuild = false; - this.counters = { - total: 0 - }; this.opacityMin = '0.15'; this.opacityMax = '1'; this.elementsReady = this.init(); @@ -1206,41 +1197,24 @@ class Container { initFn() { this.renderTheme(cfg.theme); - for (const engine of cfg.engines) { - if (engine.enabled) { - const counter = make('count-frame', '', { - dataset: { - counter: engine.name - }, - title: engine.query ? decodeURIComponent(engine.query) : engine.url, - textContent: '0' - }); - this.countframe.append(counter); - } - this.counters[engine.name] = 0; - } - - const cfgpage = this.cfgpage; - const table = this.table; - const exBtn = this.exBtn; - const supported = this.supported; - const frame = this.frame; - const refresh = this.refresh; - const cache = this.cache; - const cHost = this.host; - const urlBar = this.urlBar; + Counter.cnt.total.root = this.mainbtn; + for (const engine of cfg.engines) this.countframe.append(Counter.set(engine)); + const { cfgpage, table, exBtn, supported, frame, refresh, cache, urlBar, host } = this; class Tabs { /** * @param { HTMLElement } root */ constructor(root) { - this.Tab = new Map(); + /** + * @type { Set } + */ + this.pool = new Set(); this.blank = BLANK_PAGE; this.protocal = 'mujs:'; - this.protoReg = new RegExp(`${this.protocal}(.+)`); + this.protoReg = new RegExp(`${this.protocal}(.+)`, 'i'); this.el = { - add: make('mujs-addtab', '', { + add: make('mujs-addtab', { textContent: '+', dataset: { command: 'new-tab' @@ -1253,43 +1227,23 @@ class Container { this.el.root.append(this.el.head); this.custom = () => {}; } - hasTab(...params) { - for (const p of params) { - if (!this.Tab.has(p)) { - return false; - } - const content = normalizeTarget(this.Tab.get(p)).filter((t) => p === t.dataset.host); - if (isBlank(content)) { - return false; - } - } - return true; - } - storeTab(host) { - const h = host ?? this.blank; - if (!this.Tab.has(h)) { - this.Tab.set(h, new Set()); - } - return this.Tab.get(h); + /** + * @param {string} hostname + */ + getTab(hostname) { + return [...this.pool].find(({ dataset }) => hostname === dataset.host); } - cache(host, ...tabs) { - const h = host ?? this.blank; - const tabCache = this.storeTab(h); - for (const t of normalizeTarget(tabs)) { - if (tabCache.has(t)) { - continue; - } - tabCache.add(t); - } - this.Tab.set(h, tabCache); - return tabCache; + getActive() { + return [...this.pool].find((tab) => tab.classList.contains('active')); } - intFN(host) { - if (!host.startsWith(this.protocal)) { + /** + * @param {string} hostname + */ + intFN(hostname) { + if (!hostname.startsWith(this.protocal)) { return; } - const type = host.match(this.protoReg)[1]; - if (type === 'settings') { + if (hostname.match(this.protoReg)[1] === 'settings') { dom.cl.remove([cfgpage, exBtn], 'hidden'); dom.cl.add(table, 'hidden'); if (!supported) { @@ -1297,67 +1251,60 @@ class Container { } } } + /** + * @param {HTMLElement} tab + * @param {boolean} [build] + */ active(tab, build = true) { - for (const t of normalizeTarget(tab, false)) { - dom.cl.add([cfgpage, exBtn], 'hidden'); - dom.cl.remove(table, 'hidden'); - dom.cl.remove(qsA('mujs-tab', this.el.head), 'active'); - dom.cl.add(t, 'active'); - if (!build) { - continue; - } - const host = t.dataset.host ?? this.blank; - if (host === this.blank) { - refresh(); - } else if (host.startsWith(this.protocal)) { - this.intFN(host); - } else { - this.custom(host); - } + if (!this.pool.has(tab)) this.pool.add(tab); + dom.cl.add([cfgpage, exBtn], 'hidden'); + dom.cl.remove(table, 'hidden'); + dom.cl.remove([...this.pool], 'active'); + dom.cl.add(tab, 'active'); + if (!build) { + return; + } + const host = tab.dataset.host ?? this.blank; + if (host === this.blank) { + refresh(); + } else if (host.startsWith(this.protocal)) { + this.intFN(host); + } else { + this.custom(host); } } /** @param { HTMLElement } tab */ close(tab) { - for (const t of normalizeTarget(tab, false)) { - const host = t.dataset.host; - if (cache.has(host)) { - cache.delete(host); - } - if (dom.cl.has(t, 'active')) { - refresh(); - } - const sibling = t.previousElementSibling ?? t.nextElementSibling; - if (sibling) { - if (sibling.dataset.command !== 'new-tab') { - this.active(sibling); - } - } - if (this.Tab.has(host)) { - this.Tab.delete(host); + if (this.pool.has(tab)) this.pool.delete(tab); + const host = tab.dataset.host; + if (cfg.clearTabCache && cache.has(host)) cache.delete(host); + if (tab.classList.contains('active')) refresh(); + const sibling = tab.nextElementSibling ?? tab.previousElementSibling; + if (sibling) { + if (sibling.dataset.command !== 'new-tab') { + this.active(sibling); } - t.remove(); } + tab.remove(); } - create(host = undefined) { - if (typeof host === 'string') { - if (host.startsWith(this.protocal) && this.hasTab(host)) { - this.active(this.Tab.get(host)); - return; - } - const content = normalizeTarget(this.storeTab(host)).filter( - (t) => host === t.dataset.host - ); - if (!isEmpty(content)) { + /** + * @param {string} [hostname] + */ + create(hostname = undefined) { + if (typeof hostname === 'string') { + const createdTab = this.getTab(hostname); + if (this.protoReg.test(hostname) && createdTab) { + this.active(createdTab); return; } } - const tab = make('mujs-tab', '', { + const tab = make('mujs-tab', { dataset: { command: 'switch-tab' }, style: `order: ${this.el.head.childElementCount};` }); - const tabClose = make('mu-js', '', { + const tabClose = make('mu-js', { dataset: { command: 'close-tab' }, @@ -1368,29 +1315,28 @@ class Container { tab.append(tabHost, tabClose); this.el.head.append(tab); this.active(tab, false); - this.cache(host, tab); - if (isNull(host)) { + if (isNull(hostname)) { refresh(); urlBar.placeholder = i18n$('newTab'); tab.dataset.host = this.blank; tabHost.title = i18n$('newTab'); tabHost.textContent = i18n$('newTab'); - } else if (host.startsWith(this.protocal)) { - const type = host.match(this.protoReg)[1]; - tab.dataset.host = host || cHost; + } else if (hostname.startsWith(this.protocal)) { + const type = hostname.match(this.protoReg)[1]; + tab.dataset.host = hostname || host; tabHost.title = type || tab.dataset.host; tabHost.textContent = tabHost.title; - this.intFN(host); + this.intFN(hostname); } else { - tab.dataset.host = host || cHost; - tabHost.title = host || cHost; + tab.dataset.host = hostname || host; + tabHost.title = hostname || host; tabHost.textContent = tabHost.title; } return tab; } } this.tab = new Tabs(this.toolbar); - this.tab.create(this.host); + this.tab.create(host); const tabbody = this.tabbody; const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent; @@ -1532,9 +1478,9 @@ class Container { command: 'navigation' } }); - const makeTHead = (rows) => { + const makeTHead = (rows = []) => { const tr = make('tr'); - for (const r of normalizeTarget(rows)) { + for (const r of rows) { const tparent = make('th', r.class ?? '', r); tr.append(tparent); } @@ -1589,6 +1535,7 @@ class Container { this.unsaved = false; await StorageSystem.setValue('Config', cfg); info('Saved config:', cfg); + this.redirect(); return cfg; } /** @@ -1628,7 +1575,7 @@ class Container { return sty; } } - const sty = make('style', '', { + const sty = make('style', { textContent: css, dataset: { insertedBy: $info.script.name, @@ -1682,7 +1629,7 @@ class Container { return this.isBlacklisted; } getInfo(url) { - const webpage = strToURL(url || this.webpage); + const webpage = this.strToURL(url || this.webpage); const host = this.getHost(webpage.host); const domain = this.getDomain(webpage.host); return { @@ -1760,6 +1707,10 @@ class Container { } this.promptElem.append(el); } + /** + * @template {string | Error} E + * @param {...E} ex + */ showError(...ex) { err(...ex); const error = make('mu-js', 'error'); @@ -1776,34 +1727,74 @@ class Container { error.appendChild(createTextNode(str)); this.footer.append(error); } - updateCounter(count, engine) { - this.counters[engine.name] += count; - this.counters.total += count; - this.updateCounters(); + toArr() { + return Array.from(this.userjsCache.values()).filter(({ _mujs }) => { + return isElem(_mujs.root) && _mujs.info.engine.enabled; + }); } - updateCounters() { - for (const [k, v] of Object.entries(this.counters)) { - if (k === 'total') { - continue; - } - const c = qs(`count-frame[data-counter="${k}"]`, this.countframe); - if (c) { - dom.text(c, v); - } - } - dom.text(this.mainbtn, this.counters.total); + toElem() { + return this.toArr().map(({ _mujs }) => { + return _mujs.root; + }); } refresh() { this.urlBar.placeholder = i18n$('newTab'); - this.counters.total = 0; - for (const engine of cfg.engines) { - this.counters[engine.name] = 0; - } - this.updateCounters(); - dom.cl.remove(qsA('tr[data-engine]', this.tabbody), 'hidden'); + Counter.reset(); + dom.cl.remove(this.toElem(), 'hidden'); dom.cl.remove(qsA('mujs-section[data-name]', this.cfgpage), 'hidden'); dom.prop([this.tabbody, this.rateContainer, this.footer], 'innerHTML', ''); } + /** + * @template {string | URL} S + * @param {S} str + * @returns {URL} + */ + strToURL(str) { + const WIN_LOCATION = window.location ?? BLANK_PAGE; + try { + str = str ?? WIN_LOCATION; + return objToStr(str).includes('URL') ? str : new URL(str); + } catch (ex) { + ex.cause = 'strToURL'; + this.showError(ex); + } + return WIN_LOCATION; + } + /** + * Redirects sleazyfork userscripts from greasyfork.org to sleazyfork.org + * + * Taken from: https://greasyfork.org/scripts/23840 + */ + redirect() { + const locObj = window.top.location; + const { hostname } = locObj; + const gfSite = /greasyfork\.org/.test(hostname); + if (!gfSite && cfg.sleazyredirect) { + return; + } + const otherSite = gfSite ? 'sleazyfork' : 'greasyfork'; + if (!qs('span.sign-in-link')) { + return; + } + if (!/scripts\/\d+/.test(locObj.href)) { + return; + } + if ( + !qs('#script-info') && + (otherSite == 'greasyfork' || qs('div.width-constraint>section>p>a')) + ) { + const str = locObj.href.replace( + /\/\/([^.]+\.)?(greasyfork|sleazyfork)\.org/, + '//$1' + otherSite + '.org' + ); + info(`Redirecting to "${str}"`); + if (isFN(locObj.assign)) { + locObj.assign(str); + } else { + locObj.href = str; + } + } + } } const container = new Container(); // #endregion @@ -1820,8 +1811,6 @@ function primaryFN() { rateContainer, footer, tabbody, - toolbar, - tabhead, cfgpage, fsearch, btnfullscreen, @@ -1831,8 +1820,6 @@ function primaryFN() { btnissue, btngreasy, tab, - userjsCache, - updateCounter, showError } = container; const frameTimeout = container.timeouts.frame; @@ -1902,7 +1889,7 @@ function primaryFN() { } else if (prmpt !== prmptChoice) { installCode = dataset.userjs.replace(/\.user\.css$/, '.user.js'); } - const dlBtn = make('a', '', { + const dlBtn = make('a', { onclick(evt) { evt.preventDefault(); doInstallProcess(evt.target); @@ -1972,7 +1959,6 @@ function primaryFN() { dom.prop(rateContainer, 'innerHTML', ''); if (!dom.prop(target, 'disabled')) { const config = await container.save(); - sleazyRedirect(); if (container.rebuild) { container.cache.clear(); if (config.autofetch) { @@ -2052,7 +2038,7 @@ function primaryFN() { const apTo = (name, elem, root) => { const n = dataUserJS._mujs.code[name]; if (isEmpty(n)) { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: i18n$('listing_none') }); elem.append(el); @@ -2062,7 +2048,7 @@ function primaryFN() { dom.cl.remove(root, 'hidden'); for (const c of n) { if (typeof c === 'string' && c.startsWith('http')) { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: c, dataset: { command: 'open-tab', @@ -2073,7 +2059,7 @@ function primaryFN() { } else if (isObj(c)) { if (name === 'resource') { for (const [k, v] of Object.entries(c)) { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: k ?? 'ERROR' }); if (v.startsWith('http')) { @@ -2083,7 +2069,7 @@ function primaryFN() { elem.append(el); } } else { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: c.text }); if (c.domain) { @@ -2093,15 +2079,17 @@ function primaryFN() { elem.append(el); } } else { - const el = make('mujs-a', '', { + const el = make('mujs-a', { textContent: c }); elem.append(el); } } }; - const m = qsA('mujs-column[data-el="matches"]', target.parentElement.parentElement); - for (const e of normalizeTarget(m)) { + for (const e of qsA( + 'mujs-column[data-el="matches"]', + target.parentElement.parentElement + )) { apTo(e.dataset.type, qs('.mujs-grants', e), e); } } else if (/export-/.test(cmd)) { @@ -2136,7 +2124,6 @@ function primaryFN() { container.rebuild = true; rebuildCfg(); container.save().then((config) => { - sleazyRedirect(); container.cache.clear(); if (config.autofetch) { respHandles.build(); @@ -2469,42 +2456,23 @@ function primaryFN() { // return [...new Set(a)].filter((v) => arr.every((b) => b.includes(v))); // } } - const mergeTemplate = (obj = {}) => { - const template = { - id: 0, - bad_ratings: 0, - good_ratings: 0, - ok_ratings: 0, - daily_installs: 0, - total_installs: 0, - name: 'NOT FOUND', - description: 'NOT FOUND', - version: '0.0.0', - url: BLANK_PAGE, - code_url: BLANK_PAGE, - created_at: Date.now(), - code_updated_at: Date.now(), - locale: 'NOT FOUND', - deleted: false, - users: [ - { - id: 0, - name: 'NOT FOUND', - url: BLANK_PAGE - } - ] - }; - /** @type {ObjectConstructor["hasOwn"]} */ - const hasOwn = - Object.hasOwn || - function hasOwn(it, key) { - return Object.prototype.hasOwnProperty.call(it, key); - }; - for (const key in template) { - if (hasOwn(obj, key)) continue; - obj[key] = template[key]; - } - return obj; + const template = { + id: 0, + bad_ratings: 0, + good_ratings: 0, + ok_ratings: 0, + daily_installs: 0, + total_installs: 0, + name: 'NOT FOUND', + description: 'NOT FOUND', + version: '0.0.0', + url: BLANK_PAGE, + code_url: BLANK_PAGE, + created_at: Date.now(), + code_updated_at: Date.now(), + locale: 'NOT FOUND', + deleted: false, + users: [] }; const mkList = (txt = '', obj = {}) => { if (!obj.root || !obj.type) { @@ -2526,7 +2494,7 @@ function primaryFN() { const list = obj.list ?? []; if (isEmpty(list)) { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: i18n$('listing_none') }); applyList.append(elem); @@ -2535,7 +2503,7 @@ function primaryFN() { } for (const c of list) { if (typeof c === 'string' && c.startsWith('http')) { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: c, dataset: { command: 'open-tab', @@ -2546,7 +2514,7 @@ function primaryFN() { } else if (isObj(c)) { if (type === 'resource') { for (const [k, v] of Object.entries(c)) { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: k ?? 'ERROR' }); if (v.startsWith('http')) { @@ -2556,7 +2524,7 @@ function primaryFN() { applyList.append(elem); } } else { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: c.text }); if (c.domain) { @@ -2566,7 +2534,7 @@ function primaryFN() { applyList.append(elem); } } else { - const elem = make('mujs-a', '', { + const elem = make('mujs-a', { textContent: c }); applyList.append(elem); @@ -2596,7 +2564,6 @@ function primaryFN() { * @param { string } engine */ const createjs = (ujs, engine) => { - ujs = mergeTemplate(ujs); // Lets not add this UserJS to the list if (ujs.id === 421603) { return; @@ -2688,7 +2655,7 @@ function primaryFN() { userjs: ujs.code_url } }); - const scriptDownload = make('mu-jsbtn', '', { + const scriptDownload = make('mu-jsbtn', { innerHTML: `${iconSVG.load('install')} ${i18n$('saveFile')}`, dataset: { command: 'download-userjs', @@ -2710,7 +2677,7 @@ function primaryFN() { spellcheck: false, wrap: 'soft' }); - const loadCode = make('mu-jsbtn', '', { + const loadCode = make('mu-jsbtn', { innerHTML: `${iconSVG.load('search')} ${i18n$('preview_code')}`, dataset: { command: 'load-userjs', @@ -2730,7 +2697,7 @@ function primaryFN() { } } for (const u of ujs.users) { - const user = make('mujs-a', '', { + const user = make('mujs-a', { innerHTML: u.name, title: u.url, dataset: { @@ -2793,63 +2760,73 @@ function primaryFN() { codeArea.value = code_obj.get_code_block(); } - if (ujs._mujs.code?.translated) { - tr.classList.add('translated'); - } + if (ujs._mujs.code?.translated) tr.classList.add('translated'); - for (const e of [fname, uframe, fdaily, fupdated, eframe]) { - tr.append(e); - } - tabbody.append(tr); + for (const e of [fname, uframe, fdaily, fupdated, eframe]) tr.append(e); ujs._mujs.root = tr; return tr; }; // #endregion const loadFilters = () => { - const resp = []; - for (const v of Object.values(cfg.filters)) { - if (!v.enabled) { - continue; - } - resp.push(new RegExp(v.regExp, v.flag)); - } - return { - regExp: resp, - get(name) { - for (const v of Object.values(cfg.filters)) { - if (v.name === name) { - return new RegExp(v.regExp, v.flag) - }; + /** @type {Map} */ + const pool = new Map(); + const handles = { + pool, + enabled() { + return [...pool.values()].filter((o) => o.enabled); + }, + refresh() { + if (!Object.is(pool.size, 0)) pool.clear(); + for (const [key, value] of Object.entries(cfg.filters)) { + if (!pool.has(key)) + pool.set(key, { + ...value, + reg: new RegExp(value.regExp, value.flag), + keyReg: new RegExp(key.trim().toLocaleLowerCase(), 'gi'), + valueReg: new RegExp(value.name.trim().toLocaleLowerCase(), 'gi') + }); } - // return resp.find(r => r.name === name); + return this; }, + get(str) { + return [...pool.values()].find((v) => v.keyReg.test(str) || v.valueReg.test(str)); + }, + /** + * @param { import("../typings/types.d.ts").GSForkQuery } param0 + */ match({ name, users }) { - if (isBlank(resp)) { - return true; - } - const strArr = [{ name }, ...users]; - for (const r of resp) { - const v = strArr.find((o) => o.name.match(r)); - if (v) { - return false; - } + const p = handles.enabled(); + if (Object.is(p.length, 0)) return true; + for (const v of p) { + if ([{ name }, ...users].find((o) => o.name.match(v.reg))) return false; } return true; } }; + for (const [key, value] of Object.entries(cfg.filters)) { + if (!pool.has(key)) + pool.set(key, { + ...value, + reg: new RegExp(value.regExp, value.flag), + keyReg: new RegExp(key.trim().toLocaleLowerCase(), 'gi'), + valueReg: new RegExp(value.name.trim().toLocaleLowerCase(), 'gi') + }); + } + return handles.refresh(); }; // #region List class List { engines; - cache; intHost; - constructor(host = undefined) { + constructor(hostname = undefined) { this.build = this.build.bind(this); - if (isEmpty(host)) host = container.host; + this.toArr = this.toArr.bind(this); + this.groupBy = this.groupBy.bind(this); + this.sortRecords = this.sortRecords.bind(this); + if (isEmpty(hostname)) hostname = container.host; this.engines = cfg.engines; - this.cache = container.cache.get(host); - this.host = host; + this.host = hostname; } set host(hostname) { @@ -2862,27 +2839,24 @@ function primaryFN() { } container.cache.set(hostname, engineTemplate); } - if (container.checkBlacklist(hostname)) { + this.blacklisted = container.checkBlacklist(hostname); + if (this.blacklisted) { showError(`Blacklisted "${hostname}"`); timeoutFrame(); - this.blacklisted = true; - } else { - this.blacklisted = false; } - const isSupported = (name) => { - for (const [k, v] of Object.entries(engineUnsupported)) { - if (k !== name) { - continue; - } - if (v.includes(hostname)) { - return false; - } + this.engines = cfg.engines.filter((e) => { + if (!e.enabled) { + return false; + } + const v = engineUnsupported[e.name] ?? []; + if (v.includes(hostname)) { + showError(`Engine: "${e.name}" unsupported on "${hostname}"`); + timeoutFrame(); + return false; } return true; - }; - this.engines = cfg.engines.filter((e) => e.enabled && isSupported(e.name)); - this.cache = container.cache.get(hostname); + }); } get host() { @@ -2893,235 +2867,228 @@ function primaryFN() { build() { try { container.refresh(); - if (this.blacklisted) { - return; - } - if (isEmpty(this.engines)) { + const { blacklisted, engines, host, toArr } = this; + if (blacklisted || isEmpty(engines)) { container.opacityMin = '0'; mainframe.style.opacity = container.opacityMin; return; } - info(' Building list', { cache: this.cache, engines: this.engines }); - const customRecords = []; - const host = this.host; - const arr = []; + const fetchRecords = []; const bsFilter = loadFilters(); + const hostCache = toArr(); - for (const engine of this.engines) { - const cEngine = this.cache[`${engine.name}`]; - if (!isEmpty(cEngine)) { - for (const ujs of cEngine) { - if (isElem(ujs._mujs.root)) { - tabbody.append(ujs._mujs.root); + info('Building list', { hostCache, engines }); + + if (isBlank(hostCache)) { + for (const engine of engines) { + info(`Fetching from "${engine.name}" for "${host}"`); + const respError = (error) => { + if (!error.cause) error.cause = engine.name; + if (error.message.startsWith('429')) { + showError(`Engine: "${engine.name}" Too many requests...`); + return; } - } - updateCounter(cEngine.length, engine); - continue; - } - const respError = (error) => { - if (!error.cause) error.cause = engine.name; - if (error.message.startsWith('429')) { - showError(`Engine: "${engine.name}" Too many requests...`); - return; - } - showError(`Engine: "${engine.name}"`, error.message); - }; - const _mujs = (d) => { - const obj = { - ...d, - _mujs: { - root: {}, - info: { - engine, - host - }, - code: { - antifeatures: [], - grant: [], - match: [], - meta: {}, - request: async function (translate = false, code_url) { - if (this.data) { - return this; - } - this.data = ''; - /** @type { string } */ - const code = await Network.req(code_url ?? d.code_url, 'GET', 'text').catch( - showError - ); - if (typeof code !== 'string') { - return this; - } - Object.assign(this, { - data: code, - code_size: [Network.format(code.length)] - }); - const grantSet = new Set(); - const afSet = new Set(); - const code_obj = new ParseUserJS(code); - const meta = code_obj.parse_meta(); - const applies_to_names = code_obj.calculate_applies_to_names(); - - if (translate) { - for (const lng of language.cache) { - if (meta[`name:${lng}`]) { - Object.assign(obj, { - name: meta[`name:${lng}`] - }); - this.translated = true; - } - if (meta[`description:${lng}`]) { - Object.assign(obj, { - description: meta[`description:${lng}`] - }); - this.translated = true; + showError(`Engine: "${engine.name}"`, error.message); + }; + const _mujs = (d) => { + const obj = { + ...template, + ...d, + _mujs: { + root: {}, + info: { + engine, + host + }, + code: { + antifeatures: [], + grant: [], + match: [], + meta: {}, + request: async function (translate = false, code_url) { + if (this.data) { + return this; + } + this.data = ''; + /** @type { string } */ + const code = await Network.req(code_url ?? d.code_url, 'GET', 'text').catch( + showError + ); + if (typeof code !== 'string') { + return this; + } + Object.assign(this, { + data: code, + code_size: [Network.format(code.length)] + }); + const grantSet = new Set(); + const afSet = new Set(); + const code_obj = new ParseUserJS(code); + const meta = code_obj.parse_meta(); + const applies_to_names = code_obj.calculate_applies_to_names(); + + if (translate) { + for (const k of userjs.pool.keys()) { + if (meta[`name:${k}`]) { + Object.assign(obj, { + name: meta[`name:${k}`] + }); + this.translated = true; + } + if (meta[`description:${k}`]) { + Object.assign(obj, { + description: meta[`description:${k}`] + }); + this.translated = true; + } } } - } - for (const [key, value] of Object.entries(meta)) { - if (/grant/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (grantSet.has(v)) { - continue; + for (const [key, value] of Object.entries(meta)) { + if (/grant/.test(key)) { + for (const v of normalizeTarget(value, false)) { + if (grantSet.has(v)) { + continue; + } + grantSet.add(v); } - grantSet.add(v); - } - } else if (/antifeature/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (afSet.has(v)) { - continue; + } else if (/antifeature/.test(key)) { + for (const v of normalizeTarget(value, false)) { + if (afSet.has(v)) { + continue; + } + afSet.add(v); } - afSet.add(v); } } - } - if (typeof meta.require === 'string') { - const s = meta.require; - meta.require = [s]; - } - if (meta.resource) { - const obj = {}; - if (typeof meta.resource === 'string') { - const reg = /(.+)\s+(.+)/.exec(meta.resource); - if (reg) { - obj[reg[1].trim()] = reg[2]; - } - } else { - for (const r of meta.resource) { - const reg = /(.+)\s+(http.+)/.exec(r); + if (typeof meta.require === 'string') { + const s = meta.require; + meta.require = [s]; + } + if (meta.resource) { + const obj = {}; + if (typeof meta.resource === 'string') { + const reg = /(.+)\s+(.+)/.exec(meta.resource); if (reg) { obj[reg[1].trim()] = reg[2]; } + } else { + for (const r of meta.resource) { + const reg = /(.+)\s+(http.+)/.exec(r); + if (reg) { + obj[reg[1].trim()] = reg[2]; + } + } } + meta.resource = obj; } - meta.resource = obj; - } - Object.assign(this, { - meta, - match: applies_to_names, - grant: [...grantSet], - antifeatures: [...afSet] - }); + Object.assign(this, { + meta, + match: applies_to_names, + grant: [...grantSet], + antifeatures: [...afSet] + }); - return this; + return this; + } } } - } + }; + return obj; }; - return obj; - }; - const toQuery = (fallback) => { - if (engine.query) { - return decodeURIComponent(engine.query).replace(/\{host\}/g, host); - } - return fallback; - }; - /** - * @param { import("../typings/types.d.ts").GSFork } dataQ - */ - const forkFN = async (dataQ) => { - if (!dataQ) { - showError('Invalid data received from the server, check internet connection'); - return; - } /** - * @type { import("../typings/types.d.ts").GSForkQuery[] } + * Prior to UserScript v7.0.0 + * @template {string} F + * @param {F} fallback + * @returns {F} */ - const dq = Array.isArray(dataQ) - ? dataQ - : Array.isArray(dataQ.query) - ? dataQ.query - : []; - const dataA = dq - .filter(Boolean) - .filter((d) => !d.deleted) - .filter(bsFilter.match); - if (isBlank(dataA)) { - return; - } - const data = dataA.map(_mujs); - const otherLng = []; + const toQuery = (fallback) => { + if (engine.query) { + return decodeURIComponent(engine.query).replace(/\{host\}/g, host); + } + return fallback; + }; /** - * @param {import("../typings/types.d.ts").GSForkQuery} d - * @returns {boolean} + * @param { import("../typings/types.d.ts").GSFork } dataQ */ - const inUserLanguage = (d) => { - const dlocal = d.locale.split('-')[0] ?? d.locale; - if (language.cache.includes(dlocal)) { - return true; + const forkFN = async (dataQ) => { + if (!dataQ) { + showError('Invalid data received from the server, check internet connection'); + return; } - otherLng.push(d); - return false; - }; - const filterLang = data.filter((d) => { - if (cfg.filterlang && !inUserLanguage(d)) { - return false; + /** + * @type { import("../typings/types.d.ts").GSForkQuery[] } + */ + const dq = Array.isArray(dataQ) + ? dataQ + : Array.isArray(dataQ.query) + ? dataQ.query + : []; + const dataA = dq + .filter(Boolean) + .filter((d) => !d.deleted) + .filter(bsFilter.match); + if (isBlank(dataA)) { + return; } - return true; - }); - let finalList = filterLang; - const hds = []; - for (const ujs of otherLng) { - const c = await ujs._mujs.code.request(true); - if (c.translated) { - hds.push(ujs); + const data = dataA.map(_mujs); + const otherLng = []; + /** + * @param {import("../typings/types.d.ts").GSForkQuery} d + * @returns {boolean} + */ + const inUserLanguage = (d) => { + if (userjs.pool.has(d.locale.split('-')[0] ?? d.locale)) { + return true; + } + otherLng.push(d); + return false; + }; + const filterLang = data.filter((d) => { + if (cfg.filterlang && !inUserLanguage(d)) { + return false; + } + return true; + }); + let finalList = filterLang; + const hds = []; + for (const ujs of otherLng) { + const c = await ujs._mujs.code.request(true); + if (c.translated) { + hds.push(ujs); + } } - } - finalList = union(hds, filterLang); + finalList = union(hds, filterLang); - for (const ujs of finalList) { - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); - } - createjs(ujs, engine.name); - } - this.cache[engine.name].push(...finalList); - updateCounter(finalList.length, engine); - }; - /** - * @param {Document} htmlDocument - */ - const openuserjs = async (htmlDocument) => { - try { - if (!htmlDocument) { - showError('Invalid data received from the server, TODO fix this'); - return; + for (const ujs of finalList) { + if (cfg.codePreview && !ujs._mujs.code.data) { + await ujs._mujs.code.request(); + } + createjs(ujs, engine.name); } - const selected = htmlDocument.documentElement; - if (/openuserjs/gi.test(engine.name)) { - for (const i of qsA('.col-sm-8 .tr-link', selected)) { - while (isNull(qs('.script-version', i))) { - await new Promise((resolve) => requestAnimationFrame(resolve)); - } - const fixurl = dom - .prop(qs('.tr-link-a', i), 'href') - .replace( - new RegExp(document.location.origin, 'gi'), - 'https://openuserjs.org' - ); - const ujs = mergeTemplate( - _mujs({ + }; + /** + * @param {Document} htmlDocument + */ + const openuserjs = async (htmlDocument) => { + try { + if (!htmlDocument) { + showError('Invalid data received from the server, TODO fix this'); + return; + } + const selected = htmlDocument.documentElement; + if (/openuserjs/gi.test(engine.name)) { + for (const i of qsA('.col-sm-8 .tr-link', selected)) { + while (isNull(qs('.script-version', i))) { + await new Promise((resolve) => requestAnimationFrame(resolve)); + } + const fixurl = dom + .prop(qs('.tr-link-a', i), 'href') + .replace( + new RegExp(document.location.origin, 'gi'), + 'https://openuserjs.org' + ); + const ujs = _mujs({ name: dom.text(qs('.tr-link-a', i)), description: dom.text(qs('p', i)), version: dom.text(qs('.script-version', i)), @@ -3136,33 +3103,28 @@ function primaryFN() { url: dom.prop(qs('.inline-block a', i), 'href') } ] - }) - ); - if (bsFilter.match(ujs)) { - continue; - } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + }); + if (bsFilter.match(ujs)) { + continue; + } + if (cfg.codePreview && !ujs._mujs.code.data) { + await ujs._mujs.code.request(); + } + createjs(ujs, engine.name); } - createjs(ujs, engine.name); - customRecords.push(ujs); } + } catch (ex) { + showError(ex); } - this.cache[engine.name].push(...customRecords); - updateCounter(customRecords.length, engine); - } catch (ex) { - showError(ex); - } - }; - const gitFN = async (data) => { - try { - if (isBlank(data.items)) { - showError('Invalid data received from the server, TODO fix this'); - return; - } - for (const r of data.items) { - const ujs = mergeTemplate( - _mujs({ + }; + const gitFN = async (data) => { + try { + if (isBlank(data.items)) { + showError('Invalid data received from the server, TODO fix this'); + return; + } + for (const r of data.items) { + const ujs = _mujs({ name: r.name, description: isEmpty(r.repository.description) ? i18n$('no_license') @@ -3177,87 +3139,118 @@ function primaryFN() { url: r.repository.owner.html_url } ] - }) - ); - if (bsFilter.match(ujs)) { - continue; - } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + }); + if (bsFilter.match(ujs)) { + continue; + } + if (cfg.codePreview && !ujs._mujs.code.data) { + await ujs._mujs.code.request(); + } + createjs(ujs, engine.name); } - createjs(ujs, engine.name); - customRecords.push(ujs); + } catch (ex) { + showError(ex); } - this.cache[engine.name].push(...customRecords); - updateCounter(data.items.length, engine); - } catch (ex) { - showError(ex); - } - }; - let netFN; - if (/github/gi.test(engine.name)) { - if (isEmpty(engine.token)) { - showError(`"${engine.name}" requires a token to use`); - continue; - } - netFN = Network.req( - toQuery( - `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` - ), - 'GET', - 'json', - { - headers: { - Accept: 'application/vnd.github+json', - Authorization: `Bearer ${engine.token}`, - 'X-GitHub-Api-Version': '2022-11-28' - } + }; + let netFN; + if (/github/gi.test(engine.name)) { + if (isEmpty(engine.token)) { + showError(`"${engine.name}" requires a token to use`); + continue; } - ) - .then(gitFN) - .then(() => { - Network.req('https://api.github.com/rate_limit', 'GET', 'json', { + netFN = Network.req( + toQuery( + `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` + ), + 'GET', + 'json', + { headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${engine.token}`, 'X-GitHub-Api-Version': '2022-11-28' } - }) - .then((data) => { - for (const [key, value] of Object.entries(data.resources.code_search)) { - const txt = make('mujs-row', 'rate-info', { - textContent: `${key.toUpperCase()}: ${value}` - }); - rateContainer.append(txt); + } + ) + .then(gitFN) + .then(() => { + Network.req('https://api.github.com/rate_limit', 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' } }) - .catch(respError); - }); - } else if (/openuserjs/gi.test(engine.name)) { - netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document').then( - openuserjs - ); - } else { - netFN = Network.req( - toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) - ).then(forkFN); - } - if (netFN) { - arr.push(netFN.catch(respError)); + .then((data) => { + for (const [key, value] of Object.entries(data.resources.code_search)) { + const txt = make('mujs-row', 'rate-info', { + textContent: `${key.toUpperCase()}: ${value}` + }); + rateContainer.append(txt); + } + }) + .catch(respError); + }); + } else if (/openuserjs/gi.test(engine.name)) { + netFN = Network.req(toQuery(`${engine.url}${host}`), 'GET', 'document').then( + openuserjs + ); + } else { + netFN = Network.req( + toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) + ).then(forkFN); + } + if (netFN) { + fetchRecords.push(netFN.catch(respError)); + } } + } else { + for (const ujs of hostCache) tabbody.append(ujs._mujs.root); } urlBar.placeholder = i18n$('search_placeholder'); urlBar.value = ''; - Promise.allSettled(arr).then(() => { - tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); - tabhead.rows[0].cells[2].dispatchEvent(new MouseEvent('click')); - }); + if (isBlank(fetchRecords)) { + this.sortRecords(); + return; + } + Promise.allSettled(fetchRecords).then(this.sortRecords).catch(showError); } catch (ex) { showError(ex); } } + + sortRecords() { + const arr = this.toArr(); + for (const ujs of arr.flat().sort((a, b) => { + const sortType = cfg.autoSort ?? 'daily_installs'; + return b[sortType] - a[sortType]; + })) { + if (isElem(ujs._mujs.root)) tabbody.append(ujs._mujs.root); + } + for (const [name, value] of Object.entries(this.groupBy(arr))) + Counter.update(value.length, { name }); + } + + toArr() { + const h = this.intHost; + return container.toArr().filter(({ _mujs }) => _mujs.info.host === h); + } + + groupBy(arr) { + const callback = ({ _mujs }) => _mujs.info.engine.name; + if (isFN(Object.groupBy)) { + return Object.groupBy(arr, callback); + } + /** [Object.groupBy polyfill](https://gist.github.com/gtrabanco/7c97bd41aa74af974fa935bfb5044b6e) */ + return arr.reduce((acc = {}, ...args) => { + const key = callback(...args); + acc[key] ??= []; + acc[key].push(args[0]); + return acc; + }, {}); + } // #endregion } const MUList = new List(); @@ -3281,17 +3274,17 @@ function primaryFN() { const makesection = (name, tag) => { tag = tag ?? i18n$('no_license'); name = name ?? i18n$('no_license'); - const sec = make('mujs-section', '', { + const sec = make('mujs-section', { dataset: { name: tag } }); - const lb = make('label', '', { + const lb = make('label', { dataset: { command: tag } }); - const divDesc = make('mu-js', '', { + const divDesc = make('mu-js', { textContent: name }); ael(sec, 'click', (evt) => { @@ -3330,13 +3323,13 @@ function primaryFN() { const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); - const sec = make('mujs-section', '', { + const sec = make('mujs-section', { dataset: { name: nm } }); const lb = make('label'); - const divDesc = make('mu-js', '', { + const divDesc = make('mu-js', { textContent: desc }); lb.append(divDesc); @@ -3345,7 +3338,7 @@ function primaryFN() { if (isNull(type)) { return lb; } - const inp = make('input', '', { + const inp = make('input', { type, dataset: { name: nm @@ -3357,7 +3350,7 @@ function primaryFN() { } if (type === 'checkbox') { const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', '', { + const la = make('label', { onclick() { inp.dispatchEvent(new MouseEvent('click')); } @@ -3380,7 +3373,7 @@ function primaryFN() { if (engine.query) { const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); - const urlInp = make('input', '', { + const urlInp = make('input', { type: 'text', defaultValue: '', value: decodeURIComponent(engine.query) ?? '', @@ -3402,7 +3395,7 @@ function primaryFN() { sec.append(urlInp); } if (engine.name === 'github') { - const ghToken = make('input', '', { + const ghToken = make('input', { type: 'text', defaultValue: '', value: engine.token ?? '', @@ -3443,7 +3436,29 @@ function primaryFN() { [tag]: text } }); - const inp = make('input', '', { + if (type === 'select') { + const inp = make('select', { + dataset: { + [tag]: text + }, + ...attrs + }); + for (const selV of Object.keys(template)) { + if (selV === 'deleted' || selV === 'users') continue; + const o = make('option', { + value: selV, + textContent: selV + }); + inp.append(o); + } + inp.value = cfg[value]; + lb.append(inp); + if (sections[tag]) { + sections[tag].append(lb); + } + return lb; + } + const inp = make('input', { type, dataset: { [tag]: text @@ -3457,7 +3472,7 @@ function primaryFN() { if (type === 'checkbox') { const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', '', { + const la = make('label', { onclick() { inp.dispatchEvent(new MouseEvent('click')); } @@ -3547,7 +3562,9 @@ function primaryFN() { } } }); + mkSection('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); + mkSection('Default Sort', 'autoSort', 'select', 'list'); mkSection(i18n$('filter'), 'filterlang', 'checkbox', 'list'); mkSection(i18n$('preview_code'), 'codePreview', 'checkbox', 'list'); mkSection('Recommend author', 'recommend-author', 'checkbox', 'list'); @@ -3569,7 +3586,7 @@ function primaryFN() { theme: k } }); - const inp = make('input', '', { + const inp = make('input', { type: 'text', defaultValue: '', value: v ?? '', @@ -3643,7 +3660,7 @@ function primaryFN() { blacklist: key } }); - const inp = make('input', '', { + const inp = make('input', { type: 'text', defaultValue: '', value: v ?? '', @@ -3673,7 +3690,7 @@ function primaryFN() { } } }); - const selType = make('select', '', { + const selType = make('select', { disabled, dataset: { blacklist: key @@ -3681,14 +3698,14 @@ function primaryFN() { }); if (disabled) { inp.readOnly = true; - const o = make('option', '', { + const o = make('option', { value: type, textContent: type }); selType.append(o); } else { for (const selV of ['String', 'RegExp', 'Object']) { - const o = make('option', '', { + const o = make('option', { value: selV, textContent: selV }); @@ -3699,7 +3716,7 @@ function primaryFN() { lb.append(inp, selType); sections.blacklist.append(lb); }; - // const blacklist = make('textarea', '', { + // const blacklist = make('textarea', { // dataset: { // name: 'blacklist' // }, @@ -3728,19 +3745,19 @@ function primaryFN() { // } // }); // cfgMap.set('blacklist', blacklist); - // const addList = make('mujs-add', '', { + // const addList = make('mujs-add', { // textContent: '+', // dataset: { // command: 'new-list' // } // }); - // const n = make('input', '', { + // const n = make('input', { // type: 'text', // defaultValue: '', // value: '', // placeholder: 'Name', // }); - // const inpValue = make('input', '', { + // const inpValue = make('input', { // type: 'text', // defaultValue: '', // value: '', @@ -3806,15 +3823,16 @@ function primaryFN() { * @type { string } */ const val = evt.target.value; + const section = qsA('mujs-section[data-name]', cfgpage); if (isEmpty(val)) { - dom.cl.remove(qsA('tr[data-engine]', tabbody), 'hidden'); - dom.cl.remove(qsA('mujs-section[data-name]', cfgpage), 'hidden'); + dom.cl.remove(container.toElem(), 'hidden'); + dom.cl.remove(section, 'hidden'); return; } const finds = new Set(); if (!dom.cl.has(cfgpage, 'hidden')) { const reg = new RegExp(val, 'gi'); - for (const elem of qsA('mujs-section[data-name]', cfgpage)) { + for (const elem of section) { if (!isElem(elem)) { continue; } @@ -3825,10 +3843,13 @@ function primaryFN() { finds.add(elem); } } - dom.cl.add(qsA('mujs-section[data-name]', cfgpage), 'hidden'); + dom.cl.add(section, 'hidden'); dom.cl.remove([...finds], 'hidden'); return; } + const cacheValues = container.toArr().filter(({ _mujs }) => { + return !finds.has(_mujs.root); + }); /** * @param {RegExpMatchArray} regExp * @param {keyof import("../typings/types.d.ts").GSForkQuery} key @@ -3836,43 +3857,29 @@ function primaryFN() { const ezQuery = (regExp, key) => { const q_value = val.replace(regExp, ''); const reg = new RegExp(q_value, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } + for (const v of cacheValues) { let k = v[key]; if (typeof k === 'number') { k = `${v[key]}`; } if (k && k.match(reg)) { - finds.add(elem); + finds.add(v._mujs.root); } } }; if (val.match(/^(code_url|url):/)) { ezQuery(/^(code_url|url):/, 'code_url'); } else if (val.match(/^(author|users?):/)) { - const q_value = val.replace(/^(author|users?):/, ''); - const reg = new RegExp(q_value, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v.users) { + const parts = /^[\w_]+:(.+)/.exec(val); + if (parts) { + const reg = new RegExp(parts[1], 'gi'); + for (const v of cacheValues.filter((v) => !isEmpty(v.users))) { for (const user of v.users) { for (const value of Object.values(user)) { if (typeof value === 'string' && value.match(reg)) { - finds.add(elem); + finds.add(v._mujs.root); } else if (typeof value === 'number' && `${value}`.match(reg)) { - finds.add(elem); + finds.add(v._mujs.root); } } } @@ -3889,96 +3896,52 @@ function primaryFN() { } else if (val.match(/^description:/)) { ezQuery(/^description:/, 'description'); } else if (val.match(/^(search_engine|engine):/)) { - const q_value = val.replace(/^(search_engine|engine):/, ''); - const reg = new RegExp(q_value, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v._mujs.info.engine) { - for (const value of Object.values(v._mujs.info.engine)) { - if (typeof value === 'string' && value.match(reg)) { - finds.add(elem); - } + const parts = /^[\w_]+:(\w+)/.exec(val); + if (parts) { + const reg = new RegExp(parts[1], 'gi'); + for (const { _mujs } of cacheValues) { + if (!_mujs.info.engine.name.match(reg)) { + continue; } + finds.add(_mujs.root); } } } else if (val.match(/^filter:/)) { const parts = /^\w+:(.+)/.exec(val); if (parts) { const bsFilter = loadFilters(); - const p = parts[1].trim().toLocaleLowerCase(); - for (const [key, value] of Object.entries(cfg.filters)) { - const k = key.trim().toLocaleLowerCase(); - const v = value.name.trim().toLocaleLowerCase(); - if (p.includes(k) || p.includes(v)) { - const reg = bsFilter.get(value.name); - if (reg) { - [...userjsCache.values()].filter(({ name, users, _mujs }) => { - const elem = _mujs.root; - if (!isElem(elem)) { - return false; - } - if (finds.has(elem)) { - return false; - } - const strArr = [{ name }, ...users]; - const v = strArr.find((o) => o.name.match(reg)); - if (v) { - return false; - } - finds.add(elem); - return true; - }); + const filterType = bsFilter.get(parts[1].trim().toLocaleLowerCase()); + if (filterType) { + const { reg } = filterType; + for (const { name, users, _mujs } of cacheValues) { + if ([{ name }, ...users].find((o) => o.name.match(reg))) { + continue; } + finds.add(_mujs.root); } } } } else if (val.match(/^recommend:/)) { - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v.users.find(u => u.id === authorID)) { - finds.add(elem); - } else if (goodUserJS.includes(v.url)) { - finds.add(elem); - } else if (goodUserJS.includes(v.id)) { - finds.add(elem); + for (const { url, id, users, _mujs } of cacheValues) { + if ( + users.find((u) => u.id === authorID) || + goodUserJS.includes(url) || + goodUserJS.includes(id) + ) { + finds.add(_mujs.root); } } } else { const reg = new RegExp(val, 'gi'); - for (const v of userjsCache.values()) { - const elem = v._mujs.root; - if (!isElem(elem)) { - continue; - } - if (finds.has(elem)) { - continue; - } - if (v.name && v.name.match(reg)) { - finds.add(elem); - } - if (v.description && v.description.match(reg)) { - finds.add(elem); - } + for (const v of cacheValues) { + if (v.name && v.name.match(reg)) finds.add(v._mujs.root); + if (v.description && v.description.match(reg)) finds.add(v._mujs.root); const code_data = v._mujs.code.data; if (code_data) { const code_obj = new ParseUserJS(code_data); const meta = code_obj.parse_meta(code_data); for (const key of Object.keys(meta)) { - if (/name|desc/i.test(key) && key.match(reg)) { - finds.add(elem); - } + if (/name|desc/i.test(key) && key.match(reg)) finds.add(v._mujs.root); } } } @@ -3989,16 +3952,19 @@ function primaryFN() { ael(urlBar, 'change', (evt) => { evt.preventDefault(); const val = evt.target.value; - if (urlBar.placeholder === i18n$('newTab') && qs('mujs-tab.active', toolbar)) { - const tabElem = qs('mujs-tab.active', toolbar); - const tabHost = qs('mujs-host', tabElem); - if (val.startsWith(tab.protocal)) { + const tabElem = tab.getActive(); + if (urlBar.placeholder === i18n$('newTab') && tabElem) { + const tabHost = tabElem.firstElementChild; + if (tab.protoReg.test(val)) { + const createdTab = tab.getTab(val); tab.close(tabElem); - if (tab.hasTab(val)) { - tab.active(tab.Tab.get(val)); + if (createdTab) { + tab.active(createdTab); } else { tab.create(val); } + evt.target.placeholder = i18n$('search_placeholder'); + evt.target.value = ''; return; } else if (val === '*') { tabElem.dataset.host = val; @@ -4018,7 +3984,6 @@ function primaryFN() { tabHost.textContent = value; MUList.host = value; respHandles.build(); - return; } }); scheduler.postTask(makecfg, { priority: 'background' }); @@ -4044,20 +4009,19 @@ function primaryFN() { * @param { (this: F, doc: Document) => * } onDomReady */ const loadDOM = (onDomReady) => { - if (!isFN(onDomReady)) { - return; - } - if (document.readyState === 'interactive' || document.readyState === 'complete') { - onDomReady(document); - return; + if (isFN(onDomReady)) { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + onDomReady(document); + } else { + document.addEventListener('DOMContentLoaded', (evt) => onDomReady(evt.target), { + once: true + }); + } } - document.addEventListener('DOMContentLoaded', (evt) => onDomReady(evt.target), { - once: true - }); }; -const init = async () => { - const stored = await StorageSystem.getValue('Config', DEFAULT_CONFIG); +const init = async (prefix = 'Config') => { + const stored = await StorageSystem.getValue(prefix, DEFAULT_CONFIG); cfg = { ...DEFAULT_CONFIG, ...stored @@ -4075,8 +4039,7 @@ const init = async () => { cause: 'loadDOM' }); } - trustedTypes.init(); - sleazyRedirect(); + container.redirect(); if (cfg.autoinject) container.inject(primaryFN, doc); diff --git a/src/sass/_main.scss b/src/sass/_main.scss index 7834a03..b4d429d 100644 --- a/src/sass/_main.scss +++ b/src/sass/_main.scss @@ -889,6 +889,7 @@ mujs-body { &[data-blacklist] { display: grid; grid-auto-flow: column; + &:not(.new-list) { grid-template-columns: repeat(2, 1fr); } diff --git a/src/typings/UserJS.d.ts b/src/typings/UserJS.d.ts index 1584f08..db953c1 100644 --- a/src/typings/UserJS.d.ts +++ b/src/typings/UserJS.d.ts @@ -19,6 +19,75 @@ export interface safeHandles { scheduler: typeof scheduler; } +export interface Translations { + createdby: string; + name: string; + daily_installs: string; + close: string; + filterA: string; + max: string; + min: string; + search: string; + search_placeholder: string; + install: string; + issue: string; + version_number: string; + updated: string; + total_installs: string; + ratings: string; + good: string; + ok: string; + bad: string; + created_date: string; + redirect: string; + filter: string; + dtime: string; + save: string; + reset: string; + preview_code: string; + saveFile: string; + newTab: string; + applies_to: string; + license: string; + no_license: string; + antifeatures: string; + userjs_fullscreen: string; + listing_none: string; + export_config: string; + export_theme: string; + import_config: string; + import_theme: string; + code_size: string; + prmpt_css: string; + userjs_inject: string; + userjs_close: string; + userjs_sync: string; + userjs_autoinject: string; + auto_fetch: string; +} + +export interface LanguageTranslations { + ar: Translations; + de: Translations; + en: Translations; + en_GB: Translations; + es: Translations; + fr: Translations; + ja: Translations; + nl: Translations; + pl: Translations; + ru: Translations; + zh: Translations; + zh_CN: Translations; + zh_TW: Translations; +} + +// export declare const translations: LanguageTranslations; + +export declare function i18n$( + key: string +): Translations[K] | 'Unknown'; + /** * Some sites will alter or remove document functions * To get around this we bind them to the `userjs` object @@ -56,6 +125,7 @@ export declare function getGMInfo(): typeof GM_info; export interface StorageSystem { prefix: string; + events: Set; /** * Alias of `window.localStorage.getItem` */ @@ -73,6 +143,10 @@ export interface StorageSystem { */ remove(key: K): void; + addListener(name: string, callback: VMScriptGMValueChangeCallback): number | void; + + attach(): void; + /** * Set value - Saves key to either GM managed storage or `window.localStorage` * @@ -134,18 +208,17 @@ export interface Container { shadowRoot?: ShadowRoot | HTMLElement; supported: boolean; frame: HTMLElement | HTMLIFrameElement; - cache: Map; + cache: Map< + string, + { + [engine: string]: GSForkQuery[]; + } + >; userjsCache: Map; root: HTMLElement; unsaved: boolean; isBlacklisted: boolean; rebuild: boolean; - counters: { - total: number; - [engine: string]: number; - }; opacityMin: string; opacityMax: string; Timeout: new () => Timeout; diff --git a/src/typings/types.d.ts b/src/typings/types.d.ts index 893ca62..3dda759 100644 --- a/src/typings/types.d.ts +++ b/src/typings/types.d.ts @@ -99,11 +99,38 @@ export type UserJSEngine = { query?: string; }; +export interface FilterLayout { + enabled: boolean; + name: string; + flag?: string; + regExp: string; +} + +export interface Filters extends FilterLayout { + reg: RegExp; + keyReg: RegExp; + valueReg: RegExp; +} + export type config = { + /** + * List sorting on load + */ + autoSort: string; + /** + * Fetch from engines on load + */ autofetch: boolean; + /** + * Inject list on load + */ autoinject: boolean; /** - * Sync config with UserScript manager + * Clear cache on tab close + */ + clearTabCache: boolean; + /** + * `UserScript:` Sync config with UserScript manager */ cache?: boolean; /** @@ -111,7 +138,7 @@ export type config = { */ codePreview: boolean; /** - * Fullscreen list on load + * `UserScript:` Fullscreen list on load */ autoexpand?: boolean; /** @@ -123,7 +150,7 @@ export type config = { */ sleazyredirect: boolean; /** - * Miliseconds before list closes + * `UserScript:` Miliseconds before list closes */ time?: number; /** @@ -177,40 +204,20 @@ export type config = { author: boolean; others: boolean; }; + /** + * Taken from https://greasyfork.org/scripts/12179 + */ filters: { - [name: string ]: { - enabled: boolean; - name: string; - flag?: string; - regExp: string; - }; - // 'Non-ASCII': { - // enabled: boolean; - // regExp: string; - // }; - // 'Non-Latin': { - // enabled: boolean; - // regExp: string; - // }; - // Games: { - // enabled: boolean; - // regExp: string; - // }; - // 'Social Networks': { - // enabled: boolean; - // regExp: string; - // }; - // Clutter: { - // enabled: boolean; - // regExp: string; - // }; + ASCII: FilterLayout; + Latin: FilterLayout; + Games: FilterLayout; + SocialNetworks: FilterLayout; + Clutter: FilterLayout; }; }; export declare function objToStr(obj: O): string; -export declare function strToURL(str: S): URL; - /** * Object is typeof `RegExp` */ @@ -251,9 +258,14 @@ export declare function isEmpty(obj: O): boolean; */ export declare function normalizeTarget( target: T, - toQuery: boolean, - root: Element | Document + toQuery?: boolean, + root?: Document | Element ): T[]; +// export declare function normalizeTarget( +// target: T, +// toQuery?: boolean, +// root?: Document | Element +// ): T[]; export declare function halt(evt: Event): void; @@ -311,7 +323,7 @@ declare global { export declare function ael( el: E, type: K, - listener: (this: E, ev: HTMLElementEventMap[K]) => any, + listener: EventListenerOrEventListenerObject, options?: AddEventListenerOptions | boolean ): void; @@ -350,9 +362,11 @@ export declare function make< A extends keyof HTMLElementTagNameMap[K] >( tagName: K, - cname?: string, + cname?: string | { + [key in A]: Record; + }, attrs?: { - [key in A]: unknown; + [key in A]: Record; } ): HTMLElementTagNameMap[K]; @@ -374,8 +388,8 @@ export interface dom { ): V | undefined; text(target: T, text?: V): string | null | undefined; cl: { - add(target: T, token: string | string[]): void; - remove(target: T, token: string | string[]): void; + add(target: T, token: string | string[]): boolean; + remove(target: T, token: string | string[]): boolean; toggle(target: T, token: string | string[], force?: boolean): boolean; has(target: T, token: string | string[]): boolean; }; From aedeb67257ca324676d51e8e7cda4c510852a1c8 Mon Sep 17 00:00:00 2001 From: Magic Date: Sun, 2 Mar 2025 12:16:55 -0800 Subject: [PATCH 12/35] Updated build environment Signed-off-by: Magic --- .env.example | 3 + README.md | 83 ++++--- dist/.env.example | 2 - eslint.config.js | 2 +- package.json | 96 +------- pnpm-lock.yaml | 145 ++++++++++- pnpm-workspace.yaml | 2 + tools/languageLoader.js | 54 ----- tools/userscript.js | 400 +------------------------------ utils/builder/README.md | 1 + utils/builder/package.json | 30 +++ utils/builder/src/index.d.ts | 56 +++++ utils/builder/src/index.js | 398 ++++++++++++++++++++++++++++++ utils/builder/typings/index.d.ts | 50 ++++ utils/i18n/README.md | 1 + utils/i18n/package.json | 24 ++ utils/i18n/src/index.js | 59 +++++ utils/i18n/typings/index.d.ts | 9 + utils/user.js/README.md | 1 + utils/user.js/package.json | 29 +++ utils/user.js/src/index.js | 6 + utils/user.js/typings/index.d.ts | 6 + 22 files changed, 870 insertions(+), 587 deletions(-) create mode 100644 .env.example delete mode 100644 dist/.env.example create mode 100644 pnpm-workspace.yaml delete mode 100644 tools/languageLoader.js create mode 100644 utils/builder/README.md create mode 100644 utils/builder/package.json create mode 100644 utils/builder/src/index.d.ts create mode 100644 utils/builder/src/index.js create mode 100644 utils/builder/typings/index.d.ts create mode 100644 utils/i18n/README.md create mode 100644 utils/i18n/package.json create mode 100644 utils/i18n/src/index.js create mode 100644 utils/i18n/typings/index.d.ts create mode 100644 utils/user.js/README.md create mode 100644 utils/user.js/package.json create mode 100644 utils/user.js/src/index.js create mode 100644 utils/user.js/typings/index.d.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5da5008 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +JS_ENV="development" +JS_ROOT="./" +JS_i18n="../../../src/_locales" \ No newline at end of file diff --git a/README.md b/README.md index bf9d7a0..5ef775e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Magic Userscript+ *A complete rewrite of [Userscript+ : Show Site All UserJS](https://github.com/jae-jae/Userscript-Plus)* -Finds available UserScripts for the current webpage, the power of [Greasy Fork](https://greasyfork.org) on the go! +Finds available UserScripts and UserStyles for the current webpage, the power of [Greasy Fork](https://greasyfork.org) on the go! [UserScript Changelog](https://github.com/magicoflolis/Userscript-Plus/blob/master/CHANGELOG.user.md) @@ -33,7 +33,7 @@ Finds available UserScripts for the current webpage, the power of [Greasy Fork]( * [Open UserJS](https://openuserjs.org/scripts/Magic/Magic_Userscript+_Show_Site_All_UserJS) - outdated * [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/blob/master/dist/magic-userjs.user.js?raw=1) -**Web Extension:** +**Web Extension (under construction):** *Firefox:* @@ -49,7 +49,7 @@ Works for desktop and mobile versions. Magic Userscript+ should be compatible with any Chromium-based browser -**(Not Recommended) Bookmarklet:** +**Bookmarklet (not recommended):** Save this URL as a bookmark, clicking it will cause the **UserScript version** to inject itself into the current webpage. @@ -59,37 +59,47 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu ## Features -* Designed for mobile and desktop devices -* Support multiple languages - date formats will match your current language -* Query UserScripts from: - * [Greasy Fork](https://greasyfork.org) - * [Sleazy Fork](https://sleazyfork.org) - * [Open UserJS](https://openuserjs.org) ( limited availability, will read `Too many requests...` if limit is reached ) - * [GitHub](https://github.com/search?l=JavaScript&o=desc&q="==UserScript==") ( requires [Personal Access Token](https://github.com/settings/tokens), no permissions are required ) -* Customize the theme -* Import / export config and theme -* Search for UserScripts -* Filter UserScripts which do not match your current language -* Sort UserScripts, default sorting "Daily Installs" -* Preview UserScript code before install -* Built-in UserScript [Greasyfork Search with Sleazyfork Results include](https://greasyfork.org/scripts/23840) -* Save UserScript as a local file -* Highlight UserScripts created by the [author](https://greasyfork.org/users/166061) -* Highlight recommended UserScripts from the [author](https://greasyfork.org/users/166061) +* General: + * UI designed for mobile and desktop devices + * Multiple language support - date formats are based on your current language + * Import / export config and theme + * Customize theme UI +* Query UserScripts and UserStyles from: + * [Greasy Fork](https://greasyfork.org) - enabled by default + * [Sleazy Fork](https://sleazyfork.org) - disabled by default + * [Open UserJS](https://openuserjs.org) ( limited availability, will read `Too many requests...` if limit is reached ) - disabled by default + * [GitHub](https://github.com/search?l=JavaScript&o=desc&q="==UserScript==") ( requires [Personal Access Token](https://github.com/settings/tokens), no permissions are required ) - disabled by default +* Built-in UserScripts: + * [GreasyFork Bullshit Filter](https://greasyfork.org/scripts/12179) - disabled by default + * [Greasyfork Search with Sleazyfork Results include](https://greasyfork.org/scripts/23840) - disabled by default +* Automation: + * Fetch on load - query on page load +* Blacklist: + * Attempts to exclude certain hosts from being queried - localhost, bank, government, etc. +* Menu: + * Search for UserScripts - for shortcuts see [Wiki](https://github.com/magicoflolis/Userscript-Plus/blob/master/wiki/README.md) + * Filter UserScripts which do not match your current language + * Sort UserScripts, default sorting "Daily Installs" + * Preview UserScripts code before install + * Save UserScript as a local file + * UserScript highlights: + * UserScripts created by the [author](https://greasyfork.org/users/166061) - enabled by default + * UserScript recommendations - enabled by default **UserScript Features:** > Tested and compatible with [TamperMonkey](https://www.tampermonkey.net/) or [ViolentMonkey](https://violentmonkey.github.io/) -* Maximize, minimize, or exit the UserScript list -* Change the position of floating counter -* Sync config with UserScript manager or per host - -**Bookmarklet Features:** - -* Maximize, minimize, or exit the UserScript list -* Change the position of floating counter -* Separate config for every host +* General: + * Maximize, minimize, or close menu + * Sync config with UserScript manager or per host + * Customize timeout window - can be re-injected using your managers User Script Commands menu +* Automation: + * Inject on load - injects menu on page load + * Automatic fullscreen - maximizes menu when opened +* UserScript Commands via `GM_registerMenuCommand`: + * Inject Userscript+ - injects menu into the page + * Close Userscript+ - removes menu from the page ## Previews @@ -138,7 +148,7 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu ## Build -Install [Node.js](https://nodejs.org/) and [pnpm](https://pnpm.io/). *The version of Node.js should match or be greater than the `"node"` key in `package.json`.* +Install [Node.js](https://nodejs.org/) and [pnpm](https://pnpm.io/) - *the version of Node.js should match or be greater than the `"node"` key in `package.json`.* ``` sh # Install dependencies @@ -147,9 +157,15 @@ $ pnpm i ### UserScript Version -**Desktop** - Developed in [ViolentMonkey](https://violentmonkey.github.io/), see [How to edit scripts with your favorite editor?](https://violentmonkey.github.io/posts/how-to-edit-scripts-with-your-favorite-editor/) +Before you begin, rename `.env.example` to `.env` + +**Recommened Testing Environments:** -**Mobile** - Developed in [FireFox Developer Edition](https://www.mozilla.org/firefox/developer/) "Responsive Design Mode" on desktop + [cromite](https://github.com/uazo/cromite) app on Android +* **Desktop:** any browser with [ViolentMonkey](https://violentmonkey.github.io/), see [How to edit scripts with your favorite editor?](https://violentmonkey.github.io/posts/how-to-edit-scripts-with-your-favorite-editor/) +* **Mobile:** + * Desktop: use "Responsive Design Mode(Ctrl+Shift+M)" on [FireFox Developer Edition](https://www.mozilla.org/firefox/developer/) or just [FireFox](https://www.mozilla.org/firefox/) + * Android: any browser that supports User Script or support for installing a User Script manager, I use [Cromite](https://github.com/uazo/cromite) + * IOS: any browser that supports User Script or support for installing a User Script manager ``` sh # Watch and compile to local HTTP server @@ -180,8 +196,7 @@ $ pnpm run webpack:FF ### Roadmap * Finish WebExtension -* Add sorting to the following: "Total installs", "Ratings", "Created date" -* Improve design of blacklist section. +* See TODO section in [UserScript Changelog](https://github.com/magicoflolis/Userscript-Plus/blob/master/CHANGELOG.user.md) ### Source Code diff --git a/dist/.env.example b/dist/.env.example deleted file mode 100644 index ca948fe..0000000 --- a/dist/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -# Please do not change this .env variable -JS_ENV="production" diff --git a/eslint.config.js b/eslint.config.js index 68f464d..273b21a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -79,7 +79,7 @@ export default [ } }, { - files: ['tools/*.js'], + files: ['tools/*.js', 'utils/**/*.js'], languageOptions: { ecmaVersion: 'latest', sourceType: 'module', diff --git a/package.json b/package.json index 2773e46..bb6b904 100644 --- a/package.json +++ b/package.json @@ -8,101 +8,13 @@ "bugs": { "url": "https://github.com/magicoflolis/Userscript-Plus/issues" }, - "userJS": { - "version": "7.4.0", - "name": "Magic Userscript+ : Show Site All UserJS", - "description": "Finds available userscripts for the current webpage.", - "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", - "homepage": "https://github.com/magicoflolis/Userscript-Plus", - "icon": "./src/img/icon_64.png", - "downloadURL": "https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.user.js", - "updateURL": "https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.meta.js", - "build": { - "source": { - "head": "./src/UserJS/header.js", - "body": "./src/UserJS/main.js", - "extras": { - "mainCSS": "./build/css/magicuserjs.css" - } - }, - "watch": { - "files": [ - "main.js", - "header.js", - "magicuserjs.css" - ], - "dirs": [ - "src/UserJS", - "build/css" - ] - }, - "paths": { - "dev": { - "fileName": "magic-userjs.dev", - "env": "./src/UserJS/.env", - "dir": "./web-server" - }, - "public": { - "fileName": "magic-userjs", - "env": "./dist/.env", - "dir": "./dist" - } - } - }, - "metadata": { - "compatible": [ - "chrome", - "firefox", - "edge", - "opera", - "safari" - ], - "connect": [ - "greasyfork.org", - "sleazyfork.org", - "github.com", - "githubusercontent.com", - "openuserjs.org" - ], - "grant": [ - "GM_addValueChangeListener", - "GM_addElement", - "GM_info", - "GM_getValue", - "GM_openInTab", - "GM_setValue", - "GM_registerMenuCommand", - "GM_removeValueChangeListener", - "GM_xmlhttpRequest", - "GM.addValueChangeListener", - "GM.addElement", - "GM.info", - "GM.getValue", - "GM.openInTab", - "GM.setValue", - "GM.registerMenuCommand", - "GM.removeValueChangeListener", - "GM.xmlHttpRequest" - ], - "exclude": [], - "include": [], - "exclude-match": [], - "match": [ - "https://*/*" - ], - "noframes": true, - "resource": {}, - "require": [], - "run-at": "document-start" - } - }, "type": "module", "scripts": { - "dev:UserJS": "concurrently \"node ./tools/userscript.js\" \"pnpm run dev:Webserver\" \"sass --no-source-map -s expanded -w ./src/sass:./build/css\" ", + "dev:UserJS": "concurrently \"dotenvx run -f .env --quiet -- node ./tools/userscript.js\" \"pnpm run dev:Webserver\" \"sass --no-source-map -s expanded -w ./src/sass:./build/css\"", "dev:FF": "concurrently \"sass --embed-sources -s expanded -w ./src/sass:./build/firefox/css\" \"pnpm run webpack:FF\"", "dev:Cr": "concurrently \"sass --embed-sources -s expanded -w ./src/sass:./build/chrome/css\" \"pnpm run webpack:Cr\"", "dev:Webserver": "http-server ./web-server -p 9090 -s --no-dotfiles -c-1", - "pub:UserJS": "concurrently \"sass --no-source-map -s expanded ./src/sass:./build/css\" \"node -r dotenv/config ./tools/userscript.js dotenv_config_path=./dist/.env\"", + "pub:UserJS": "concurrently \"sass --no-source-map -s expanded ./src/sass:./build/css\" \"dotenvx run --env JS_ENV=production -f .env --quiet -- node ./tools/userscript.js\"", "pub:FF": "webpack --mode production --config=tools/webpack.config.js --env brws=firefox", "pub:Cr": "webpack --mode production --config=tools/webpack.config.js --env brws=chrome", "webpack:Cr": "webpack --progress --mode development --config=tools/webpack.config.js --env brws=chrome", @@ -110,6 +22,7 @@ "web-run:firefox-android": "web-ext run --config=./tools/web-ext.js -t firefox-android --firefox-apk org.mozilla.firefox" }, "devDependencies": { + "@dotenvx/dotenvx": "^1.38.3", "@eslint/js": "^9.20.0", "@swc/cli": "^0.6.0", "@swc/core": "^1.10.16", @@ -127,7 +40,6 @@ "copy-webpack-plugin": "^12.0.2", "crx3": "^1.1.3", "css-loader": "^7.1.2", - "dotenv": "^16.4.7", "eslint": "^9.20.1", "eslint-config-prettier": "^10.0.1", "globals": "^15.15.0", @@ -140,7 +52,7 @@ "swc-loader": "^0.2.6", "terser-webpack-plugin": "^5.3.11", "typescript": "^5.7.3", - "watchpack": "^2.4.2", + "user.js": "workspace:^", "web-ext": "^8.4.0", "webpack": "^5.98.0", "webpack-cli": "^6.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 546bb2b..d834f60 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: devDependencies: + '@dotenvx/dotenvx': + specifier: ^1.38.3 + version: 1.38.3 '@eslint/js': specifier: ^9.20.0 version: 9.20.0 @@ -59,9 +62,6 @@ importers: css-loader: specifier: ^7.1.2 version: 7.1.2(webpack@5.98.0) - dotenv: - specifier: ^16.4.7 - version: 16.4.7 eslint: specifier: ^9.20.1 version: 9.20.1 @@ -98,9 +98,9 @@ importers: typescript: specifier: ^5.7.3 version: 5.7.3 - watchpack: - specifier: ^2.4.2 - version: 2.4.2 + user.js: + specifier: workspace:^ + version: link:utils/user.js web-ext: specifier: ^8.4.0 version: 8.4.0 @@ -114,6 +114,29 @@ importers: specifier: ^6.0.1 version: 6.0.1 + utils/builder: + dependencies: + '@userjs/i18n': + specifier: workspace:^ + version: link:../i18n + minimist: + specifier: ^1.2.8 + version: 1.2.8 + watchpack: + specifier: ^2.4.2 + version: 2.4.2 + + utils/i18n: {} + + utils/user.js: + dependencies: + '@userjs/builder': + specifier: workspace:^ + version: link:../builder + '@userjs/i18n': + specifier: workspace:^ + version: link:../i18n + packages: '@aashutoshrathi/word-wrap@1.2.6': @@ -156,6 +179,16 @@ packages: resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} engines: {node: '>=14.17.0'} + '@dotenvx/dotenvx@1.38.3': + resolution: {integrity: sha512-6tquYDfAiJbgQbYwWfL0jJHiUumY5EiFXVswk9sTwn5lWICMwOPmMOrM9TEVLzesfNMYwDyUiMp5WAA6yXs+SQ==} + hasBin: true + + '@ecies/ciphers@0.2.2': + resolution: {integrity: sha512-ylfGR7PyTd+Rm2PqQowG08BCKA22QuX8NzrL+LxAAvazN10DMwdJ2fWwAzRj05FI/M8vNFGm3cv9Wq/GFWCBLg==} + engines: {bun: '>=1', deno: '>=2', node: '>=16'} + peerDependencies: + '@noble/ciphers': ^1.0.0 + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -263,6 +296,18 @@ packages: '@mdn/browser-compat-data@5.6.31': resolution: {integrity: sha512-E/X4YlErVjBCMvaJbqD2Jb0B/Z+TQJyw4vN6q98iit05RLW9VEcsedaTiL81BAbYF9GICn/KpFGE9dMJi66Ydw==} + '@noble/ciphers@1.2.1': + resolution: {integrity: sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.8.1': + resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.7.1': + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -859,6 +904,10 @@ packages: resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==} engines: {node: '>=8.0.0'} + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -1054,6 +1103,10 @@ packages: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} + eciesjs@0.4.14: + resolution: {integrity: sha512-eJAgf9pdv214Hn98FlUzclRMYWF7WfoLlkS9nWMTm1qcCwn6Ad4EGD9lr9HXMBfSrZhYQujRE+p0adPRkctC6A==} + engines: {bun: '>=1', deno: '>=2', node: '>=16'} + electron-to-chromium@1.5.80: resolution: {integrity: sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==} @@ -1244,6 +1297,14 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1476,6 +1537,10 @@ packages: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + image-size@1.2.0: resolution: {integrity: sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==} engines: {node: '>=16.x'} @@ -1627,6 +1692,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} @@ -1872,6 +1941,10 @@ packages: object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + object-treeify@1.1.33: + resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} + engines: {node: '>= 10'} + on-exit-leak-free@2.1.0: resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==} @@ -1994,6 +2067,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pino-abstract-transport@1.2.0: resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} @@ -2784,6 +2861,11 @@ packages: engines: {node: '>= 8'} hasBin: true + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + widest-line@5.0.0: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} @@ -2903,6 +2985,22 @@ snapshots: '@discoveryjs/json-ext@0.6.3': {} + '@dotenvx/dotenvx@1.38.3': + dependencies: + commander: 11.1.0 + dotenv: 16.4.7 + eciesjs: 0.4.14 + execa: 5.1.1 + fdir: 6.4.3(picomatch@4.0.2) + ignore: 5.3.2 + object-treeify: 1.1.33 + picomatch: 4.0.2 + which: 4.0.0 + + '@ecies/ciphers@0.2.2(@noble/ciphers@1.2.1)': + dependencies: + '@noble/ciphers': 1.2.1 + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: eslint: 8.57.1 @@ -3021,6 +3119,14 @@ snapshots: '@mdn/browser-compat-data@5.6.31': {} + '@noble/ciphers@1.2.1': {} + + '@noble/curves@1.8.1': + dependencies: + '@noble/hashes': 1.7.1 + + '@noble/hashes@1.7.1': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3682,6 +3788,8 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + commander@11.1.0: {} + commander@12.1.0: {} commander@2.20.3: {} @@ -3866,6 +3974,13 @@ snapshots: dotenv@16.4.7: {} + eciesjs@0.4.14: + dependencies: + '@ecies/ciphers': 0.2.2(@noble/ciphers@1.2.1) + '@noble/ciphers': 1.2.1 + '@noble/curves': 1.8.1 + '@noble/hashes': 1.7.1 + electron-to-chromium@1.5.80: {} emoji-regex@10.4.0: {} @@ -4105,6 +4220,10 @@ snapshots: dependencies: pend: 1.2.0 + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.0.4 @@ -4352,6 +4471,8 @@ snapshots: ignore@5.2.4: {} + ignore@5.3.2: {} + image-size@1.2.0: dependencies: queue: 6.0.2 @@ -4458,6 +4579,8 @@ snapshots: isexe@2.0.0: {} + isexe@3.1.1: {} + isobject@3.0.1: {} jest-worker@27.5.1: @@ -4606,7 +4729,7 @@ snapshots: mkdirp@0.5.6: dependencies: - minimist: 1.2.7 + minimist: 1.2.8 mri@1.2.0: {} @@ -4672,6 +4795,8 @@ snapshots: object-inspect@1.12.3: {} + object-treeify@1.1.33: {} + on-exit-leak-free@2.1.0: {} once@1.4.0: @@ -4785,6 +4910,8 @@ snapshots: picomatch@2.3.1: {} + picomatch@4.0.2: {} + pino-abstract-transport@1.2.0: dependencies: readable-stream: 4.3.0 @@ -5557,6 +5684,10 @@ snapshots: dependencies: isexe: 2.0.0 + which@4.0.0: + dependencies: + isexe: 3.1.1 + widest-line@5.0.0: dependencies: string-width: 7.2.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..9a82b7a --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - 'utils/*' diff --git a/tools/languageLoader.js b/tools/languageLoader.js deleted file mode 100644 index 50e8861..0000000 --- a/tools/languageLoader.js +++ /dev/null @@ -1,54 +0,0 @@ -import { readdir, readFile, stat } from 'node:fs/promises'; -import { URL, fileURLToPath } from 'node:url'; - -/** - * Loads all the structures in the provided directory. - * - * @template T - * @param {import('node:fs').PathLike} dir - The directory to load the structures from - * @param {boolean} recursive - Whether to recursively load the structures in the directory - * @returns {Promise} - */ -export async function loadLanguages(dir, recursive = true) { - // Get the stats of the directory - const statDir = await stat(dir); - - // If the provided directory path is not a directory, throw an error - if (!statDir.isDirectory()) { - throw new Error(`The directory '${dir}' is not a directory.`); - } - - // Get all the files in the directory - const files = await readdir(dir); - - // Create an empty array to store the structures - /** @type {T[]} */ - const structures = []; - - // Loop through all the files in the directory - for (const file of files) { - // Get the stats of the file - const statFile = await stat(new URL(`${dir}/${file}`)); - - // If the file is a directory and recursive is true, recursively load the structures in the directory - if (statFile.isDirectory() && recursive) { - structures.push(...(await loadLanguages(new URL(`${dir}/${file}`), recursive))); - continue; - } - - if (!file.endsWith('.json')) { - continue; - } - - const filePath = fileURLToPath(`${dir}/${file}`); - const reg = /_locales\\(.*?)\\messages\.json/g.exec(filePath); - if (reg) { - const structure = await readFile(filePath, 'utf-8'); - structures.push({ - [reg[1]]: JSON.parse(structure.toString('utf-8')) - }); - } - } - - return structures; -} diff --git a/tools/userscript.js b/tools/userscript.js index 2bb3a73..c7c6d0d 100644 --- a/tools/userscript.js +++ b/tools/userscript.js @@ -1,398 +1,4 @@ -import path from 'path'; -import { URL } from 'node:url'; -import fs from 'node:fs'; -import dotenv from 'dotenv'; -import Watchpack from 'watchpack'; -import { loadLanguages } from './languageLoader.js'; +'use strict'; +import build from 'user.js'; -/** - * @typedef { import('../package.json') } CFG - */ - -const replaceTemplate = /\[\[(.*?)\]\]/g; -const metaStr = '[[metadata]]'; - -const log = (...msg) => { - console.log('[LOG]', ...msg); -}; -const err = (...msg) => { - console.error('[ERROR]', ...msg); -}; -/** - * Object is typeof `object` / JSON Object - * @template O - * @param { O } obj - * @returns { boolean } - */ -const isObj = (obj) => { - /** @type { string } */ - const s = Object.prototype.toString.call(obj); - return s.includes('Object'); -}; -/** - * Object is `null` or `undefined` - * @template O - * @param { O } obj - * @returns { boolean } - */ -const isNull = (obj) => { - return Object.is(obj, null) || Object.is(obj, undefined); -}; -/** - * Object is Blank - * @template O - * @param { O } obj - * @returns { boolean } - */ -const isBlank = (obj) => { - return ( - (typeof obj === 'string' && Object.is(obj.trim(), '')) || - ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || - (Array.isArray(obj) && Object.is(obj.length, 0)) || - (isObj(obj) && Object.is(Object.keys(obj).length, 0)) - ); -}; -/** - * Object is Empty - * @template O - * @param { O } obj - * @returns { boolean } - */ -const isEmpty = (obj) => { - return isNull(obj) || isBlank(obj); -}; -/** - * @template { string | { msg: string; } } T - * @template D - * @param { T } template - * @param { D } data - */ -const nano = (template, data) => { - if (typeof template === 'string') { - return template.replace(replaceTemplate, (_match, key) => { - const keys = key.split('.'); - let v = data[keys.shift()]; - for (const i in keys.length) v = v[keys[i]]; - return isEmpty(v) ? '' : v; - }); - } - return ''; -}; -/** - * @param {import('node:fs').PathLike} filePath - * @param {string} encoding - */ -const canAccess = async (filePath, encoding = 'utf-8') => { - const testAccess = await fs.promises.access( - filePath, - fs.promises.constants.R_OK | fs.promises.constants.W_OK - ); - if (isNull(testAccess)) { - const data = await fs.promises.readFile(filePath, encoding); - return data.toString(encoding); - } - return { - msg: `Cannot access provided filePath: ${filePath}` - }; -}; -/** - * @param {import('node:fs').PathLike} filePath - * @param {string} encoding - */ -const fileToJSON = async (filePath, encoding = 'utf-8') => { - const testAccess = await canAccess(filePath, encoding); - if (isObj(testAccess)) { - throw new Error(testAccess.msg); - } - return JSON.parse(testAccess); -}; -/** - * @param {import('node:fs').PathLike} destinationFilePath - * @param data - */ -const writeUserJS = async (destinationFilePath, data) => { - return await fs.promises.writeFile(destinationFilePath, data); -}; -const toTime = () => { - return new Intl.DateTimeFormat('default', { - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - fractionalSecondDigits: 3 - }).format(new Date()); -}; -/** - * @type { Map } - */ -const dataMap = new Map(); -const compareArrays = (a, b) => - a.length === b.length && a.every((element, index) => element === b[index]); -/** - * @template {string} K - * @template V - * @param {K} key - * @param {...V} values - */ -const addTo = (key, ...values) => { - if (values.length === 0) { - return ''; - } - if (dataMap.has(key)) { - if (compareArrays(dataMap.get(key), values)) { - return dataMap.get(key); - } - } - dataMap.set(key, values); - return dataMap.get(key); -}; -const filterData = [ - 'name', - 'description', - 'author', - 'icon', - 'version', - 'url', - 'homepage', - 'bugs', - 'license' -]; - -(async () => { - /** @type { dotenv.DotenvConfigOutput } */ - let result = {}; - try { - /** - * @type { CFG } - */ - const jsonData = await fileToJSON('./package.json'); - if (!isObj(jsonData)) { - throw new Error('"jsonData" must be an object.'); - } - if (!jsonData.userJS) { - throw new Error('Missing "userJS" key'); - } - const userJS = jsonData.userJS; - const { build } = userJS; - - result = dotenv.config({ - path: isEmpty(process.env.JS_ENV) ? build.paths.dev.env : build.paths.public.env - }); - if (result.error) { - throw result.error; - } - if (isNull(result.parsed.JS_ENV)) { - dotenv.populate( - result.parsed, - { - JS_ENV: 'development' - }, - { override: true, debug: true } - ); - } - const env = result.parsed; - const js_env = env.JS_ENV === 'development'; - const dp = js_env ? 'dev' : 'public'; - const compileMetadata = () => { - const metaData = []; - for (const [key, value] of Object.entries(userJS.metadata)) { - if (Array.isArray(value)) { - for (const v of value) { - metaData.push(`// @${key} ${v}`); - } - } else if (isObj(value)) { - for (const [k, v] of Object.entries(value)) { - metaData.push(`// @${key} ${k} ${v}`); - } - } else if (typeof value === 'boolean') { - if (value === true) { - metaData.push(`// @${key}`); - } - } else { - metaData.push(`// @${key} ${value}`); - } - } - return metaData.join('\n'); - }; - const buildUserJS = async () => { - try { - const lngList = await loadLanguages(new URL('../src/_locales', import.meta.url)); - const transformLanguages = () => { - const resp = {}; - for (const obj of lngList) { - for (const [k, v] of Object.entries(obj)) { - const o = {}; - for (const [key, value] of Object.entries(v)) { - if (key.startsWith('ext')) { - continue; - } - if (/userjs_(name|description)/i.test(key)) { - continue; - } - if (isEmpty(value.message)) { - continue; - } - o[key] = value.message; - } - resp[k] = o; - } - } - return JSON.stringify(resp, null, ' '); - }; - const compileLanguage = (type = 'userjs_name') => { - const resp = []; - for (const obj of lngList) { - for (const [k, v] of Object.entries(obj)) { - if (v[type]) { - if (isEmpty(v[type].message)) { - continue; - } - if (k.startsWith('en')) { - continue; - } - const t = type.toLowerCase().replace('userjs_', ''); - if (type === 'userjs_name') { - resp.push( - `// @${t}:${k.replace('_', '-')} ${js_env ? '[Dev] ' : ''}${v[type].message}` - ); - } else { - resp.push(`// @${t}:${k.replace('_', '-')} ${v[type].message}`); - } - } - } - } - return resp; - }; - const getData = () => { - for (const [k, v] of Object.entries(userJS)) { - if (typeof v !== 'string') { - continue; - } - if (k === 'name') { - addTo( - k, - `// @${k} ${js_env ? '[Dev] ' : ''}${v}`, - ...compileLanguage('userjs_name') - ); - } else if (k === 'description') { - addTo(k, `// @${k} ${v}`, ...compileLanguage('userjs_description')); - } else if (k === 'author') { - addTo(k, `// @${k} ${v}`); - } else if (k === 'icon') { - const buff = new Buffer.from(fs.readFileSync(v)); - const base64data = buff.toString('base64'); - if (v.endsWith('.png')) { - addTo(k, `// @${k} data:image/png;base64,${base64data}`); - } else if (v.endsWith('.svg')) { - addTo(k, `// @${k} data:image/svg+xml;base64,${base64data}`); - } - } else if (k === 'downloadURL') { - addTo(k, `// @downloadURL ${v}`); - } else if (k === 'updateURL') { - addTo(k, `// @updateURL ${v}`); - } else if (k === 'url') { - addTo(k, `// @downloadURL ${v}`, `// @updateURL ${v}`); - } else if (k === 'version') { - addTo(k, `// @${k} ${js_env ? +new Date() : v}`); - } else if (k === 'homepage') { - addTo(k, `// @namespace ${v}`, `// @homepageURL ${v}`); - } else if (k === 'bugs') { - addTo(k, `// @supportURL ${v}`); - } else if (k === 'license') { - addTo(k, `// @${k} ${v}`); - } else { - addTo(k, v); - } - } - for (const [k, v] of Object.entries(jsonData)) { - if (typeof v !== 'string') { - continue; - } - if (!filterData.includes(k)) { - continue; - } - if (dataMap.has(k)) { - continue; - } - if (k === 'license') { - addTo(k, `// @${k} ${v}`); - } else if (k === 'author') { - addTo(k, `// @${k} ${v}`); - } - } - if (userJS.metadata) { - addTo('metaData', compileMetadata()); - } - return [...dataMap.values()].flat().join('\n'); - }; - const userJSHeader = `// ==UserScript==\n${getData()}\n// ==/UserScript==`; - const headerFile = await canAccess(build.source.head); - const mainFile = await canAccess(build.source.body); - const nanoCFG = { - metadata: userJSHeader, - languageList: transformLanguages(), - code: mainFile - }; - if (build.source.extras) { - for (const [k, v] of Object.entries(build.source.extras)) { - const extraFile = await canAccess(v); - if (typeof extraFile === 'string') { - nanoCFG[k] = extraFile; - } - } - } - const outFile = `${build.paths[dp].dir}/${build.paths[dp].fileName}.user.js`; - await writeUserJS(outFile, nano(headerFile, nanoCFG)); - log('UserJS Build:', { - path: outFile, - time: toTime() - }); - if (!js_env) { - const outMeta = `${build.paths[dp].dir}/${build.paths[dp].fileName}.meta.js`; - await writeUserJS(outMeta, nano(metaStr, { metadata: userJSHeader })); - log('UserJS Metadata:', { - path: outMeta, - time: toTime() - }); - } - } catch (ex) { - err(ex); - } - }; - //#region Start Process - log(`Node ENV: ${env.JS_ENV}`); - - if (js_env) { - const wp = new Watchpack(); - let changed = new Set(); - wp.watch(build.watch.files, build.watch.dirs); - wp.on('change', (changedFile, mtime) => { - if (mtime === null) { - changed.delete(changedFile); - } else { - changed.add(changedFile); - } - }); - wp.on('aggregated', async () => { - // Filter out files that start with a dot from detected changes - // (as they are hidden files or temp files created by an editor). - const changes = Array.from(changed).filter((filePath) => { - return !path.basename(filePath).startsWith('.'); - }); - changed = new Set(); - - if (changes.length === 0) { - return; - } - - await buildUserJS(); - }); - return; - } - await buildUserJS(); - - process.exit(0); - //#endregion - } catch (ex) { - err(ex); - } -})(); +build(); diff --git a/utils/builder/README.md b/utils/builder/README.md new file mode 100644 index 0000000..b69b879 --- /dev/null +++ b/utils/builder/README.md @@ -0,0 +1 @@ +# UserScript Builder diff --git a/utils/builder/package.json b/utils/builder/package.json new file mode 100644 index 0000000..c42ffd6 --- /dev/null +++ b/utils/builder/package.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "@userjs/builder", + "description": "Create a UserScript", + "version": "1.0.0", + "license": "MIT", + "type": "module", + "main": "./src/index.js", + "types": "./typings/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./typings/index.d.ts", + "default": "./src/index.js" + } + } + }, + "directories": { + "lib": "src" + }, + "files": [ + "src", + "typings" + ], + "dependencies": { + "@userjs/i18n": "workspace:^", + "minimist": "^1.2.8", + "watchpack": "^2.4.2" + } +} diff --git a/utils/builder/src/index.d.ts b/utils/builder/src/index.d.ts new file mode 100644 index 0000000..1ca7e43 --- /dev/null +++ b/utils/builder/src/index.d.ts @@ -0,0 +1,56 @@ +import { PathLike } from 'node:fs'; + +/** + * Loads all the structures in the provided directory. + * + * @param dir - The directory to load the structures from + * @param recursive - Whether to recursively load the structures in the directory + */ +export declare function loadLanguages(dir: PathLike, recursive?: boolean): Promise; +export declare function build(): Promise; +export interface UserJS { + name: string; + description: string; + version: string; + license?: string; + bugs?: URL; + homepage?: URL; + icon?: PathLike; + downloadURL?: URL; + updateURL?: URL; + url_source?: URL; + url?: URL; + build: { + source: { + languageList: string; + [source: string]: PathLike; + }; + watch: { + files: string[]; + dirs: PathLike[]; + }; + paths: { + fileName: string; + dir: PathLike; + dev?: { + fileName?: string; + dir?: PathLike; + }; + }; + }; + metadata: { + compatible: string[]; + connect: string[]; + grant: string[]; + exclude: string[]; + include: string[]; + 'exclude-match': string[]; + match: string[]; + noframes: boolean; + resource: { + [name: string]: string; + }; + require: string[]; + 'run-at': 'document-start' | 'document-body' | 'document-end' | 'document-idle'; + }; +} diff --git a/utils/builder/src/index.js b/utils/builder/src/index.js new file mode 100644 index 0000000..4f8f350 --- /dev/null +++ b/utils/builder/src/index.js @@ -0,0 +1,398 @@ +'use strict'; +import path from 'path'; +import { URL } from 'node:url'; +import fs from 'node:fs'; +import Watchpack from 'watchpack'; +import minimist from 'minimist'; +import { loadLanguages } from '@userjs/i18n'; + +/** + * @typedef { import('../typings/index.d.ts').UserJS } CFG + */ + +const replaceTemplate = /\[\[(.*?)\]\]/g; +const metaStr = '[[metadata]]'; + +const log = (...msg) => { + console.log('[LOG]', ...msg); +}; +const err = (...msg) => { + console.error('[ERROR]', ...msg); +}; +/** + * Object is typeof `object` / JSON Object + * @template O + * @param { O } obj + * @returns { boolean } + */ +const isObj = (obj) => { + /** @type { string } */ + const s = Object.prototype.toString.call(obj); + return s.includes('Object'); +}; +/** + * Object is `null` or `undefined` + * @template O + * @param { O } obj + * @returns { boolean } + */ +const isNull = (obj) => { + return Object.is(obj, null) || Object.is(obj, undefined); +}; +/** + * Object is Blank + * @template O + * @param { O } obj + * @returns { boolean } + */ +const isBlank = (obj) => { + return ( + (typeof obj === 'string' && Object.is(obj.trim(), '')) || + ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || + (Array.isArray(obj) && Object.is(obj.length, 0)) || + (isObj(obj) && Object.is(Object.keys(obj).length, 0)) + ); +}; +/** + * Object is Empty + * @template O + * @param { O } obj + * @returns { boolean } + */ +const isEmpty = (obj) => { + return isNull(obj) || isBlank(obj); +}; +/** + * @template { string | { msg: string; } } T + * @template D + * @param { T } template + * @param { D } data + */ +const nano = (template, data) => { + if (typeof template === 'string') { + return template.replace(replaceTemplate, (_match, key) => { + const keys = key.split('.'); + let v = data[keys.shift()]; + for (const i in keys.length) v = v[keys[i]]; + return isEmpty(v) ? '' : v; + }); + } + return ''; +}; +/** + * @param {import('node:fs').PathLike} filePath + * @param {string} encoding + */ +const canAccess = async (filePath, encoding = 'utf-8') => { + const testAccess = await fs.promises.access( + filePath, + fs.promises.constants.R_OK | fs.promises.constants.W_OK + ); + if (isNull(testAccess)) { + const data = await fs.promises.readFile(filePath, encoding); + return data.toString(encoding); + } + return { + msg: `Cannot access provided filePath: ${filePath}` + }; +}; +/** + * @param {import('node:fs').PathLike} filePath + * @param {string} encoding + */ +const fileToJSON = async (filePath, encoding = 'utf-8') => { + const testAccess = await canAccess(filePath, encoding); + if (isObj(testAccess)) { + throw new Error(testAccess.msg); + } + return JSON.parse(testAccess); +}; +/** + * @param {import('node:fs').PathLike} destinationFilePath + * @param data + */ +const writeUserJS = async (destinationFilePath, data) => { + return await fs.promises.writeFile(destinationFilePath, data); +}; +const toTime = () => { + return new Intl.DateTimeFormat('default', { + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + fractionalSecondDigits: 3 + }).format(new Date()); +}; +/** + * @type { Map } + */ +const dataMap = new Map(); +const compareArrays = (a, b) => + a.length === b.length && a.every((element, index) => element === b[index]); +/** + * @template {string} K + * @template V + * @param {K} key + * @param {...V} values + */ +const addTo = (key, ...values) => { + if (values.length === 0) { + return ''; + } + if (dataMap.has(key)) { + if (compareArrays(dataMap.get(key), values)) { + return dataMap.get(key); + } + } + dataMap.set(key, values); + return dataMap.get(key); +}; + +async function build() { + try { + const getEnv = () => { + const argv = minimist(process.argv.slice(2)); + if (argv.JS_ROOT && argv.JS_ENV) { + return { + JS_ROOT: argv.JS_ROOT, + JS_ENV: argv.JS_ENV, + JS_i18n: `${argv.JS_ROOT}src/_locales` + }; + } + return process.env; + }; + const { JS_ROOT, JS_ENV, JS_i18n } = getEnv(); + const jsonRecords = await Promise.all([ + // fileToJSON('./package.json').then(({ userJS }) => { + // return userJS ?? {}; + // }), + fileToJSON('./UserJS.json') + .then((userJS) => { + return userJS ?? {}; + }) + .catch(() => { + return {}; + }) + ]); + if (isEmpty(jsonRecords)) + throw new Error('"UserJS.json" not found + no "userJS" key in package.json'); + /** + * @type { CFG } + */ + const userJS = {}; + for (const r of jsonRecords) Object.assign(userJS, r); + const isDev = isEmpty(JS_ENV) || JS_ENV === 'development'; + const buildUserJS = async () => { + try { + const i18nList = await loadLanguages(new URL(JS_i18n ?? `${JS_ROOT}src/_locales`, import.meta.url)); + const compileLanguage = (type = 'userjs_name') => { + const resp = []; + for (const obj of i18nList) { + for (const [k, v] of Object.entries(obj)) { + if (v[type]) { + if (isEmpty(v[type].message)) { + continue; + } + if (k.startsWith('en')) { + continue; + } + const t = type.toLowerCase().replace('userjs_', ''); + if (type === 'userjs_name') { + resp.push( + `// @${t}:${k.replace('_', '-')} ${isDev ? '[Dev] ' : ''}${v[type].message}` + ); + } else { + resp.push(`// @${t}:${k.replace('_', '-')} ${v[type].message}`); + } + } + } + } + return resp; + }; + const compileData = () => { + if (isDev && !isEmpty(dataMap)) { + addTo('version', `// @version ${+new Date()}`); + return `// ==UserScript==\n${[...dataMap.values()].flat().join('\n')}\n// ==/UserScript==`; + } + for (const [k, v] of Object.entries(userJS)) { + if (k === 'metadata') { + const metaData = []; + for (const [key, value] of Object.entries(v)) { + if (Array.isArray(value)) { + for (const v of value) { + metaData.push(`// @${key} ${v}`); + } + } else if (isObj(value)) { + for (const [k, v] of Object.entries(value)) { + metaData.push(`// @${key} ${k} ${v}`); + } + } else if (typeof value === 'boolean') { + if (value === true) { + metaData.push(`// @${key}`); + } + } else { + metaData.push(`// @${key} ${value}`); + } + } + addTo('metaData', metaData.join('\n')); + } + if (typeof v !== 'string') { + continue; + } + if (k === 'name') { + addTo( + k, + `// @${k} ${isDev ? '[Dev] ' : ''}${v}`, + ...compileLanguage('userjs_name') + ); + } else if (k === 'description') { + addTo(k, `// @${k} ${v}`, ...compileLanguage('userjs_description')); + } else if (k === 'author') { + addTo(k, `// @${k} ${v}`); + } else if (k === 'icon') { + if (v.startsWith('.') || v.startsWith('/')) { + const buff = new Buffer.from(fs.readFileSync(v)); + const base64data = buff.toString('base64'); + if (v.endsWith('.png')) { + addTo(k, `// @${k} data:image/png;base64,${base64data}`); + } else if (v.endsWith('.svg')) { + addTo(k, `// @${k} data:image/svg+xml;base64,${base64data}`); + } + } else { + addTo(k, `// @${k} ${v}`); + } + } else if (k === 'downloadURL') { + addTo(k, `// @downloadURL ${v}`); + } else if (k === 'updateURL') { + addTo(k, `// @updateURL ${v}`); + } else if (k === 'url_source') { + addTo(k, `// @url_source ${v}`); + } else if (k === 'url') { + addTo(k, `// @downloadURL ${v}`, `// @updateURL ${v}`); + } else if (k === 'version') { + addTo(k, `// @${k} ${isDev ? +new Date() : v}`); + } else if (k === 'homepage') { + addTo(k, `// @namespace ${v}`, `// @homepageURL ${v}`); + } else if (k === 'bugs') { + addTo(k, `// @supportURL ${v}`); + } else if (k === 'license') { + addTo(k, `// @${k} ${v}`); + } else { + addTo(k, v); + } + } + return `// ==UserScript==\n${[...dataMap.values()].flat().join('\n')}\n// ==/UserScript==`; + }; + const cfg = { + nano: { + languageList: {}, + metadata: compileData() + }, + path: { + fileName: 'main-userjs', + dir: './dist' + }, + file: '', + meta: '', + metaPath: '' + }; + for (const [k, v] of Object.entries(userJS.build.source)) { + const f = await canAccess(v); + if (typeof f !== 'string') continue; + if (k === 'metadata') { + cfg.meta = f; + } else { + cfg.nano[k] = f; + } + } + if (!isEmpty(i18nList)) { + for (const i18n of i18nList) { + for (const [k, v] of Object.entries(i18n)) { + const o = {}; + for (const [key, value] of Object.entries(v)) { + if (key.startsWith('ext')) { + continue; + } + if (/userjs_(name|description)/i.test(key)) { + continue; + } + if (isEmpty(value.message)) { + continue; + } + o[key] = value.message; + } + cfg.nano.languageList[k] = o; + } + } + } + for (const [k, v] of Object.entries(userJS.build.paths)) { + if (isEmpty(v)) continue; + if (isDev && /dev/i.test(k)) { + for (const [key, value] of Object.entries(v)) { + cfg.path[key] = value; + } + } else { + cfg.path[k] = v; + } + } + cfg.file = `${cfg.path.dir}/${cfg.path.fileName}.user.js`; + cfg.metaPath = `${cfg.path.dir}/${cfg.path.fileName}.meta.js`; + cfg.nano.languageList = JSON.stringify(cfg.nano.languageList, null, ' '); + + await writeUserJS(cfg.file, nano(cfg.meta, cfg.nano)); + log('UserJS Build:', { + path: cfg.file, + time: toTime() + }); + if (!isDev) { + await writeUserJS( + cfg.metaPath, + nano(metaStr, { + metadata: cfg.nano.metadata + }) + ); + log('UserJS Metadata:', { + path: cfg.metaPath, + time: toTime() + }); + } + } catch (ex) { + err(ex); + } + }; + log(`Node ENV: ${JS_ENV}`); + await buildUserJS(); + if (isDev) { + const wp = new Watchpack(); + let changed = new Set(); + wp.watch(userJS.build.watch.files, userJS.build.watch.dirs); + wp.on('change', (changedFile, mtime) => { + if (mtime === null) { + changed.delete(changedFile); + } else { + changed.add(changedFile); + } + }); + wp.on('aggregated', async () => { + // Filter out files that start with a dot from detected changes + // (as they are hidden files or temp files created by an editor). + const changes = Array.from(changed).filter((filePath) => { + return !path.basename(filePath).startsWith('.'); + }); + changed = new Set(); + + if (changes.length === 0) { + return; + } + + await buildUserJS(); + }); + } else { + process.exit(0); + } + } catch (ex) { + err(ex); + } +} + +export { build }; +export default build; diff --git a/utils/builder/typings/index.d.ts b/utils/builder/typings/index.d.ts new file mode 100644 index 0000000..6eacd4f --- /dev/null +++ b/utils/builder/typings/index.d.ts @@ -0,0 +1,50 @@ +import { PathLike } from 'node:fs'; + +export interface UserJS { + name: string; + description: string; + version: string; + license?: string; + bugs?: URL; + homepage?: URL; + icon?: PathLike; + downloadURL?: URL; + updateURL?: URL; + url_source?: URL; + url?: URL; + build: { + source: { + languageList: string; + [source: string]: PathLike; + }; + watch: { + files: string[]; + dirs: PathLike[]; + }; + paths: { + fileName: string; + dir: PathLike; + dev?: { + fileName?: string; + dir?: PathLike; + }; + }; + }; + metadata: { + compatible: string[]; + connect: string[]; + grant: string[]; + exclude: string[]; + include: string[]; + 'exclude-match': string[]; + match: string[]; + noframes: boolean; + resource: { + [name: string]: string; + }; + require: string[]; + 'run-at': 'document-start' | 'document-body' | 'document-end' | 'document-idle'; + }; +} + +export declare function build(): Promise; diff --git a/utils/i18n/README.md b/utils/i18n/README.md new file mode 100644 index 0000000..90c84e3 --- /dev/null +++ b/utils/i18n/README.md @@ -0,0 +1 @@ +# UserScript i18n diff --git a/utils/i18n/package.json b/utils/i18n/package.json new file mode 100644 index 0000000..3b931be --- /dev/null +++ b/utils/i18n/package.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "@userjs/i18n", + "description": "Loads languages", + "version": "1.0.0", + "license": "MIT", + "main": "./src/index.js", + "types": "./typings/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./typings/index.d.ts", + "default": "./src/index.js" + } + } + }, + "directories": { + "lib": "src" + }, + "files": [ + "src", + "typings" + ] +} diff --git a/utils/i18n/src/index.js b/utils/i18n/src/index.js new file mode 100644 index 0000000..0179325 --- /dev/null +++ b/utils/i18n/src/index.js @@ -0,0 +1,59 @@ +'use strict'; +import { readdir, readFile, stat } from 'node:fs/promises'; +import { URL, fileURLToPath } from 'node:url'; + +/** + * + * @type { import('../typings/index.d.ts').loadLanguages } + */ +async function loadLanguages(dir, recursive = true) { + try { + // Get the stats of the directory + const statDir = await stat(dir); + + // If the provided directory path is not a directory, throw an error + if (!statDir.isDirectory()) { + throw new Error(`The directory '${dir}' is not a directory.`); + } + + // Get all the files in the directory + const files = await readdir(dir); + + // Create an empty array to store the structures + /** @type {T[]} */ + const structures = []; + + // Loop through all the files in the directory + for (const file of files) { + // Get the stats of the file + const statFile = await stat(new URL(`${dir}/${file}`)); + + // If the file is a directory and recursive is true, recursively load the structures in the directory + if (statFile.isDirectory() && recursive) { + structures.push(...(await loadLanguages(new URL(`${dir}/${file}`), recursive))); + continue; + } + + if (!file.endsWith('.json')) { + continue; + } + + const filePath = fileURLToPath(`${dir}/${file}`); + const reg = /_locales\\(.*?)\\messages\.json/g.exec(filePath); + if (reg) { + const structure = await readFile(filePath, 'utf-8'); + structures.push({ + [reg[1]]: JSON.parse(structure.toString('utf-8')) + }); + } + } + + return structures; + // eslint-disable-next-line no-unused-vars + } catch (ex) { + return []; + } +} + +export { loadLanguages }; +export default loadLanguages; diff --git a/utils/i18n/typings/index.d.ts b/utils/i18n/typings/index.d.ts new file mode 100644 index 0000000..27f7743 --- /dev/null +++ b/utils/i18n/typings/index.d.ts @@ -0,0 +1,9 @@ +import { PathLike } from 'node:fs'; + +/** + * Loads all the structures in the provided directory. + * + * @param dir - The directory to load the structures from + * @param recursive - Whether to recursively load the structures in the directory + */ +export declare function loadLanguages(dir: PathLike, recursive?: boolean): Promise; diff --git a/utils/user.js/README.md b/utils/user.js/README.md new file mode 100644 index 0000000..b69b879 --- /dev/null +++ b/utils/user.js/README.md @@ -0,0 +1 @@ +# UserScript Builder diff --git a/utils/user.js/package.json b/utils/user.js/package.json new file mode 100644 index 0000000..47fb61a --- /dev/null +++ b/utils/user.js/package.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "user.js", + "description": "Create a UserScript", + "version": "1.0.0", + "license": "MIT", + "type": "module", + "main": "./src/index.js", + "types": "./typings/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./typings/index.d.ts", + "default": "./src/index.js" + } + } + }, + "directories": { + "lib": "src" + }, + "files": [ + "src", + "typings" + ], + "dependencies": { + "@userjs/builder": "workspace:^", + "@userjs/i18n": "workspace:^" + } +} diff --git a/utils/user.js/src/index.js b/utils/user.js/src/index.js new file mode 100644 index 0000000..f8f2a95 --- /dev/null +++ b/utils/user.js/src/index.js @@ -0,0 +1,6 @@ +'use strict'; +import { build } from '@userjs/builder'; +import { loadLanguages } from '@userjs/i18n'; + +export { build, loadLanguages }; +export default build; diff --git a/utils/user.js/typings/index.d.ts b/utils/user.js/typings/index.d.ts new file mode 100644 index 0000000..f8f2a95 --- /dev/null +++ b/utils/user.js/typings/index.d.ts @@ -0,0 +1,6 @@ +'use strict'; +import { build } from '@userjs/builder'; +import { loadLanguages } from '@userjs/i18n'; + +export { build, loadLanguages }; +export default build; From b04ff3e07ba49c8ffd698e3b50c838889b45ec84 Mon Sep 17 00:00:00 2001 From: Magic Date: Sun, 2 Mar 2025 12:18:28 -0800 Subject: [PATCH 13/35] v7.5.0 Signed-off-by: Magic --- CHANGELOG.user.md | 24 ++++++++++++++ UserJS.json | 69 +++++++++++++++++++++++++++++++++++++++ dist/magic-userjs.meta.js | 4 +-- dist/magic-userjs.user.js | 41 ++++++++++------------- src/UserJS/header.js | 9 ----- src/UserJS/main.js | 20 +++++------- 6 files changed, 120 insertions(+), 47 deletions(-) create mode 100644 UserJS.json diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 81b66f2..5786ca2 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,5 +1,25 @@ # Changelog +## v7.5.0 + +* Merged https://github.com/magicoflolis/Userscript-Plus/pull/64 +* Cleaned up old comments + +**Known Issues:** + +* Enabling a engine requires the page to be reloaded, while disabling a engine does not. + * This is caused by the cache system. +* "Filter out other languages" may not filter _every_ userscript that is not in your language. +* SVG elements don't load on every webpage, _can be blocked by the page, external script, or extensions._ + +**TODO:** + +* Finish translations. +* Finish blacklist section. +* Finish config section. + +--- + ## v7.4.0 * Merged https://github.com/magicoflolis/Userscript-Plus/pull/59 @@ -136,3 +156,7 @@ * Improve design of blacklist section --- + +## Previous Changes + +[https://github.com/magicoflolis/Userscript-Plus/releases](https://github.com/magicoflolis/Userscript-Plus/releases) diff --git a/UserJS.json b/UserJS.json new file mode 100644 index 0000000..31269ec --- /dev/null +++ b/UserJS.json @@ -0,0 +1,69 @@ +{ + "version": "7.5.0", + "name": "Magic Userscript+ : Show Site All UserJS", + "description": "Finds available userscripts for the current webpage.", + "author": "Magic ", + "bugs": "https://github.com/magicoflolis/Userscript-Plus/issues", + "homepage": "https://github.com/magicoflolis/Userscript-Plus", + "icon": "./src/img/icon_64.png", + "downloadURL": "https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.user.js", + "updateURL": "https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.meta.js", + "license": "MIT", + "build": { + "source": { + "metadata": "./src/UserJS/header.js", + "code": "./src/UserJS/main.js", + "mainCSS": "./build/css/magicuserjs.css" + }, + "watch": { + "files": ["main.js", "header.js", "magicuserjs.css"], + "dirs": ["src/UserJS", "build/css"] + }, + "paths": { + "fileName": "magic-userjs", + "dir": "./dist", + "dev": { + "fileName": "magic-userjs.dev", + "dir": "./web-server" + } + } + }, + "metadata": { + "compatible": ["chrome", "firefox", "edge", "opera", "safari"], + "connect": [ + "greasyfork.org", + "sleazyfork.org", + "github.com", + "githubusercontent.com", + "openuserjs.org" + ], + "grant": [ + "GM_addValueChangeListener", + "GM_addElement", + "GM_info", + "GM_getValue", + "GM_openInTab", + "GM_setValue", + "GM_registerMenuCommand", + "GM_removeValueChangeListener", + "GM_xmlhttpRequest", + "GM.addValueChangeListener", + "GM.addElement", + "GM.info", + "GM.getValue", + "GM.openInTab", + "GM.setValue", + "GM.registerMenuCommand", + "GM.removeValueChangeListener", + "GM.xmlHttpRequest" + ], + "exclude": [], + "include": [], + "exclude-match": [], + "match": ["https://*/*"], + "noframes": true, + "resource": {}, + "require": [], + "run-at": "document-start" + } +} diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index 6dd5d1d..a6aab9d 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.4.0 +// @version 7.5.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -24,13 +24,13 @@ // @description:zh 为当前网页查找可用的用户脚本。 // @description:zh-CN 为当前网页查找可用的用户脚本。 // @description:zh-TW 为当前网页查找可用的用户脚本。 +// @author Magic // @supportURL https://github.com/magicoflolis/Userscript-Plus/issues // @namespace https://github.com/magicoflolis/Userscript-Plus // @homepageURL https://github.com/magicoflolis/Userscript-Plus // @icon data:image/png;base64,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 // @downloadURL https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.user.js // @updateURL https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.meta.js -// @author Magic // @license MIT // @compatible chrome // @compatible firefox diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index a624bdd..6f288aa 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.4.0 +// @version 7.5.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -24,13 +24,13 @@ // @description:zh 为当前网页查找可用的用户脚本。 // @description:zh-CN 为当前网页查找可用的用户脚本。 // @description:zh-TW 为当前网页查找可用的用户脚本。 +// @author Magic // @supportURL https://github.com/magicoflolis/Userscript-Plus/issues // @namespace https://github.com/magicoflolis/Userscript-Plus // @homepageURL https://github.com/magicoflolis/Userscript-Plus // @icon data:image/png;base64,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 // @downloadURL https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.user.js // @updateURL https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.meta.js -// @author Magic // @license MIT // @compatible chrome // @compatible firefox @@ -104,11 +104,7 @@ const createPolicy = () => { }; createPolicy(); /** - * Uncompressed locales + compiler - * * [_locales](https://github.com/magicoflolis/Userscript-Plus/tree/master/src/_locales) - * - * [languageLoader.js](https://github.com/magicoflolis/Userscript-Plus/blob/master/tools/languageLoader.js) */ const translations = { "ar": { @@ -245,7 +241,7 @@ const translations = { "prmpt_css": "Install as UserStyle?", "userjs_inject": "Inject Userscript+", "userjs_close": "Close Userscript+", - "userjs_sync": "Sync with UserScript Manager", + "userjs_sync": "Sync", "userjs_autoinject": "Inject on load", "auto_fetch": "Fetch on load" }, @@ -710,11 +706,6 @@ const translations = { "auto_fetch": "Fetch on load" } }; -/** - * To compile this CSS `pnpm run build:Sass` - * - * [Uncompiled Cascading Style Sheet](https://github.com/magicoflolis/Userscript-Plus/tree/master/src/sass) - */ const main_css = `mujs-root { --mujs-even-row: hsl(222, 14%, 22%); --mujs-odd-row: hsl(222, 14%, 11%); @@ -1893,7 +1884,7 @@ const DEFAULT_CONFIG = { class i18nHandler { constructor() { if (userjs.pool !== undefined) { - return userjs.pool; + return this; } userjs.pool = new Map(); for (const [k, v] of Object.entries(translations)) { @@ -1922,7 +1913,7 @@ class i18nHandler { i18n$(key) { const { navigator } = safeSelf(); const current = navigator.language.split('-')[0] ?? 'en'; - return userjs.pool.get(current)?.[key] ?? 'Unknown'; + return userjs.pool.get(current)?.[key] ?? 'Invalid Key'; } } const language = new i18nHandler(); @@ -2114,7 +2105,7 @@ const getGMInfo = () => { icon: '', name: 'Magic Userscript+', namespace: 'https://github.com/magicoflolis/Userscript-Plus', - updateURL: 'https://github.com/magicoflolis/Userscript-Plus/releases', + updateURL: 'https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.js', version: 'Bookmarklet', bugs: 'https://github.com/magicoflolis/Userscript-Plus/issues' } @@ -2922,7 +2913,8 @@ class Container { this.tab.create(host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent; + const getCellValue = (tr, idx) => + tr.children[idx].dataset.value || tr.children[idx].innerText || tr.children[idx].textContent; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) @@ -3814,9 +3806,6 @@ function primaryFN() { data_names; constructor(code) { this.code = code; - this.get_all(); - } - get_all() { this.get_meta_block(); this.get_code_block(); this.parse_meta(); @@ -4154,16 +4143,17 @@ function primaryFN() { if (badUserJS.includes(ujs.id) || badUserJS.includes(ujs.url)) { return; } - if (!container.userjsCache.has(ujs.id)) { - container.userjsCache.set(ujs.id, ujs); - } + if (!container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); const eframe = make('td', 'install-btn'); const uframe = make('td', 'mujs-uframe'); const fdaily = make('td', 'mujs-list', { textContent: ujs.daily_installs }); const fupdated = make('td', 'mujs-list', { - textContent: language.toDate(ujs.code_updated_at) + textContent: language.toDate(ujs.code_updated_at), + dataset: { + value: new Date(ujs.code_updated_at).toISOString() + } }); const fname = make('td', 'mujs-name'); const fmore = make('mujs-column', 'mujs-list hidden', { @@ -4187,7 +4177,10 @@ function primaryFN() { textContent: `${i18n$('version_number')}: ${ujs.version}` }); const fcreated = make('mu-js', 'mujs-list', { - textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}` + textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`, + dataset: { + value: new Date(ujs.created_at).toISOString() + } }); const flicense = make('mu-js', 'mujs-list', { title: ujs.license ?? i18n$('no_license'), diff --git a/src/UserJS/header.js b/src/UserJS/header.js index 9b48860..fe229de 100644 --- a/src/UserJS/header.js +++ b/src/UserJS/header.js @@ -39,18 +39,9 @@ const createPolicy = () => { }; createPolicy(); /** - * Uncompressed locales + compiler - * * [_locales](https://github.com/magicoflolis/Userscript-Plus/tree/master/src/_locales) - * - * [languageLoader.js](https://github.com/magicoflolis/Userscript-Plus/blob/master/tools/languageLoader.js) */ const translations = [[languageList]]; -/** - * To compile this CSS `pnpm run build:Sass` - * - * [Uncompiled Cascading Style Sheet](https://github.com/magicoflolis/Userscript-Plus/tree/master/src/sass) - */ const main_css = `[[mainCSS]]`; /******************************************************************************/ [[code]] diff --git a/src/UserJS/main.js b/src/UserJS/main.js index cf28c30..87c6905 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -310,7 +310,7 @@ const DEFAULT_CONFIG = { class i18nHandler { constructor() { if (userjs.pool !== undefined) { - return userjs.pool; + return this; } userjs.pool = new Map(); for (const [k, v] of Object.entries(translations)) { @@ -339,7 +339,7 @@ class i18nHandler { i18n$(key) { const { navigator } = safeSelf(); const current = navigator.language.split('-')[0] ?? 'en'; - return userjs.pool.get(current)?.[key] ?? 'Unknown'; + return userjs.pool.get(current)?.[key] ?? 'Invalid Key'; } } const language = new i18nHandler(); @@ -531,7 +531,7 @@ const getGMInfo = () => { icon: '', name: 'Magic Userscript+', namespace: 'https://github.com/magicoflolis/Userscript-Plus', - updateURL: 'https://github.com/magicoflolis/Userscript-Plus/releases', + updateURL: 'https://github.com/magicoflolis/Userscript-Plus/raw/master/dist/magic-userjs.js', version: 'Bookmarklet', bugs: 'https://github.com/magicoflolis/Userscript-Plus/issues' } @@ -1339,7 +1339,8 @@ class Container { this.tab.create(host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => tr.children[idx].dataset.value || tr.children[idx].innerText || tr.children[idx].textContent; + const getCellValue = (tr, idx) => + tr.children[idx].dataset.value || tr.children[idx].innerText || tr.children[idx].textContent; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) @@ -2231,9 +2232,6 @@ function primaryFN() { data_names; constructor(code) { this.code = code; - this.get_all(); - } - get_all() { this.get_meta_block(); this.get_code_block(); this.parse_meta(); @@ -2571,9 +2569,7 @@ function primaryFN() { if (badUserJS.includes(ujs.id) || badUserJS.includes(ujs.url)) { return; } - if (!container.userjsCache.has(ujs.id)) { - container.userjsCache.set(ujs.id, ujs); - } + if (!container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); const eframe = make('td', 'install-btn'); const uframe = make('td', 'mujs-uframe'); const fdaily = make('td', 'mujs-list', { @@ -2582,7 +2578,7 @@ function primaryFN() { const fupdated = make('td', 'mujs-list', { textContent: language.toDate(ujs.code_updated_at), dataset: { - value: (new Date(ujs.code_updated_at)).toISOString() + value: new Date(ujs.code_updated_at).toISOString() } }); const fname = make('td', 'mujs-name'); @@ -2609,7 +2605,7 @@ function primaryFN() { const fcreated = make('mu-js', 'mujs-list', { textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`, dataset: { - value: (new Date(ujs.created_at)).toISOString() + value: new Date(ujs.created_at).toISOString() } }); const flicense = make('mu-js', 'mujs-list', { From 3132d5534de47c8bde83bfdd9f31410124933b42 Mon Sep 17 00:00:00 2001 From: Magic Date: Sun, 2 Mar 2025 12:21:56 -0800 Subject: [PATCH 14/35] Updated README.md Signed-off-by: Magic --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 5ef775e..cd6701d 100644 --- a/README.md +++ b/README.md @@ -40,15 +40,11 @@ Finds available UserScripts and UserStyles for the current webpage, the power of * [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/userscript-plus/) * [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest) -Works for desktop and mobile versions. - *Chromium:* * ~~[Chrome Web Store](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest)~~ * [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest) -Magic Userscript+ should be compatible with any Chromium-based browser - **Bookmarklet (not recommended):** Save this URL as a bookmark, clicking it will cause the **UserScript version** to inject itself into the current webpage. From fefd7aefbec16be7c0d5a16195f8dee6408550f5 Mon Sep 17 00:00:00 2001 From: Magic Date: Sun, 2 Mar 2025 13:33:51 -0800 Subject: [PATCH 15/35] Updated README.md Signed-off-by: Magic --- README.md | 49 ++---------------------- src/UserJS/.env.example | 2 - wiki/Build.md | 84 +++++++++++++++++++++++++++++++++++++++++ wiki/README.md | 9 ++++- 4 files changed, 95 insertions(+), 49 deletions(-) delete mode 100644 src/UserJS/.env.example create mode 100644 wiki/Build.md diff --git a/README.md b/README.md index cd6701d..79bb3ba 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * Blacklist: * Attempts to exclude certain hosts from being queried - localhost, bank, government, etc. * Menu: - * Search for UserScripts - for shortcuts see [Wiki](https://github.com/magicoflolis/Userscript-Plus/blob/master/wiki/README.md) + * Search for UserScripts - for shortcuts see [Wiki](https://github.com/magicoflolis/Userscript-Plus/blob/master/wiki/README.md#shortcuts) * Filter UserScripts which do not match your current language * Sort UserScripts, default sorting "Daily Installs" * Preview UserScripts code before install @@ -142,52 +142,11 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * **If nothing appears, this means the script is not executing at all!** * For any additional help, submit a [New Issue](https://github.com/magicoflolis/Userscript-Plus/issues/new/choose) -## Build +## Want to Contribute? -Install [Node.js](https://nodejs.org/) and [pnpm](https://pnpm.io/) - *the version of Node.js should match or be greater than the `"node"` key in `package.json`.* +Fork this repo and open a [pull request](https://github.com/magicoflolis/Userscript-Plus/pulls) - [Rules](https://github.com/magicoflolis/Userscript-Plus/blob/master/wiki/Build.md#contribution-rules) - [Guide](https://github.com/magicoflolis/Userscript-Plus/blob/master/wiki/Build.md#contribution-guide) -``` sh -# Install dependencies -$ pnpm i -``` - -### UserScript Version - -Before you begin, rename `.env.example` to `.env` - -**Recommened Testing Environments:** - -* **Desktop:** any browser with [ViolentMonkey](https://violentmonkey.github.io/), see [How to edit scripts with your favorite editor?](https://violentmonkey.github.io/posts/how-to-edit-scripts-with-your-favorite-editor/) -* **Mobile:** - * Desktop: use "Responsive Design Mode(Ctrl+Shift+M)" on [FireFox Developer Edition](https://www.mozilla.org/firefox/developer/) or just [FireFox](https://www.mozilla.org/firefox/) - * Android: any browser that supports User Script or support for installing a User Script manager, I use [Cromite](https://github.com/uazo/cromite) - * IOS: any browser that supports User Script or support for installing a User Script manager - -``` sh -# Watch and compile to local HTTP server -$ pnpm run dev:UserJS - -# Compile UserScript to "./dist" -$ pnpm run pub:UserJS -``` - -### WebExtension Version - -``` sh -# Compile WebExtension (developer version) for "Chromium" to "./build/chrome" -$ pnpm run dev:Cr -# Compile WebExtension (developer version) for "Firefox" to "./build/firefox" -$ pnpm run dev:FF -# Compile WebExtension (public version) for "Chromium" to "./build/chrome" -$ pnpm run webpack:Cr -# Compile WebExtension (public version) for "Firefox" to "./build/firefox" -$ pnpm run webpack:FF - -# [ Testing ] -# Browsers can be launched via "Run and Debug" in VSCode. -# Edit runtimeExecutable in ".vscode/launch.json" to your Chrome executable. -# Recommended to create an additional profile "about:profiles" for Firefox. -``` +How to add or edit translations? How to build? - [Build](https://github.com/magicoflolis/Userscript-Plus/blob/master/wiki/Build.md) ### Roadmap diff --git a/src/UserJS/.env.example b/src/UserJS/.env.example deleted file mode 100644 index 2d29ccc..0000000 --- a/src/UserJS/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -# Please do not change this .env variable -JS_ENV="development" diff --git a/wiki/Build.md b/wiki/Build.md new file mode 100644 index 0000000..4d1ef16 --- /dev/null +++ b/wiki/Build.md @@ -0,0 +1,84 @@ +# Build + +Install [Node.js](https://nodejs.org/) and [pnpm](https://pnpm.io/) - *the version of Node.js should match or be greater than the `"node"` key in `package.json`.* + +```sh +# Install dependencies +$ pnpm i +``` + +**UserScript:** + +Before you begin, rename `.env.example` to `.env` + +**Recommened Testing Environments:** + +- **Desktop:** any browser with [ViolentMonkey](https://violentmonkey.github.io/), see [How to edit scripts with your favorite editor?](https://violentmonkey.github.io/posts/how-to-edit-scripts-with-your-favorite-editor/) +- **Mobile:** + - Desktop: use "Responsive Design Mode (Ctrl+Shift+M)" on [FireFox Developer Edition](https://www.mozilla.org/firefox/developer/) or [FireFox](https://www.mozilla.org/firefox/) + - Android: any browser with UserScript support or support for installing a UserScript manager, I use [Cromite](https://github.com/uazo/cromite) + - IOS: any browser with UserScript support or support for installing a UserScript manager + +```sh +# Watch and build to local HTTP server +$ pnpm run dev:UserJS + +# Build UserScript to "./dist" +$ pnpm run pub:UserJS +``` + +--- + +**WebExtension:** + +```sh +# Build WebExtension (developer version) for "Chromium" to "./build/chrome" +$ pnpm run dev:Cr +# Build WebExtension (developer version) for "Firefox" to "./build/firefox" +$ pnpm run dev:FF +# Build WebExtension (public version) for "Chromium" to "./build/chrome" +$ pnpm run webpack:Cr +# Build WebExtension (public version) for "Firefox" to "./build/firefox" +$ pnpm run webpack:FF + +# [ Testing ] +# Browsers can be launched via "Run and Debug" in VSCode. +# Edit runtimeExecutable in ".vscode/launch.json" to your Chrome executable. +# Recommended to create an additional profile "about:profiles" for Firefox. +``` + +## Contribution Rules + +**General:** + +Follow [Semantic Versioning](https://semver.org/) standards, if your unsure you don't need to update the version + +--- + +**Translations:** + +Translations follow [Web Extension Internationalization](https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/Internationalization) standards + +--- + +**UserScript:** + +Do not edit the UserScript found in the `./dist` directory, the file is auto generated from `dev:UserJS` command. Instead edit it from `./src/UserJS` + +## Contribution Guide + +Fork this repo, make your changes, and open a [pull request](https://github.com/magicoflolis/Userscript-Plus/pulls) + +**Translations:** + +Translations are located in `./src/_locales` + +For versioning translations are a PATCH + +**Adding:** + +Recommend using `./src/_locales/en/messages.json` as a template + +**Updating:** + +Update any key from `messages.json` file diff --git a/wiki/README.md b/wiki/README.md index c4a70f4..8bffd31 100644 --- a/wiki/README.md +++ b/wiki/README.md @@ -1,6 +1,11 @@ # Wiki Page (Under Construction) -## New Tab +- [Wiki Page (Under Construction)](#wiki-page-under-construction) + - [Shortcuts](#shortcuts) + +## Shortcuts + +**New Tab:** Syntax: `*` - Shortcut for userscipts that apply to `All sites` @@ -25,7 +30,7 @@ mujs:settings --- -## Search Bar +**Search Bar:** By default it will search by name and description, you can refine your searches using the examples listed below. From 50dbc988c85e3b85380272fe3f23074a2739eacb Mon Sep 17 00:00:00 2001 From: Magic Date: Mon, 3 Mar 2025 13:55:22 -0800 Subject: [PATCH 16/35] Updated package.json Signed-off-by: Magic --- utils/i18n/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/i18n/package.json b/utils/i18n/package.json index 3b931be..65555d5 100644 --- a/utils/i18n/package.json +++ b/utils/i18n/package.json @@ -4,6 +4,7 @@ "description": "Loads languages", "version": "1.0.0", "license": "MIT", + "type": "module", "main": "./src/index.js", "types": "./typings/index.d.ts", "exports": { From 369711533656fb5edc37799916080794333074a0 Mon Sep 17 00:00:00 2001 From: Magic Date: Wed, 5 Mar 2025 15:42:42 -0800 Subject: [PATCH 17/35] UserJS v7.6.0 Signed-off-by: Magic --- CHANGELOG.user.md | 31 + README.md | 6 +- UserJS.json | 2 +- dist/magic-userjs.meta.js | 2 +- dist/magic-userjs.user.js | 1502 ++++++++++------- package.json | 4 +- src/UserJS/main.js | 1288 +++++++------- src/UserJS/svg/bug-svgrepo-com.svg | 1 - src/UserJS/svg/close-svgrepo-com.svg | 8 - src/UserJS/svg/download-svgrepo-com.svg | 1 - .../expand-full-fullscreen-svgrepo-com.svg | 1 - src/UserJS/svg/filter-svgrepo-com.svg | 5 - src/UserJS/svg/fork-svgrepo-com.svg | 1 - src/UserJS/svg/fullscreen-svgrepo-com.svg | 63 - src/UserJS/svg/github-svgrepo-com.svg | 1 - src/UserJS/svg/minus-svgrepo-com.svg | 2 - src/UserJS/svg/navigation-svgrepo-com.svg | 11 - src/UserJS/svg/plus-svgrepo-com.svg | 5 - src/UserJS/svg/search-svgrepo-com.svg | 1 - src/UserJS/svg/settings-svgrepo-com.svg | 4 - src/_locales/en/messages.json | 4 +- src/sass/_main.scss | 319 ++-- src/sass/magicuserjs.scss | 2 +- src/typings/UserJS.d.ts | 1 + src/typings/types.d.ts | 37 +- 25 files changed, 1838 insertions(+), 1464 deletions(-) delete mode 100644 src/UserJS/svg/bug-svgrepo-com.svg delete mode 100644 src/UserJS/svg/close-svgrepo-com.svg delete mode 100644 src/UserJS/svg/download-svgrepo-com.svg delete mode 100644 src/UserJS/svg/expand-full-fullscreen-svgrepo-com.svg delete mode 100644 src/UserJS/svg/filter-svgrepo-com.svg delete mode 100644 src/UserJS/svg/fork-svgrepo-com.svg delete mode 100644 src/UserJS/svg/fullscreen-svgrepo-com.svg delete mode 100644 src/UserJS/svg/github-svgrepo-com.svg delete mode 100644 src/UserJS/svg/minus-svgrepo-com.svg delete mode 100644 src/UserJS/svg/navigation-svgrepo-com.svg delete mode 100644 src/UserJS/svg/plus-svgrepo-com.svg delete mode 100644 src/UserJS/svg/search-svgrepo-com.svg delete mode 100644 src/UserJS/svg/settings-svgrepo-com.svg diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 5786ca2..4094647 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,5 +1,36 @@ # Changelog +## v7.6.0 + +* New feature, `Preview Metadata` - same as `Preview Code` but loads userscripts metadata head +* Config changes, moved `codePreview` value to `preview: code`, recommended resetting your config to clear any old/unused settings. + * If you had `Preview Code` enabled, you will need to re-enable it +* When `Preview Metadata` and `Preview Code` are both enabled, it will display the entire userscript +* Icon changes, svgs are now from [fontawesome.com](fontawesome.com) +* Search engines have been moved to the `Search Engines` section +* Improved mobile UI +* Improved userscript parsing +* Improved load times - added custom event to handle async item changes +* Improved GitHub engine + * Number of stars for a repo = daily installs + * Number of watchers for a repo = good rating +* Cleanup old css +* Minor bug fixes + +**Known Issues:** + +* Enabling a engine requires the page to be reloaded, while disabling a engine does not. + * This is caused by the cache system. +* SVG elements don't load on every webpage, _can be blocked by the page, external scripts, or web extensions._ +* If an item changes after the list is sorted, the sorting won't be updated + +**TODO:** + +* Finish translations. +* Finish blacklist section. + +--- + ## v7.5.0 * Merged https://github.com/magicoflolis/Userscript-Plus/pull/64 diff --git a/README.md b/README.md index 79bb3ba..58acd8e 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,17 @@ [![Badge Issues](https://img.shields.io/github/issues/magicoflolis/Userscript-Plus?style=flat-square)](https://github.com/magicoflolis/Userscript-Plus/issues) [![Badge Greasy Fork](https://img.shields.io/greasyfork/dt/421603?style=flat-square)](https://greasyfork.org/scripts/421603) [![Badge Stars](https://img.shields.io/github/stars/magicoflolis/Userscript-Plus?style=flat-square)](https://github.com/magicoflolis/Userscript-Plus/stargazers) -[![UserScript](https://img.shields.io/badge/Userscript-Download-brightgreen.svg?style=flat-square&label=Greasy+Fork&logo=javascript&logoColor=white)](https://greasyfork.org/scripts/421603) -[![UserScript](https://img.shields.io/badge/Userscript-Download-brightgreen.svg?style=flat-square&label=GitHub+Repo&logo=javascript&logoColor=white)](https://github.com/magicoflolis/Userscript-Plus/blob/master/dist/magic-userjs.user.js?raw=1) --- -

+
+

Magic Userscript+

+
*A complete rewrite of [Userscript+ : Show Site All UserJS](https://github.com/jae-jae/Userscript-Plus)* diff --git a/UserJS.json b/UserJS.json index 31269ec..24fd9a8 100644 --- a/UserJS.json +++ b/UserJS.json @@ -1,5 +1,5 @@ { - "version": "7.5.0", + "version": "7.6.0", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "author": "Magic ", diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index a6aab9d..091b951 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.5.0 +// @version 7.6.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index 6f288aa..4a35efc 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.5.0 +// @version 7.6.0 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -225,7 +225,7 @@ const translations = { "save": "Save", "reset": "Reset", "preview_code": "Preview Code", - "saveFile": "Save File", + "saveFile": "Download", "newTab": "New Tab", "applies_to": "Applies to", "license": "License", @@ -737,6 +737,9 @@ const main_css = `mujs-root { } mujs-root * { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; scrollbar-color: var(--mujs-txt-color, hsl(0, 0%, 100%)) hsl(224, 14%, 21%); scrollbar-width: thin; } @@ -783,10 +786,6 @@ td.mujs-list { font-weight: 500; } -.mujs-sty-flex > mujs-btn { - margin: auto; -} - .mujs-invalid { border-radius: 8px !important; border-width: 2px !important; @@ -806,11 +805,6 @@ mujs-row { gap: 0.5em; } -@media screen and (max-width: 800px) { - mujs-column { - flex-flow: row wrap; - } -} mujs-column count-frame[data-counter=greasyfork] { background: var(--mujs-gf-color, hsl(204, 100%, 40%)); } @@ -823,6 +817,11 @@ mujs-column count-frame[data-counter=github] { mujs-column count-frame[data-counter=openuserjs] { background: hsla(12, 86%, 50%, 0.568); } +@media screen and (max-width: 800px) { + mujs-column { + flex-flow: row wrap; + } +} mujs-row { flex-flow: column wrap; @@ -920,6 +919,11 @@ mujs-main mujs-tabs mujs-tab { border-radius: 4px; background: transparent; } +@media screen and (max-width: 800px) { + mujs-main mujs-tabs mujs-tab { + min-width: 6em !important; + } +} mujs-main mujs-tabs mujs-tab.active { background: var(--mujs-even-row, hsl(222, 14%, 18%)); } @@ -962,17 +966,25 @@ mujs-main input:not([type=checkbox]) { border: transparent; outline: none !important; } +mujs-main mujs-page, mujs-main textarea { background: inherit; overflow-y: auto; - color: var(--mujs-placeholder, hsl(81, 56%, 54%)); border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); - border-radius: 10px; - resize: vertical; + border-radius: 5px; outline: none; font-family: monospace; font-size: 14px; } +mujs-main mujs-page { + padding: 0.5em; + margin: 0.5em; +} +mujs-main textarea { + overflow-y: auto; + color: var(--mujs-placeholder, hsl(81, 56%, 54%)); + resize: vertical; +} mujs-main textarea:focus { outline: none; } @@ -1002,8 +1014,7 @@ mujs-main .mujs-prompt { align-items: center; justify-content: center; } -mujs-main .mujs-prompt svg, -mujs-main .mujs-prompt img { +mujs-main .mujs-prompt svg { width: 14px; height: 14px; background: transparent; @@ -1119,9 +1130,6 @@ mujs-header mujs-url > input { mujs-header .rate-container { order: 1; } -mujs-header .mujs-sty-flex { - order: 2; -} mujs-header .btn-frame { order: 999999999999; } @@ -1168,13 +1176,11 @@ mujs-body table { display: flex; flex-flow: row wrap; align-items: center; - border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); padding-top: 0.5em; padding-bottom: 0.5em; } mujs-body table .frame:not(.webext-page) td { margin: auto; - border-bottom: 1px solid transparent; } mujs-body table .frame:not(.webext-page) td > mujs-a, mujs-body table .frame:not(.webext-page) td > mu-js, @@ -1182,9 +1188,32 @@ mujs-body table { text-align: center; justify-content: center; } + mujs-body table .frame:not(.webext-page) td > mujs-a { + width: 100%; + } +} +@media screen and (max-width: 1180px) and (max-width: 800px) { + mujs-body table .frame:not(.webext-page) td > mujs-column { + flex-flow: column wrap; + } + mujs-body table .frame:not(.webext-page) td > mujs-column > mujs-row { + align-content: center; + } + mujs-body table .frame:not(.webext-page) td > mujs-column mujs-column { + justify-content: center; + } +} +@media screen and (max-width: 1180px) { mujs-body table .frame:not(.webext-page) td:not(.mujs-name, .install-btn) { width: 25%; } +} +@media screen and (max-width: 1180px) and (max-width: 800px) { + mujs-body table .frame:not(.webext-page) td.install-btn { + width: 100%; + } +} +@media screen and (max-width: 1180px) { mujs-body table .frame:not(.webext-page) .mujs-name { width: 100%; } @@ -1197,15 +1226,12 @@ mujs-body table { width: auto !important; } } -mujs-body table th, -mujs-body table td { - border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); -} mujs-body table th { position: -webkit-sticky; position: sticky; top: 0; background: hsla(222, 14%, 33%, 0.75); + border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); } mujs-body table th.mujs-header-name { width: 50%; @@ -1218,9 +1244,15 @@ mujs-body table th.mujs-header-name { mujs-body table .frame:nth-child(even) { background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; } +mujs-body table .frame:nth-child(even) textarea { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; +} mujs-body table .frame:nth-child(odd) { background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; } +mujs-body table .frame:nth-child(odd) textarea { + background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; +} mujs-body table .frame:not([data-engine=sleazyfork], [data-engine=greasyfork]) mujs-a { color: var(--mujs-sf-txt-color, hsl(12, 79%, 55%)); } @@ -1295,12 +1327,9 @@ mujs-body table .frame .mujs-ratings[data-el=bad] { color: hsl(0, 100%, 50%); } mujs-body table .frame svg { + width: 12px; + height: 12px; fill: currentColor; -} -mujs-body table .frame svg, -mujs-body table .frame img { - width: 14px; - height: 14px; background: transparent; } mujs-body table .frame > td:not(.mujs-name) { @@ -1323,6 +1352,11 @@ mujs-body table .frame > .mujs-name > mu-jsbtn { mujs-body table .frame > .mujs-name > mujs-column > mu-jsbtn { padding: 0px 7px; } +@media screen and (max-width: 800px) { + mujs-body table .frame > .mujs-name > mujs-column > mu-jsbtn { + width: 100%; + } +} mujs-body table .frame > .mujs-uframe > mujs-a { font-size: 16px; font-weight: 500; @@ -1363,6 +1397,26 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a::after { mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after { content: ""; } +@media screen and (max-width: 800px) { + mujs-body table .frame [data-el=matches] { + width: 30em !important; + } +} +mujs-body table .frame [data-name=license] { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; +} +@media screen and (max-width: 800px) { + mujs-body table .frame [data-name=license] { + width: 100% !important; + width: -moz-available !important; + width: -webkit-fill-available !important; + } +} @media screen and (max-width: 1150px) { .mujs-cfg { @@ -1374,18 +1428,6 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after height: -moz-fit-content; height: -webkit-fit-content; } -@media screen and (max-height: 720px) { - .mujs-cfg:not(.webext-page) { - height: 100%; - height: -moz-available; - height: -webkit-fill-available; - width: 100%; - width: -moz-available; - width: -webkit-fill-available; - overflow-x: auto; - padding: 0.5em; - } -} .mujs-cfg mujs-section { border-radius: 16px; padding: 0.5em; @@ -1393,15 +1435,43 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg mujs-section:nth-child(even) { background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; } +.mujs-cfg mujs-section:nth-child(even) input, +.mujs-cfg mujs-section:nth-child(even) select { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)); +} +.mujs-cfg mujs-section:nth-child(even) select option { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)); +} +.mujs-cfg mujs-section:nth-child(even) select option:hover { + background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; +} .mujs-cfg mujs-section:nth-child(odd) { background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; } -.mujs-cfg mujs-section[data-name=theme], .mujs-cfg mujs-section[data-name=blacklist] { +.mujs-cfg mujs-section:nth-child(odd) input, +.mujs-cfg mujs-section:nth-child(odd) select { + background: var(--mujs-even-row, hsl(222, 14%, 18%)); +} +.mujs-cfg mujs-section:nth-child(odd) select option { + background: var(--mujs-even-row, hsl(222, 14%, 18%)); +} +.mujs-cfg mujs-section:nth-child(odd) select option:hover { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; +} +.mujs-cfg mujs-section[data-name=theme], .mujs-cfg mujs-section[data-name=exp], .mujs-cfg mujs-section[data-name=blacklist] { display: flex; justify-content: space-between; flex-direction: column; gap: 0.25em; } +.mujs-cfg mujs-section[data-name=theme] > mujs-btn, .mujs-cfg mujs-section[data-name=exp] > mujs-btn, .mujs-cfg mujs-section[data-name=blacklist] > mujs-btn { + width: 100%; + width: -moz-available; + width: -webkit-fill-available; +} +.mujs-cfg mujs-section[data-name=theme] > mujs-btn:hover, .mujs-cfg mujs-section[data-name=exp] > mujs-btn:hover, .mujs-cfg mujs-section[data-name=blacklist] > mujs-btn:hover { + background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; +} .mujs-cfg mujs-section input[type=text]::-webkit-input-placeholder { color: var(--mujs-placeholder, hsl(81, 56%, 54%)); } @@ -1434,22 +1504,37 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg mujs-section > label.new-list mujs-add { font-size: 20px; } -.mujs-cfg mujs-section > label.sub-section { - padding: 0.2em; -} .mujs-cfg mujs-section > label input:not([type=checkbox]) { font-size: 14px; position: relative; border-radius: 4px; border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); } -.mujs-cfg mujs-section > input { +.mujs-cfg mujs-section select, +.mujs-cfg mujs-section select option { + color: var(--mujs-txt-color, hsl(0, 0%, 100%)); + border: 1px solid transparent; + list-style: none; + outline-style: none; + pointer-events: auto; +} +.mujs-cfg mujs-section select { + text-align: center; + border-radius: 4px; +} +.mujs-cfg mujs-section > *.sub-section { + padding: 0.2em; +} +.mujs-cfg mujs-section > *.sub-section[data-engine] { + flex-wrap: wrap; +} +.mujs-cfg mujs-section > *.sub-section[data-engine] input { width: 100%; width: -moz-available; width: -webkit-fill-available; - margin-top: 5px; - border-radius: 4px; - border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); +} +.mujs-cfg mujs-section > *.sub-section input[type=text] { + margin: 0.2em 0px; } .mujs-cfg .mujs-inlab { position: relative; @@ -1465,8 +1550,11 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg .mujs-inlab input[type=checkbox]:checked + label:before { right: 0px; } -.mujs-cfg .mujs-inlab input[type=checkbox][data-name=greasyfork]:checked + label, .mujs-cfg .mujs-inlab input[type=checkbox][data-name=sleazyfork]:checked + label { - background: var(--mujs-chck-gf, hsla(197, 100%, 50%, 0.568)); +.mujs-cfg .mujs-inlab input[type=checkbox][data-name=greasyfork]:checked + label { + background: var(--mujs-gf-color, hsl(204, 100%, 40%)); +} +.mujs-cfg .mujs-inlab input[type=checkbox][data-name=sleazyfork]:checked + label { + background: var(--mujs-sf-color, hsl(12, 86%, 50%)); } .mujs-cfg .mujs-inlab input[type=checkbox][data-name=openuserjs]:checked + label { background: var(--mujs-chck-open, hsla(12, 86%, 50%, 0.568)); @@ -1494,6 +1582,9 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after right: 20px; border-radius: 20px; } +.mujs-cfg .mujs-sty-flex mujs-btn { + margin: auto; +} .mujs-cfg .mujs-sty-flex mujs-btn[data-command=reset] { background: var(--mujs-sf-btn-color, hsl(12, 86%, 50%)); border-color: var(--mujs-sf-btn-color, hsl(12, 86%, 50%)); @@ -1513,6 +1604,18 @@ mujs-body table .frame [data-el=matches] .mujs-grants > mujs-a:last-child::after .mujs-cfg:not(.webext-page) { margin: 1rem 25rem; } +@media screen and (max-height: 720px) { + .mujs-cfg:not(.webext-page) { + height: 100%; + height: -moz-available; + height: -webkit-fill-available; + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + overflow-x: auto; + padding: 0.5em; + } +} mujs-a { display: inline-block; @@ -1541,12 +1644,9 @@ mujs-btn { padding: 6px 15px; } mujs-btn svg { - fill: var(--mujs-txt-color, hsl(0, 0%, 100%)); -} -mujs-btn svg, -mujs-btn img { width: 14px; height: 14px; + fill: var(--mujs-txt-color, hsl(0, 0%, 100%)); } mu-jsbtn { @@ -1564,7 +1664,7 @@ mu-jsbtn { mujs-a, mu-jsbtn, .mujs-pointer, -.mujs-cfg mujs-section *:not(input[type=password], input[type=text], input[type=number], [data-theme], [data-blacklist]), +.mujs-cfg mujs-section *:not(input[type=text], input[type=number], [data-theme], [data-blacklist]), .mainbtn, .mainframe, mujs-btn { @@ -1624,6 +1724,65 @@ const log = (...msg) => { */ let cfg = {}; +// #region Validators +/** + * @type { import("../typings/types.d.ts").objToStr } + */ +const objToStr = (obj) => Object.prototype.toString.call(obj); +/** + * @type { import("../typings/types.d.ts").isRegExp } + */ +const isRegExp = (obj) => { + const s = objToStr(obj); + return s.includes('RegExp'); +}; +/** + * @type { import("../typings/types.d.ts").isElem } + */ +const isElem = (obj) => { + const s = objToStr(obj); + return s.includes('Element'); +}; +/** + * @type { import("../typings/types.d.ts").isObj } + */ +const isObj = (obj) => { + const s = objToStr(obj); + return s.includes('Object'); +}; +/** + * @type { import("../typings/types.d.ts").isFN } + */ +const isFN = (obj) => { + const s = objToStr(obj); + return s.includes('Function'); +}; +/** + * @type { import("../typings/types.d.ts").isNull } + */ +const isNull = (obj) => { + return Object.is(obj, null) || Object.is(obj, undefined); +}; +/** + * @type { import("../typings/types.d.ts").isBlank } + */ +const isBlank = (obj) => { + return ( + (typeof obj === 'string' && Object.is(obj.trim(), '')) || + ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || + (Array.isArray(obj) && Object.is(obj.length, 0)) || + (isObj(obj) && Object.is(Object.keys(obj).length, 0)) + ); +}; +/** + * @type { import("../typings/types.d.ts").isEmpty } + */ +const isEmpty = (obj) => { + return isNull(obj) || isBlank(obj); +}; +// #endregion + +// #region Globals /** * https://github.com/zloirock/core-js/blob/master/packages/core-js/internals/global-this.js * @returns {typeof globalThis} @@ -1643,7 +1802,6 @@ function globalWin() { Function('return this')() ); } - /** @type { import("../typings/UserJS.d.ts").safeSelf } */ function safeSelf() { if (userjs.safeSelf) { @@ -1653,6 +1811,7 @@ function safeSelf() { /** @type { import("../typings/UserJS.d.ts").safeHandles } */ const safe = { XMLHttpRequest: g.XMLHttpRequest, + CustomEvent: g.CustomEvent, createElement: g.document.createElement.bind(g.document), createElementNS: g.document.createElementNS.bind(g.document), createTextNode: g.document.createTextNode.bind(g.document), @@ -1689,9 +1848,20 @@ function safeSelf() { } } }; + for (const [k, v] of Object.entries(safe)) { + if (k === 'scheduler') { + continue; + } else if (k === 'navigator') { + continue; + } else if (isFN(v)) { + continue; + } + err({ message: `Safe handles "${k}" returned "${v}"`, cause: 'safeSelf' }); + } userjs.safeSelf = safe; return userjs.safeSelf; } +// #endregion const BLANK_PAGE = 'about:blank'; // Lets highlight me :) @@ -1786,12 +1956,15 @@ const DEFAULT_CONFIG = { autoSort: 'daily_installs', clearTabCache: true, cache: true, - codePreview: false, autoexpand: false, filterlang: false, sleazyredirect: false, time: 10000, blacklist: ['userjs-local', 'userjs-finance', 'userjs-social', 'userjs-unsupported'], + preview: { + code: false, + metadata: false + }, engines: [ { enabled: true, @@ -1943,61 +2116,6 @@ const qsA = (selectors, root) => { } return []; }; -/** - * @type { import("../typings/types.d.ts").objToStr } - */ -const objToStr = (obj) => Object.prototype.toString.call(obj); -/** - * @type { import("../typings/types.d.ts").isRegExp } - */ -const isRegExp = (obj) => { - const s = objToStr(obj); - return s.includes('RegExp'); -}; -/** - * @type { import("../typings/types.d.ts").isElem } - */ -const isElem = (obj) => { - const s = objToStr(obj); - return s.includes('Element'); -}; -/** - * @type { import("../typings/types.d.ts").isObj } - */ -const isObj = (obj) => { - const s = objToStr(obj); - return s.includes('Object'); -}; -/** - * @type { import("../typings/types.d.ts").isFN } - */ -const isFN = (obj) => { - const s = objToStr(obj); - return s.includes('Function'); -}; -/** - * @type { import("../typings/types.d.ts").isNull } - */ -const isNull = (obj) => { - return Object.is(obj, null) || Object.is(obj, undefined); -}; -/** - * @type { import("../typings/types.d.ts").isBlank } - */ -const isBlank = (obj) => { - return ( - (typeof obj === 'string' && Object.is(obj.trim(), '')) || - ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || - (Array.isArray(obj) && Object.is(obj.length, 0)) || - (isObj(obj) && Object.is(Object.keys(obj).length, 0)) - ); -}; -/** - * @type { import("../typings/types.d.ts").isEmpty } - */ -const isEmpty = (obj) => { - return isNull(obj) || isBlank(obj); -}; /** * @type { import("../typings/types.d.ts").normalizeTarget } */ @@ -2201,61 +2319,57 @@ class Memorize { const memory = new Memorize(); //#region Icon SVGs const iconSVG = { - cfg: { - viewBox: '0 0 24 24', - html: '' - }, close: { - viewBox: '0 0 24 24', - html: '' + viewBox: '0 0 384 512', + html: '' }, - filter: { - viewBox: '0 0 24 24', - html: '' + code: { + viewBox: '0 0 640 512', + html: '' }, - fsClose: { - viewBox: '0 0 24 24', - html: ' ' + collapse: { + viewBox: '0 0 448 512', + html: '' }, - fsOpen: { - viewBox: '0 0 24 24', - html: ' ' + download: { + viewBox: '0 0 384 512', + html: '' }, - fullscreen: { - viewBox: '0 0 96 96', - html: '' + expand: { + viewBox: '0 0 448 512', + html: '' }, - gf: { - viewBox: '0 0 510.4 510.4', - html: '' + gear: { + viewBox: '0 0 512 512', + html: '' }, - gh: { - viewBox: '0 0 16 16', - html: '' + github: { + viewBox: '0 0 496 512', + html: '' }, - hide: { - viewBox: '0 0 24 24', - html: ' ' + globe: { + viewBox: '0 0 512 512', + html: '' }, install: { - viewBox: '0 0 16 16', - html: '' + viewBox: '0 0 512 512', + html: '' }, issue: { - viewBox: '0 0 24 24', - html: '' + viewBox: '0 0 512 512', + html: '' }, - nav: { - viewBox: '0 0 24 24', - html: ' ' + minus: { + viewBox: '0 0 448 512', + html: '' }, - plus: { - viewBox: '0 0 24 24', - html: '' + nav: { + viewBox: '0 0 448 512', + html: '' }, - search: { - viewBox: '0 0 24 24', - html: '' + pager: { + viewBox: '0 0 512 512', + html: '' }, verified: { viewBox: '0 0 56 56', @@ -2264,9 +2378,9 @@ const iconSVG = { html: '' }, refresh: { - viewBox: '0 0 1024 1024', + viewBox: '0 0 512 512', fill: 'currentColor', - html: '' + html: '' }, load(type, container) { const { createElementNS } = safeSelf(); @@ -2610,6 +2724,7 @@ const Counter = { } } }; + // #region Container /** * @type { import("../typings/UserJS.d.ts").Container } @@ -2675,11 +2790,7 @@ class Container { } }); if (this.supported) { - this.shadowRoot = this.frame.attachShadow({ - mode: 'closed' - // clonable: false, - // delegatesfocus: false - }); + this.shadowRoot = this.frame.attachShadow({ mode: 'closed' }); this.ready = true; } this.cache = memory.maps.container; @@ -2698,6 +2809,7 @@ class Container { } set(delay, reason) { + const { setTimeout } = safeSelf(); return new Promise((resolve, reject) => { const id = setTimeout(() => { Object.is(reason, null) || Object.is(reason, undefined) ? resolve() : reject(reason); @@ -2708,6 +2820,7 @@ class Container { } clear(...ids) { + const { clearTimeout } = safeSelf(); this.ids = this.ids.filter((id) => { if (ids.includes(id)) { clearTimeout(id); @@ -2773,7 +2886,7 @@ class Container { Counter.cnt.total.root = this.mainbtn; for (const engine of cfg.engines) this.countframe.append(Counter.set(engine)); - const { cfgpage, table, exBtn, supported, frame, refresh, cache, urlBar, host } = this; + const { cfgpage, table, supported, frame, refresh, cache, urlBar, host } = this; class Tabs { /** @@ -2818,7 +2931,7 @@ class Container { return; } if (hostname.match(this.protoReg)[1] === 'settings') { - dom.cl.remove([cfgpage, exBtn], 'hidden'); + dom.cl.remove(cfgpage, 'hidden'); dom.cl.add(table, 'hidden'); if (!supported) { dom.attr(frame, 'style', 'height: 100%;'); @@ -2831,7 +2944,7 @@ class Container { */ active(tab, build = true) { if (!this.pool.has(tab)) this.pool.add(tab); - dom.cl.add([cfgpage, exBtn], 'hidden'); + dom.cl.add(cfgpage, 'hidden'); dom.cl.remove(table, 'hidden'); dom.cl.remove([...this.pool], 'active'); dom.cl.add(tab, 'active'); @@ -2913,8 +3026,7 @@ class Container { this.tab.create(host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => - tr.children[idx].dataset.value || tr.children[idx].innerText || tr.children[idx].textContent; + const getCellValue = (tr, idx) => tr.children[idx].dataset.value; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) @@ -2961,43 +3073,18 @@ class Container { this.tbody = make('mujs-body'); this.cfgpage = make('mujs-row', 'mujs-cfg hidden'); this.btnframe = make('mujs-column', 'btn-frame'); - this.exBtn = make('mujs-column', 'mujs-sty-flex hidden'); this.fsearch = make('mujs-btn', 'hidden'); - this.exportCFG = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_config'), - dataset: { - command: 'export-cfg' - } - }); - this.importCFG = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_config'), - dataset: { - command: 'import-cfg' - } - }); - this.exportTheme = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_theme'), - dataset: { - command: 'export-theme' - } - }); - this.importTheme = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_theme'), - dataset: { - command: 'import-theme' - } - }); this.btnHandles = make('mujs-column', 'btn-handles'); this.btnHide = make('mujs-btn', 'hide-list', { title: i18n$('min'), - innerHTML: iconSVG.load('hide'), + innerHTML: iconSVG.load('minus'), dataset: { command: 'hide-list' } }); this.btnfullscreen = make('mujs-btn', 'fullscreen', { title: i18n$('max'), - innerHTML: iconSVG.load('fullscreen'), + innerHTML: iconSVG.load('expand'), dataset: { command: 'fullscreen' } @@ -3013,7 +3100,7 @@ class Container { }); this.btncfg = make('mujs-btn', 'settings hidden', { title: 'Settings', - innerHTML: iconSVG.load('cfg'), + innerHTML: iconSVG.load('gear'), dataset: { command: 'settings' } @@ -3024,7 +3111,7 @@ class Container { ? $info.script.version : $info.script.version.slice(0, 5) })`, - innerHTML: iconSVG.load('gh'), + innerHTML: iconSVG.load('github'), dataset: { command: 'open-tab', webpage: $info.script.namespace @@ -3040,7 +3127,7 @@ class Container { }); this.btngreasy = make('mujs-btn', 'greasy hidden', { title: 'Greasy Fork', - innerHTML: iconSVG.load('gf'), + innerHTML: iconSVG.load('globe'), dataset: { command: 'open-tab', webpage: 'https://greasyfork.org/scripts/421603' @@ -3081,17 +3168,30 @@ class Container { } ]); // #endregion - - this.btnHandles.append(this.btnHide, this.btnfullscreen, this.closebtn); - this.btnframe.append(this.btnhome, this.btngreasy, this.btnissue, this.btncfg, this.btnnav); + if (isMobile) { + dom.cl.add([this.btnHide, this.btnfullscreen, this.closebtn], 'hidden'); + this.btnframe.append( + this.btnHide, + this.btnfullscreen, + this.closebtn, + this.btnhome, + this.btngreasy, + this.btnissue, + this.btncfg, + this.btnnav + ); + } else { + this.btnHandles.append(this.btnHide, this.btnfullscreen, this.closebtn); + this.btnframe.append(this.btnhome, this.btngreasy, this.btnissue, this.btncfg, this.btnnav); + } this.toolbar.append(this.btnHandles); this.urlContainer.append(this.urlBar); this.header.append(this.urlContainer, this.rateContainer, this.countframe, this.btnframe); this.tbody.append(this.table, this.cfgpage); this.main.append(this.toolbar, this.header, this.tbody, this.footer, this.promptElem); this.mainframe.append(this.mainbtn); - this.exBtn.append(this.importCFG, this.importTheme, this.exportCFG, this.exportTheme); - this.header.append(this.exBtn); + // this.exBtn.append(this.importCFG, this.importTheme, this.exportCFG, this.exportTheme); + // this.header.append(this.exBtn); this.root.append(this.mainframe, this.main); return true; @@ -3390,10 +3490,6 @@ function primaryFN() { fsearch, btnfullscreen, main, - btncfg, - btnhome, - btnissue, - btngreasy, tab, showError } = container; @@ -3438,8 +3534,75 @@ function primaryFN() { installLink.remove(); await init(); }; + const applyTo = (ujs, name, elem, root) => { + const n = ujs._mujs.code[name] ?? ujs._mujs.code.data_meta[name]; + if (isEmpty(n)) { + const el = make('mujs-a', { + textContent: i18n$('listing_none') + }); + elem.append(el); + return; + } + dom.prop(elem, 'innerHTML', ''); + dom.cl.remove(root, 'hidden'); + if (isObj(n)) { + if (name === 'resource') { + for (const [k, v] of Object.entries(n)) { + const el = make('mujs-a', { + textContent: k ?? 'ERROR' + }); + if (v.startsWith('http')) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = v; + } + elem.append(el); + } + } else { + const el = make('mujs-a', { + textContent: n.text + }); + if (n.domain) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = `https://${n.text}`; + } + elem.append(el); + } + } else if (typeof n === 'string') { + const el = make('mujs-a', { + textContent: n + }); + elem.append(el); + } else { + for (const c of n) { + if (typeof c === 'string' && c.startsWith('http')) { + const el = make('mujs-a', { + textContent: c, + dataset: { + command: 'open-tab', + webpage: c + } + }); + elem.append(el); + } else if (isObj(c)) { + const el = make('mujs-a', { + textContent: c.text + }); + if (c.domain) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = `https://${c.text}`; + } + elem.append(el); + } else { + const el = make('mujs-a', { + textContent: c + }); + elem.append(el); + } + } + } + }; // #region Main event handlers - ael(main, 'click', async (evt) => { + ael(main, isMobile ? 'touchend' : 'click', async (evt) => { try { /** @type { HTMLElement } */ const target = evt.target.closest('[data-command]'); @@ -3485,10 +3648,13 @@ function primaryFN() { } return window.open(dataset.webpage, '_blank'); } else if (cmd === 'navigation') { - if (dom.cl.has(btngreasy, 'hidden')) { - dom.cl.remove([btncfg, btngreasy, btnhome, btnissue], 'hidden'); - } else { - dom.cl.add([btncfg, btngreasy, btnhome, btnissue], 'hidden'); + for (const e of qsA('mujs-btn', target.parentElement)) { + if (dom.cl.has(e, 'nav')) continue; + if (dom.cl.has(e, 'hidden')) { + dom.cl.remove(e, 'hidden'); + } else { + dom.cl.add(e, 'hidden'); + } } } else if (cmd === 'list-description') { const arr = []; @@ -3520,10 +3686,10 @@ function primaryFN() { } else if (cmd === 'fullscreen') { if (dom.cl.has(btnfullscreen, 'expanded')) { dom.cl.remove([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('expand')); } else { dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('collapse')); } } else if (cmd === 'hide-list') { dom.cl.add(main, 'hidden'); @@ -3592,81 +3758,115 @@ function primaryFN() { dlBtn.click(); URL.revokeObjectURL(dlBtn.href); dlBtn.remove(); - } else if (cmd === 'load-userjs') { + } else if (cmd === 'load-userjs' || cmd === 'load-header') { if (!container.userjsCache.has(+dataset.userjs)) { return; } const codeArea = qs('textarea', target.parentElement.parentElement); - if (!isEmpty(codeArea.value)) { + if (!isEmpty(codeArea.value) && cmd === codeArea.dataset.load) { dom.cl.toggle(codeArea, 'hidden'); return; } + codeArea.dataset.load = cmd; const dataUserJS = container.userjsCache.get(+dataset.userjs); - const r = await dataUserJS._mujs.code.request(); - const txt = r.data; - if (typeof txt !== 'string') { + const code_obj = await dataUserJS._mujs.code.request(); + if (typeof code_obj.data_code_block !== 'string') { + codeArea.value = 'An error occured'; return; } - const code_obj = new ParseUserJS(txt); - codeArea.value = code_obj.get_code_block(); + codeArea.value = + cmd === 'load-userjs' ? code_obj.data_code_block : code_obj.data_meta_block; dom.cl.remove(codeArea, 'hidden'); - const apTo = (name, elem, root) => { - const n = dataUserJS._mujs.code[name]; - if (isEmpty(n)) { - const el = make('mujs-a', { - textContent: i18n$('listing_none') + for (const e of qsA( + 'mujs-column[data-el="matches"]', + target.parentElement.parentElement + )) { + applyTo(dataUserJS, e.dataset.type, qs('.mujs-grants', e), e); + } + } else if (cmd === 'load-page') { + if (!container.userjsCache.has(+dataset.userjs)) { + return; + } + let pageArea = qs('mujs-page', target.parentElement.parentElement); + if (!pageArea) { + pageArea = make('mujs-page'); + target.parentElement.parentElement.append(pageArea); + const dataUserJS = container.userjsCache.get(+dataset.userjs); + const engine = dataUserJS._mujs.info.engine; + let pageURL; + if (engine.name.includes('fork')) { + const { navigator } = safeSelf(); + const current = navigator.language.split('-')[0] ?? 'en'; + pageURL = dataUserJS.url.replace( + /\/scripts/, + `/${/^(zh|fr|es)/.test(current) ? navigator.language : current}/scripts` + ); + } else if (engine.name.includes('github')) { + const page_url = await Network.req(dataUserJS.page_url, 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).catch(() => { + return {}; }); - elem.append(el); + if (!page_url.download_url) { + return; + } + const page = await Network.req(page_url.download_url, 'GET', 'text'); + if (container.supported) { + const shadow = pageArea.attachShadow({ mode: 'closed' }); + const div = make('div', { + innerHTML: page + }); + shadow.append(div); + } return; + } else { + pageURL = dataUserJS.url; } - dom.prop(elem, 'innerHTML', ''); - dom.cl.remove(root, 'hidden'); - for (const c of n) { - if (typeof c === 'string' && c.startsWith('http')) { - const el = make('mujs-a', { - textContent: c, - dataset: { - command: 'open-tab', - webpage: c - } - }); - elem.append(el); - } else if (isObj(c)) { - if (name === 'resource') { - for (const [k, v] of Object.entries(c)) { - const el = make('mujs-a', { - textContent: k ?? 'ERROR' - }); - if (v.startsWith('http')) { - el.dataset.command = 'open-tab'; - el.dataset.webpage = v; - } - elem.append(el); - } - } else { - const el = make('mujs-a', { - textContent: c.text - }); - if (c.domain) { - el.dataset.command = 'open-tab'; - el.dataset.webpage = `https://${c.text}`; - } - elem.append(el); + if (!pageURL) { + return; + } + const page = await Network.req(pageURL, 'GET', 'document'); + const getContent = () => { + let content = 'An error occured'; + const h = new URL(dataUserJS.url); + const root = qs('.user-content', page.documentElement); + for (const e of qsA('[href]', root)) { + e.target = '_blank'; + e.style = 'pointer-events: auto;'; + if (e.href.startsWith('/')) { + e.href = `${h.origin}${e.href}`; } + } + for (const e of qsA('img[src]', root)) { + e.style = + 'max-width: 25em; max-height: 25em; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;'; + } + if (root) { + content = root.innerHTML; } else { - const el = make('mujs-a', { - textContent: c - }); - elem.append(el); + content = 'No additional info available'; } + return content; + }; + if (container.supported) { + const shadow = pageArea.attachShadow({ mode: 'closed' }); + const div = make('div', { + style: 'pointer-events: none;', + innerHTML: getContent() + }); + shadow.append(div); } - }; - for (const e of qsA( - 'mujs-column[data-el="matches"]', - target.parentElement.parentElement - )) { - apTo(e.dataset.type, qs('.mujs-grants', e), e); + return; + } + if (!dom.cl.has(pageArea, 'hidden')) { + dom.cl.add(pageArea, 'hidden'); + return; } + dom.cl.remove(pageArea, 'hidden'); } else if (/export-/.test(cmd)) { const str = JSON.stringify(cmd === 'export-cfg' ? cfg : cfg.theme, null, ' '); const bytes = new TextEncoder().encode(str); @@ -3767,9 +3967,50 @@ function primaryFN() { }); } } + ael(main, 'updateditem', (evt) => { + /** + * @type {import("../typings/types.d.ts").GSForkQuery} + */ + const ujs = evt.detail; + if (!ujs._mujs) return; + for (const elem of qsA('[data-name]', ujs._mujs.root)) { + const name = elem.dataset.name; + if (name === 'code') { + if (ujs._mujs.code.data_code_block) { + if (cfg.preview.code && !cfg.preview.metadata) { + elem.value = ujs._mujs.code.data_code_block; + } else if (cfg.preview.metadata && !cfg.preview.code) { + elem.value = ujs._mujs.code.data_meta_block; + } else { + elem.value = `${ujs._mujs.code.META_START_COMMENT}${ujs._mujs.code.data_meta_block}${ujs._mujs.code.META_END_COMMENT}${ujs._mujs.code.data_code_block}`; + } + } + continue; + } + if (!ujs[name]) continue; + if (name === 'license') { + dom.attr(elem, 'title', ujs.license ?? i18n$('no_license')); + dom.text(elem, `${i18n$('license')}: ${ujs.license ?? i18n$('no_license')}`); + } else if (name === 'code_updated_at') { + dom.text(elem, language.toDate(ujs.code_updated_at)); + elem.dataset.value = new Date(ujs.code_updated_at).toISOString(); + } else if (name === 'created_date') { + dom.text(elem, `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`); + elem.dataset.value = new Date(ujs.created_at).toISOString(); + } else if (name === 'total_installs') { + dom.text(elem, `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}`); + } else { + dom.text(elem, ujs[name]); + } + } + if (ujs._mujs.code.data_code_block) { + for (const e of qsA('mujs-column[data-el="matches"]', ujs._mujs.root)) { + applyTo(ujs, e.dataset.type, qs('.mujs-grants', e), e); + } + } + if (container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); + }); // #endregion - const META_START_COMMENT = '// ==UserScript=='; - const META_END_COMMENT = '// ==/UserScript=='; const TLD_EXPANSION = ['com', 'net', 'org', 'de', 'co.uk']; const APPLIES_TO_ALL_PATTERNS = [ 'http://*', @@ -3797,15 +4038,17 @@ function primaryFN() { */ data_code_block; /** - * @type { { [meta: string]: any } } + * @type { { [meta: string]: string | string[] | { [resource: string]: string } } } */ data_meta; /** - * @type { string[] } + * @type { {text: string;domain: boolean;tld_extra: boolean}[] } */ data_names; - constructor(code) { + constructor(code, isUserCSS) { this.code = code; + this.META_START_COMMENT = isUserCSS ? '/* ==UserStyle==' : '// ==UserScript=='; + this.META_END_COMMENT = isUserCSS ? '==/UserStyle== */' : '// ==/UserScript=='; this.get_meta_block(); this.get_code_block(); this.parse_meta(); @@ -3818,17 +4061,20 @@ function primaryFN() { if (this.data_meta_block) { return this.data_meta_block; } - const start_block = this.code.indexOf(META_START_COMMENT); + const start_block = this.code.indexOf(this.META_START_COMMENT); if (isNull(start_block)) { return null; } - const end_block = this.code.indexOf(META_END_COMMENT, start_block); + const end_block = this.code.indexOf(this.META_END_COMMENT, start_block); if (isNull(end_block)) { return null; } - const meta_block = this.code.substring(start_block + META_START_COMMENT.length, end_block); + const meta_block = this.code.substring( + start_block + this.META_START_COMMENT.length, + end_block + ); this.data_meta_block = meta_block; - return meta_block; + return this.data_meta_block; } get_code_block() { if (isEmpty(this.code)) { @@ -3837,28 +4083,23 @@ function primaryFN() { if (this.data_code_block) { return this.data_code_block; } - const start_block = this.code.indexOf(META_START_COMMENT); + const start_block = this.code.indexOf(this.META_START_COMMENT); if (isNull(start_block)) { return null; } - const end_block = this.code.indexOf(META_END_COMMENT, start_block); + const end_block = this.code.indexOf(this.META_END_COMMENT, start_block); if (isNull(end_block)) { return null; } const code_block = this.code.substring( - end_block + META_END_COMMENT.length, + end_block + this.META_END_COMMENT.length, this.code.length ); - const lines = []; - for (const l of code_block.split('\n')) { - if (isEmpty(l)) { - continue; - } - lines.push(l); - } - const clean_code = lines.join('\n'); - this.data_code_block = clean_code; - return clean_code; + this.data_code_block = code_block + .split('\n') + .filter((l) => !isEmpty(l)) + .join('\n'); + return this.data_code_block; } parse_meta() { if (isEmpty(this.code)) { @@ -3868,11 +4109,10 @@ function primaryFN() { return this.data_meta; } const meta = {}; - const meta_block = this.get_meta_block(); const meta_block_map = new Map(); - for (const meta_line of meta_block.split('\n')) { - const meta_match = meta_line.match(/\/\/\s+@([a-zA-Z:-]+)\s+(.*)/); - if (isNull(meta_match)) { + for (const meta_line of this.get_meta_block().split('\n')) { + const meta_match = /\/\/\s+@([a-zA-Z:-]+)\s+(.*)/.exec(meta_line); + if (!meta_match) { continue; } const key = meta_match[1].trim(); @@ -3894,9 +4134,6 @@ function primaryFN() { this.data_meta = meta; return this.data_meta; } - /** - * @returns { string[] } - */ calculate_applies_to_names() { if (isEmpty(this.code)) { return null; @@ -3904,10 +4141,9 @@ function primaryFN() { if (this.data_names) { return this.data_names; } - const meta = this.parse_meta(); let patterns = []; - for (const [k, v] of Object.entries(meta)) { - if (/include|match/.test(k)) { + for (const [k, v] of Object.entries(this.parse_meta())) { + if (/include|match/i.test(k)) { if (Array.isArray(v)) { patterns = patterns.concat(v); } else { @@ -3919,14 +4155,21 @@ function primaryFN() { return []; } if (this.intersect(patterns, APPLIES_TO_ALL_PATTERNS)) { - return []; + this.data_names = [ + { + domain: false, + text: 'All sites', + tld_extra: false + } + ]; + return this.data_names; } - const name_set = new Set(); + const name_map = new Map(); const addObj = (obj) => { - if (name_set.has(obj)) { + if (name_map.has(obj.text)) { return; } - name_set.add(obj); + name_map.set(obj.text, obj); }; for (let p of patterns) { try { @@ -3935,8 +4178,8 @@ function primaryFN() { if (p.match(/^\/(.*)\/$/)) { pre_wildcards = [p]; } else { - let m = p.match(/^\*(https?:.*)/i); - if (!isNull(m)) { + let m = /^\*(https?:.*)/i.exec(p); + if (m) { p = m[1]; } p = p @@ -3944,20 +4187,20 @@ function primaryFN() { .replace(/^\*\/\//i, 'http://') .replace(/^http\*:/i, 'http:') .replace(/^(https?):([^/])/i, '$1://$2'); - m = p.match(/^([a-z]+:\/\/)\*\.?([a-z0-9-]+(?:.[a-z0-9-]+)+.*)/i); - if (!isNull(m)) { + m = /^([a-z]+:\/\/)\*\.?([a-z0-9-]+(?:.[a-z0-9-]+)+.*)/i.exec(p); + if (m) { p = m[1] + m[2]; } - m = p.match(/^\*\.?([a-z0-9-]+\.[a-z0-9-]+.*)/i); - if (!isNull(m)) { + m = /^\*\.?([a-z0-9-]+\.[a-z0-9-]+.*)/i.exec(p); + if (m) { p = `http://${m[1]}`; } - m = p.match(/^http\*(?:\/\/)?\.?((?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+.*)/i); - if (!isNull(m)) { + m = /^http\*(?:\/\/)?\.?((?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+.*)/i.exec(p); + if (m) { p = `http://${m[1]}`; } - m = p.match(/^([a-z]+:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)*\.))\*(.*)/); - if (!isNull(m)) { + m = /^([a-z]+:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)*\.))\*(.*)/.exec(p); + if (m) { if (m[2].match(/A([0-9]+\.){2,}z/)) { p = `${m[1]}tld${m[3]}`; pre_wildcards = [p.split('*')[0]]; @@ -4007,26 +4250,12 @@ function primaryFN() { err(ex); } } - const arr = [...name_set]; - this.data_names = arr; + this.data_names = [...name_map.values()]; return this.data_names; } - intersect(a = [], b = []) { - for (const v of a) { - if (b.includes(v)) { - return true; - } - } - for (const v of b) { - if (a.includes(v)) { - return true; - } - } - return false; + intersect(a, ...arr) { + return !isBlank([...new Set(a)].filter((v) => arr.every((b) => b.includes(v)))); } - // intersect(a, ...arr) { - // return [...new Set(a)].filter((v) => arr.every((b) => b.includes(v))); - // } } const template = { id: 0, @@ -4147,11 +4376,15 @@ function primaryFN() { const eframe = make('td', 'install-btn'); const uframe = make('td', 'mujs-uframe'); const fdaily = make('td', 'mujs-list', { - textContent: ujs.daily_installs + textContent: ujs.daily_installs, + dataset: { + name: 'daily_installs' + } }); const fupdated = make('td', 'mujs-list', { textContent: language.toDate(ujs.code_updated_at), dataset: { + name: 'code_updated_at', value: new Date(ujs.code_updated_at).toISOString() } }); @@ -4179,17 +4412,22 @@ function primaryFN() { const fcreated = make('mu-js', 'mujs-list', { textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`, dataset: { + name: 'created_at', value: new Date(ujs.created_at).toISOString() } }); const flicense = make('mu-js', 'mujs-list', { title: ujs.license ?? i18n$('no_license'), textContent: `${i18n$('license')}: ${ujs.license ?? i18n$('no_license')}`, - style: - 'text-overflow: ellipsis; overflow: hidden; white-space: nowrap; width: fit-content; max-width: 20em;' + dataset: { + name: 'license' + } }); const ftotal = make('mu-js', 'mujs-list', { - textContent: `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}` + textContent: `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}`, + dataset: { + name: 'total_installs' + } }); const fratings = make('mu-js', 'mujs-list', { title: i18n$('ratings'), @@ -4199,6 +4437,7 @@ function primaryFN() { title: i18n$('good'), textContent: ujs.good_ratings, dataset: { + name: 'good_ratings', el: 'good' } }); @@ -4206,6 +4445,7 @@ function primaryFN() { title: i18n$('ok'), textContent: ujs.ok_ratings, dataset: { + name: 'ok_ratings', el: 'ok' } }); @@ -4213,6 +4453,7 @@ function primaryFN() { title: i18n$('bad'), textContent: ujs.bad_ratings, dataset: { + name: 'bad_ratings', el: 'bad' } }); @@ -4232,7 +4473,7 @@ function primaryFN() { } }); const scriptDownload = make('mu-jsbtn', { - innerHTML: `${iconSVG.load('install')} ${i18n$('saveFile')}`, + innerHTML: `${iconSVG.load('download')} ${i18n$('saveFile')}`, dataset: { command: 'download-userjs', userjs: ujs.id, @@ -4254,23 +4495,22 @@ function primaryFN() { wrap: 'soft' }); const loadCode = make('mu-jsbtn', { - innerHTML: `${iconSVG.load('search')} ${i18n$('preview_code')}`, + innerHTML: `${iconSVG.load('code')} ${i18n$('preview_code')}`, dataset: { command: 'load-userjs', userjs: ujs.id } }); - if (engine) { - tr.dataset.engine = engine; - // if (engine.includes('fork')) { - // fdaily.dataset.command = 'open-tab'; - // fdaily.dataset.webpage = `${ujs.url}/stats`; - // fupdated.dataset.command = 'open-tab'; - // fupdated.dataset.webpage = `${ujs.url}/versions`; - // } - if (!engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.url)) { - tr.dataset.good = 'upsell'; + const loadMetadata = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('code')} Metadata`, + dataset: { + command: 'load-header', + userjs: ujs.id } + }); + tr.dataset.engine = engine; + if (!engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.url)) { + tr.dataset.good = 'upsell'; } for (const u of ujs.users) { const user = make('mujs-a', { @@ -4287,7 +4527,7 @@ function primaryFN() { } uframe.append(user); } - if (engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.id)) { + if (cfg.recommend.others && goodUserJS.includes(ujs.id)) { tr.dataset.good = 'upsell'; } eframe.append(scriptInstall); @@ -4295,53 +4535,55 @@ function primaryFN() { jsInfo.append(ftotal, ratings, fver, fcreated); mkList(i18n$('code_size'), { list: ujs._mujs.code.code_size, - type: 'size', + type: 'code_size', root: jsInfo }); jsInfoB.append(flicense); + const data_meta = ujs._mujs.code?.data_meta ?? {}; mkList(i18n$('antifeatures'), { - list: ujs._mujs.code.antifeatures, + list: data_meta.antifeatures ?? [], type: 'antifeatures', root: jsInfoB }); mkList(i18n$('applies_to'), { - list: ujs._mujs.code.match, - type: 'match', + list: ujs._mujs.code?.data_names ?? [], + type: 'data_names', root: jsInfoB }); mkList('@grant', { - list: ujs._mujs.code.grant, + list: data_meta.grant ?? [], type: 'grant', root: jsInfoB }); mkList('@require', { - list: ujs._mujs.code.meta?.require, + list: data_meta.require, type: 'require', root: jsInfoB }); - const script_resources = ujs._mujs.code.meta?.resource; mkList('@resource', { - list: isNull(script_resources) ? [] : [script_resources], + list: isNull(data_meta.resource) ? [] : [data_meta.resource], type: 'resource', root: jsInfoB }); fmore.append(jsInfo, jsInfoB); - fBtns.append(scriptDownload, loadCode); + fBtns.append(scriptDownload, loadCode, loadMetadata); fname.append(ftitle, fdesc, fmore, fBtns, codeArea); - const code_data = ujs._mujs.code.data; - if (code_data) { - const code_obj = new ParseUserJS(code_data); - codeArea.value = code_obj.get_code_block(); - } + const loadPage = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('pager')} Page`, + dataset: { + command: 'load-page', + userjs: ujs.id + } + }); + fBtns.append(loadPage); if (ujs._mujs.code?.translated) tr.classList.add('translated'); for (const e of [fname, uframe, fdaily, fupdated, eframe]) tr.append(e); ujs._mujs.root = tr; - - return tr; + return ujs._mujs.root; }; // #endregion const loadFilters = () => { @@ -4399,12 +4641,19 @@ function primaryFN() { this.build = this.build.bind(this); this.toArr = this.toArr.bind(this); this.groupBy = this.groupBy.bind(this); + this.dispatch = this.dispatch.bind(this); this.sortRecords = this.sortRecords.bind(this); if (isEmpty(hostname)) hostname = container.host; this.engines = cfg.engines; this.host = hostname; } + dispatch(ujs) { + const { CustomEvent } = safeSelf(); + const customEvent = new CustomEvent('updateditem', { detail: ujs }); + main.dispatchEvent(customEvent); + } + set host(hostname) { this.intHost = hostname; @@ -4443,7 +4692,7 @@ function primaryFN() { build() { try { container.refresh(); - const { blacklisted, engines, host, toArr } = this; + const { blacklisted, engines, host, toArr, dispatch } = this; if (blacklisted || isEmpty(engines)) { container.opacityMin = '0'; mainframe.style.opacity = container.opacityMin; @@ -4477,92 +4726,59 @@ function primaryFN() { host }, code: { - antifeatures: [], - grant: [], - match: [], meta: {}, request: async function (translate = false, code_url) { - if (this.data) { + if (this.data_code_block) { return this; } - this.data = ''; + code_url = code_url ?? d.code_url; /** @type { string } */ - const code = await Network.req(code_url ?? d.code_url, 'GET', 'text').catch( - showError - ); + const code = await Network.req(code_url, 'GET', 'text').catch(showError); if (typeof code !== 'string') { return this; } - Object.assign(this, { - data: code, - code_size: [Network.format(code.length)] - }); - const grantSet = new Set(); - const afSet = new Set(); - const code_obj = new ParseUserJS(code); - const meta = code_obj.parse_meta(); - const applies_to_names = code_obj.calculate_applies_to_names(); - + const code_obj = new ParseUserJS(code, /\.user\.css/.test(code_url)); + const { data_meta } = code_obj; if (translate) { for (const k of userjs.pool.keys()) { - if (meta[`name:${k}`]) { + if (data_meta[`name:${k}`]) { Object.assign(obj, { - name: meta[`name:${k}`] + name: data_meta[`name:${k}`] }); this.translated = true; } - if (meta[`description:${k}`]) { + if (data_meta[`description:${k}`]) { Object.assign(obj, { - description: meta[`description:${k}`] + description: data_meta[`description:${k}`] }); this.translated = true; } } } - - for (const [key, value] of Object.entries(meta)) { - if (/grant/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (grantSet.has(v)) { - continue; - } - grantSet.add(v); - } - } else if (/antifeature/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (afSet.has(v)) { - continue; - } - afSet.add(v); - } - } - } - if (typeof meta.require === 'string') { - const s = meta.require; - meta.require = [s]; + if (Array.isArray(data_meta.grant)) { + data_meta.grant = union(data_meta.grant); } - if (meta.resource) { + if (data_meta.resource) { const obj = {}; - if (typeof meta.resource === 'string') { - const reg = /(.+)\s+(.+)/.exec(meta.resource); + if (typeof data_meta.resource === 'string') { + const reg = /(.+)\s+(.+)/.exec(data_meta.resource); if (reg) { obj[reg[1].trim()] = reg[2]; } } else { - for (const r of meta.resource) { + for (const r of data_meta.resource) { const reg = /(.+)\s+(http.+)/.exec(r); if (reg) { obj[reg[1].trim()] = reg[2]; } } } - meta.resource = obj; + data_meta.resource = obj; } Object.assign(this, { - meta, - match: applies_to_names, - grant: [...grantSet], - antifeatures: [...afSet] + code_size: [Network.format(code.length)], + meta: data_meta, + ...code_obj }); return this; @@ -4637,8 +4853,13 @@ function primaryFN() { finalList = union(hds, filterLang); for (const ujs of finalList) { - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + if ( + !ujs._mujs.code.data_code_block && + (cfg.preview.code || cfg.preview.metadata) + ) { + ujs._mujs.code.request().then(() => { + dispatch(ujs); + }); } createjs(ujs, engine.name); } @@ -4654,7 +4875,8 @@ function primaryFN() { } const selected = htmlDocument.documentElement; if (/openuserjs/gi.test(engine.name)) { - for (const i of qsA('.col-sm-8 .tr-link', selected)) { + const col = qsA('.col-sm-8 .tr-link', selected) ?? []; + for (const i of col) { while (isNull(qs('.script-version', i))) { await new Promise((resolve) => requestAnimationFrame(resolve)); } @@ -4683,8 +4905,13 @@ function primaryFN() { if (bsFilter.match(ujs)) { continue; } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + if ( + !ujs._mujs.code.data_code_block && + (cfg.preview.code || cfg.preview.metadata) + ) { + ujs._mujs.code.request().then(() => { + dispatch(ujs); + }); } createjs(ujs, engine.name); } @@ -4693,7 +4920,7 @@ function primaryFN() { showError(ex); } }; - const gitFN = async (data) => { + const gitFN = (data) => { try { if (isBlank(data.items)) { showError('Invalid data received from the server, TODO fix this'); @@ -4701,14 +4928,14 @@ function primaryFN() { } for (const r of data.items) { const ujs = _mujs({ - name: r.name, + id: r.repository.id ?? r.id ?? 0, + name: r.repository.name ?? r.name, description: isEmpty(r.repository.description) ? i18n$('no_license') : r.repository.description, - url: r.html_url, + url: r.repository.html_url, code_url: r.html_url.replace(/\/blob\//g, '/raw/'), - code_updated_at: r.commit || Date.now(), - total_installs: r.score, + page_url: `${r.repository.url}/contents/README.md`, users: [ { name: r.repository.owner.login, @@ -4716,11 +4943,30 @@ function primaryFN() { } ] }); - if (bsFilter.match(ujs)) { - continue; - } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + // if (bsFilter.match(ujs)) { + // continue; + // } + Network.req(r.repository.url, 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).then((repository) => { + ujs.code_updated_at = r.commit || repository.updated_at || Date.now(); + ujs.created_at = repository.created_at; + ujs.daily_installs = repository.watchers_count ?? 0; + ujs.good_ratings = repository.stargazers_count ?? 0; + if (repository.license?.name) ujs.license = repository.license.name; + dispatch(ujs); + }); + if ( + !ujs._mujs.code.data_code_block && + (cfg.preview.code || cfg.preview.metadata) + ) { + ujs._mujs.code.request().then(() => { + dispatch(ujs); + }); } createjs(ujs, engine.name); } @@ -4847,6 +5093,8 @@ function primaryFN() { command: 'reset' } }); + cbtn.append(resetbtn, savebtn); + const makesection = (name, tag) => { tag = tag ?? i18n$('no_license'); name = name ?? i18n$('no_license'); @@ -4871,7 +5119,7 @@ function primaryFN() { } const cmd = target.dataset.command; if (cmd === tag) { - const a = qsA(`label[data-${tag}]`, sec); + const a = qsA(`[data-${tag}]`, sec); if (dom.cl.has(a, 'hidden')) { dom.cl.remove(a, 'hidden'); } else { @@ -4885,133 +5133,24 @@ function primaryFN() { cfgpage.append(sec); return sec; }; - const sections = { general: makesection('General', 'general'), load: makesection('Automation', 'load'), list: makesection('List', 'list'), filters: makesection('List Filters', 'filters'), blacklist: makesection('Blacklist (WIP)', 'blacklist'), - // engine: makesection('Search Engine', 'engine'), - theme: makesection('Theme Colors', 'theme') - }; - - const makerow = (desc, type = null, nm, attrs = {}) => { - desc = desc ?? i18n$('no_license'); - nm = nm ?? i18n$('no_license'); - const sec = make('mujs-section', { - dataset: { - name: nm - } - }); - const lb = make('label'); - const divDesc = make('mu-js', { - textContent: desc - }); - lb.append(divDesc); - sec.append(lb); - cfgpage.append(sec); - if (isNull(type)) { - return lb; - } - const inp = make('input', { - type, - dataset: { - name: nm - }, - ...attrs - }); - if (!cfgMap.has(nm)) { - cfgMap.set(nm, inp); - } - if (type === 'checkbox') { - const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', { - onclick() { - inp.dispatchEvent(new MouseEvent('click')); - } - }); - inlab.append(inp, la); - lb.append(inlab); - if (nm.includes('-')) { - return inp; - } - if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { - const engine = cfg.engines.find((engine) => engine.name === nm); - if (engine) { - inp.checked = engine.enabled; - inp.dataset.engine = engine.name; - ael(inp, 'change', (evt) => { - container.unsaved = true; - container.rebuild = true; - engine.enabled = evt.target.checked; - }); - - if (engine.query) { - const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); - const urlInp = make('input', { - type: 'text', - defaultValue: '', - value: decodeURIComponent(engine.query) ?? '', - placeholder: decodeURIComponent(d.query) ?? '', - dataset: { - name: nm, - engine: engine.name - }, - onchange(evt) { - container.unsaved = true; - container.rebuild = true; - try { - engine.query = encodeURIComponent(new URL(evt.target.value).toString()); - } catch (ex) { - err(ex); - } - } - }); - sec.append(urlInp); - } - if (engine.name === 'github') { - const ghToken = make('input', { - type: 'text', - defaultValue: '', - value: engine.token ?? '', - placeholder: 'Paste Access Token', - dataset: { - engine: 'github-token' - }, - onchange(evt) { - container.unsaved = true; - container.rebuild = true; - engine.token = evt.target.value; - } - }); - sec.append(ghToken); - cfgMap.set('github-token', ghToken); - } - } - } else { - inp.checked = cfg[nm]; - ael(inp, 'change', (evt) => { - container.unsaved = true; - if (/filterlang/i.test(nm)) { - container.rebuild = true; - } - cfg[nm] = evt.target.checked; - }); - } - } else { - lb.append(inp); - } - return inp; + engine: makesection('Search Engines', 'engine'), + theme: makesection('Theme Colors', 'theme'), + exp: makesection('Import / Export', 'exp') }; - const mkSection = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { - cfgMap.set(text, value); + const makeRow = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { const lb = make('label', 'sub-section hidden', { textContent: text, dataset: { [tag]: text } }); + cfgMap.set(text, value); if (type === 'select') { const inp = make('select', { dataset: { @@ -5042,6 +5181,10 @@ function primaryFN() { ...attrs }); + if (tag === 'engine') { + inp.dataset.name = value; + } + if (sections[tag]) { sections[tag].append(lb); } @@ -5081,6 +5224,61 @@ function primaryFN() { cfg[value] = evt.target.checked; } }); + + if (tag === 'engine') { + const engine = cfg.engines.find((engine) => engine.name === value); + if (engine) { + inp.checked = engine.enabled; + inp.dataset.engine = engine.name; + ael(inp, 'change', (evt) => { + container.unsaved = true; + container.rebuild = true; + engine.enabled = evt.target.checked; + }); + + if (engine.query) { + const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); + const urlInp = make('input', { + type: 'text', + defaultValue: '', + value: decodeURIComponent(engine.query) ?? '', + placeholder: decodeURIComponent(d.query) ?? '', + dataset: { + name: nm, + engine: engine.name + }, + onchange(evt) { + container.unsaved = true; + container.rebuild = true; + try { + engine.query = encodeURIComponent(new URL(evt.target.value).toString()); + } catch (ex) { + err(ex); + } + } + }); + lb.append(urlInp); + } + if (engine.name === 'github') { + const ghToken = make('input', { + type: 'text', + defaultValue: '', + value: engine.token ?? '', + placeholder: 'Paste Access Token', + dataset: { + engine: 'github-token' + }, + onchange(evt) { + container.unsaved = true; + container.rebuild = true; + engine.token = evt.target.value; + } + }); + lb.append(ghToken); + cfgMap.set('github-token', ghToken); + } + } + } } else { if (type === 'text') { inp.defaultValue = ''; @@ -5094,11 +5292,11 @@ function primaryFN() { return lb; }; if (isGM) { - mkSection(i18n$('userjs_sync'), 'cache'); - mkSection(i18n$('userjs_autoinject'), 'autoinject', 'checkbox', 'load'); + makeRow(i18n$('userjs_sync'), 'cache'); + makeRow(i18n$('userjs_autoinject'), 'autoinject', 'checkbox', 'load'); } - mkSection(i18n$('redirect'), 'sleazyredirect'); - mkSection(`${i18n$('dtime')} (ms)`, 'time', 'number', 'general', { + makeRow(i18n$('redirect'), 'sleazyredirect'); + makeRow(`${i18n$('dtime')} (ms)`, 'time', 'number', 'general', { defaultValue: 10000, value: cfg.time, min: 0, @@ -5126,34 +5324,35 @@ function primaryFN() { } }); - mkSection(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); - mkSection(i18n$('userjs_fullscreen'), 'autoexpand', 'checkbox', 'load', { + makeRow(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); + makeRow(i18n$('userjs_fullscreen'), 'autoexpand', 'checkbox', 'load', { onchange(e) { if (e.target.checked) { dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('collapse')); } else { dom.cl.remove([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('expand')); } } }); - mkSection('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); + makeRow('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); - mkSection('Default Sort', 'autoSort', 'select', 'list'); - mkSection(i18n$('filter'), 'filterlang', 'checkbox', 'list'); - mkSection(i18n$('preview_code'), 'codePreview', 'checkbox', 'list'); - mkSection('Recommend author', 'recommend-author', 'checkbox', 'list'); - mkSection('Recommend scripts', 'recommend-others', 'checkbox', 'list'); + makeRow('Default Sort', 'autoSort', 'select', 'list'); + makeRow(i18n$('filter'), 'filterlang', 'checkbox', 'list'); + makeRow(i18n$('preview_code'), 'preview-code', 'checkbox', 'list'); + makeRow('Preview Metadata', 'preview-metadata', 'checkbox', 'list'); + makeRow('Recommend author', 'recommend-author', 'checkbox', 'list'); + makeRow('Recommend scripts', 'recommend-others', 'checkbox', 'list'); for (const [k, v] of Object.entries(cfg.filters)) { - mkSection(v.name, `filters-${k}`, 'checkbox', 'filters'); + makeRow(v.name, `filters-${k}`, 'checkbox', 'filters'); } - makerow('Greasy Fork', 'checkbox', 'greasyfork'); - makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); - makerow('Open UserJS', 'checkbox', 'openuserjs'); - makerow('GitHub API', 'checkbox', 'github'); + makeRow('Greasy Fork', 'greasyfork', 'checkbox', 'engine'); + makeRow('Sleazy Fork', 'sleazyfork', 'checkbox', 'engine'); + makeRow('Open UserJS', 'openuserjs', 'checkbox', 'engine'); + makeRow('GitHub API', 'github', 'checkbox', 'engine'); for (const [k, v] of Object.entries(cfg.theme)) { const lb = make('label', 'hidden', { @@ -5207,6 +5406,66 @@ function primaryFN() { sections.theme.append(lb); } + // const blacklist = make('textarea', { + // dataset: { + // name: 'blacklist' + // }, + // rows: '10', + // autocomplete: false, + // spellcheck: false, + // wrap: 'soft', + // value: JSON.stringify(cfg.blacklist, null, ' '), + // oninput(evt) { + // let isvalid = true; + // try { + // cfg.blacklist = JSON.parse(evt.target.value); + // isvalid = true; + // } catch (ex) { + // err(ex); + // isvalid = false; + // } finally { + // if (isvalid) { + // dom.cl.remove(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', false); + // } else { + // dom.cl.add(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', true); + // } + // } + // } + // }); + // cfgMap.set('blacklist', blacklist); + // const addList = make('mujs-add', { + // textContent: '+', + // dataset: { + // command: 'new-list' + // } + // }); + // const n = make('input', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Name', + // }); + // const inpValue = make('input', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Value', + // }); + // const label = make('label', 'new-list hidden', { + // dataset: { + // blacklist: 'new-list' + // } + // }); + // label.append(n, inpValue, addList); + // listSec.append(label); + // ael(addList, 'click', () => { + // if (isEmpty(n.value) || isEmpty(inpValue.value)) { + // return + // }; + // createList(n.value, n.value, inpValue.value); + // }); const createList = (key, v = '', disabled = false, type = 'String') => { let txt = key; if (typeof key === 'string') { @@ -5292,72 +5551,50 @@ function primaryFN() { lb.append(inp, selType); sections.blacklist.append(lb); }; - // const blacklist = make('textarea', { - // dataset: { - // name: 'blacklist' - // }, - // rows: '10', - // autocomplete: false, - // spellcheck: false, - // wrap: 'soft', - // value: JSON.stringify(cfg.blacklist, null, ' '), - // oninput(evt) { - // let isvalid = true; - // try { - // cfg.blacklist = JSON.parse(evt.target.value); - // isvalid = true; - // } catch (ex) { - // err(ex); - // isvalid = false; - // } finally { - // if (isvalid) { - // dom.cl.remove(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', false); - // } else { - // dom.cl.add(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', true); - // } - // } - // } - // }); - // cfgMap.set('blacklist', blacklist); - // const addList = make('mujs-add', { - // textContent: '+', - // dataset: { - // command: 'new-list' - // } - // }); - // const n = make('input', { - // type: 'text', - // defaultValue: '', - // value: '', - // placeholder: 'Name', - // }); - // const inpValue = make('input', { - // type: 'text', - // defaultValue: '', - // value: '', - // placeholder: 'Value', - // }); - // const label = make('label', 'new-list hidden', { - // dataset: { - // blacklist: 'new-list' - // } - // }); - // label.append(n, inpValue, addList); - // listSec.append(label); - // ael(addList, 'click', () => { - // if (isEmpty(n.value) || isEmpty(inpValue.value)) { - // return - // }; - // createList(n.value, n.value, inpValue.value); - // }); - for (const key of cfg.blacklist) { createList(key); } - cbtn.append(resetbtn, savebtn); + const transfers = { + export: { + cfg: make('mujs-btn', 'mujs-export sub-section hidden', { + textContent: i18n$('export_config'), + dataset: { + command: 'export-cfg', + exp: 'export-cfg' + } + }), + theme: make('mujs-btn', 'mujs-export sub-section hidden', { + textContent: i18n$('export_theme'), + dataset: { + command: 'export-theme', + exp: 'export-theme' + } + }) + }, + import: { + cfg: make('mujs-btn', 'mujs-import sub-section hidden', { + textContent: i18n$('import_config'), + dataset: { + command: 'import-cfg', + exp: 'import-cfg' + } + }), + theme: make('mujs-btn', 'mujs-import sub-section hidden', { + textContent: i18n$('import_theme'), + dataset: { + command: 'import-theme', + exp: 'import-theme' + } + }) + } + }; + for (const value of Object.values(transfers)) { + for (const v of Object.values(value)) { + sections.exp.append(v); + } + } + cfgpage.append(cbtn); }; // #endregion @@ -5384,7 +5621,7 @@ function primaryFN() { dom.cl.add(mainframe, 'hidden'); if (cfg.autoexpand) { dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('collapse')); } if (dom.cl.has(mainframe, 'error')) { tab.create('mujs:settings'); @@ -5512,11 +5749,8 @@ function primaryFN() { for (const v of cacheValues) { if (v.name && v.name.match(reg)) finds.add(v._mujs.root); if (v.description && v.description.match(reg)) finds.add(v._mujs.root); - const code_data = v._mujs.code.data; - if (code_data) { - const code_obj = new ParseUserJS(code_data); - const meta = code_obj.parse_meta(code_data); - for (const key of Object.keys(meta)) { + if (v._mujs.code.data_meta) { + for (const key of Object.keys(v._mujs.code.data_meta)) { if (/name|desc/i.test(key) && key.match(reg)) finds.add(v._mujs.root); } } diff --git a/package.json b/package.json index bb6b904..3b7f4ba 100644 --- a/package.json +++ b/package.json @@ -80,8 +80,8 @@ "sourceDir": "./build/firefox" }, "engines": { - "node": ">=18", - "pnpm": ">=9" + "node": ">=20", + "pnpm": ">=10" }, "packageManager": "pnpm@10.3.0+sha512.ee592eda8815a8a293c206bb0917c4bb0ff274c50def7cbc17be05ec641fc2d1b02490ce660061356bd0d126a4d7eb2ec8830e6959fb8a447571c631d5a2442d", "pnpm": { diff --git a/src/UserJS/main.js b/src/UserJS/main.js index 87c6905..941cb25 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -50,6 +50,65 @@ const log = (...msg) => { */ let cfg = {}; +// #region Validators +/** + * @type { import("../typings/types.d.ts").objToStr } + */ +const objToStr = (obj) => Object.prototype.toString.call(obj); +/** + * @type { import("../typings/types.d.ts").isRegExp } + */ +const isRegExp = (obj) => { + const s = objToStr(obj); + return s.includes('RegExp'); +}; +/** + * @type { import("../typings/types.d.ts").isElem } + */ +const isElem = (obj) => { + const s = objToStr(obj); + return s.includes('Element'); +}; +/** + * @type { import("../typings/types.d.ts").isObj } + */ +const isObj = (obj) => { + const s = objToStr(obj); + return s.includes('Object'); +}; +/** + * @type { import("../typings/types.d.ts").isFN } + */ +const isFN = (obj) => { + const s = objToStr(obj); + return s.includes('Function'); +}; +/** + * @type { import("../typings/types.d.ts").isNull } + */ +const isNull = (obj) => { + return Object.is(obj, null) || Object.is(obj, undefined); +}; +/** + * @type { import("../typings/types.d.ts").isBlank } + */ +const isBlank = (obj) => { + return ( + (typeof obj === 'string' && Object.is(obj.trim(), '')) || + ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || + (Array.isArray(obj) && Object.is(obj.length, 0)) || + (isObj(obj) && Object.is(Object.keys(obj).length, 0)) + ); +}; +/** + * @type { import("../typings/types.d.ts").isEmpty } + */ +const isEmpty = (obj) => { + return isNull(obj) || isBlank(obj); +}; +// #endregion + +// #region Globals /** * https://github.com/zloirock/core-js/blob/master/packages/core-js/internals/global-this.js * @returns {typeof globalThis} @@ -69,7 +128,6 @@ function globalWin() { Function('return this')() ); } - /** @type { import("../typings/UserJS.d.ts").safeSelf } */ function safeSelf() { if (userjs.safeSelf) { @@ -79,6 +137,7 @@ function safeSelf() { /** @type { import("../typings/UserJS.d.ts").safeHandles } */ const safe = { XMLHttpRequest: g.XMLHttpRequest, + CustomEvent: g.CustomEvent, createElement: g.document.createElement.bind(g.document), createElementNS: g.document.createElementNS.bind(g.document), createTextNode: g.document.createTextNode.bind(g.document), @@ -115,9 +174,20 @@ function safeSelf() { } } }; + for (const [k, v] of Object.entries(safe)) { + if (k === 'scheduler') { + continue; + } else if (k === 'navigator') { + continue; + } else if (isFN(v)) { + continue; + } + err({ message: `Safe handles "${k}" returned "${v}"`, cause: 'safeSelf' }); + } userjs.safeSelf = safe; return userjs.safeSelf; } +// #endregion const BLANK_PAGE = 'about:blank'; // Lets highlight me :) @@ -212,12 +282,15 @@ const DEFAULT_CONFIG = { autoSort: 'daily_installs', clearTabCache: true, cache: true, - codePreview: false, autoexpand: false, filterlang: false, sleazyredirect: false, time: 10000, blacklist: ['userjs-local', 'userjs-finance', 'userjs-social', 'userjs-unsupported'], + preview: { + code: false, + metadata: false + }, engines: [ { enabled: true, @@ -369,61 +442,6 @@ const qsA = (selectors, root) => { } return []; }; -/** - * @type { import("../typings/types.d.ts").objToStr } - */ -const objToStr = (obj) => Object.prototype.toString.call(obj); -/** - * @type { import("../typings/types.d.ts").isRegExp } - */ -const isRegExp = (obj) => { - const s = objToStr(obj); - return s.includes('RegExp'); -}; -/** - * @type { import("../typings/types.d.ts").isElem } - */ -const isElem = (obj) => { - const s = objToStr(obj); - return s.includes('Element'); -}; -/** - * @type { import("../typings/types.d.ts").isObj } - */ -const isObj = (obj) => { - const s = objToStr(obj); - return s.includes('Object'); -}; -/** - * @type { import("../typings/types.d.ts").isFN } - */ -const isFN = (obj) => { - const s = objToStr(obj); - return s.includes('Function'); -}; -/** - * @type { import("../typings/types.d.ts").isNull } - */ -const isNull = (obj) => { - return Object.is(obj, null) || Object.is(obj, undefined); -}; -/** - * @type { import("../typings/types.d.ts").isBlank } - */ -const isBlank = (obj) => { - return ( - (typeof obj === 'string' && Object.is(obj.trim(), '')) || - ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || - (Array.isArray(obj) && Object.is(obj.length, 0)) || - (isObj(obj) && Object.is(Object.keys(obj).length, 0)) - ); -}; -/** - * @type { import("../typings/types.d.ts").isEmpty } - */ -const isEmpty = (obj) => { - return isNull(obj) || isBlank(obj); -}; /** * @type { import("../typings/types.d.ts").normalizeTarget } */ @@ -627,61 +645,57 @@ class Memorize { const memory = new Memorize(); //#region Icon SVGs const iconSVG = { - cfg: { - viewBox: '0 0 24 24', - html: '' - }, close: { - viewBox: '0 0 24 24', - html: '' + viewBox: '0 0 384 512', + html: '' }, - filter: { - viewBox: '0 0 24 24', - html: '' + code: { + viewBox: '0 0 640 512', + html: '' }, - fsClose: { - viewBox: '0 0 24 24', - html: ' ' + collapse: { + viewBox: '0 0 448 512', + html: '' }, - fsOpen: { - viewBox: '0 0 24 24', - html: ' ' + download: { + viewBox: '0 0 384 512', + html: '' }, - fullscreen: { - viewBox: '0 0 96 96', - html: '' + expand: { + viewBox: '0 0 448 512', + html: '' }, - gf: { - viewBox: '0 0 510.4 510.4', - html: '' + gear: { + viewBox: '0 0 512 512', + html: '' }, - gh: { - viewBox: '0 0 16 16', - html: '' + github: { + viewBox: '0 0 496 512', + html: '' }, - hide: { - viewBox: '0 0 24 24', - html: ' ' + globe: { + viewBox: '0 0 512 512', + html: '' }, install: { - viewBox: '0 0 16 16', - html: '' + viewBox: '0 0 512 512', + html: '' }, issue: { - viewBox: '0 0 24 24', - html: '' + viewBox: '0 0 512 512', + html: '' }, - nav: { - viewBox: '0 0 24 24', - html: ' ' + minus: { + viewBox: '0 0 448 512', + html: '' }, - plus: { - viewBox: '0 0 24 24', - html: '' + nav: { + viewBox: '0 0 448 512', + html: '' }, - search: { - viewBox: '0 0 24 24', - html: '' + pager: { + viewBox: '0 0 512 512', + html: '' }, verified: { viewBox: '0 0 56 56', @@ -690,9 +704,9 @@ const iconSVG = { html: '' }, refresh: { - viewBox: '0 0 1024 1024', + viewBox: '0 0 512 512', fill: 'currentColor', - html: '' + html: '' }, load(type, container) { const { createElementNS } = safeSelf(); @@ -1036,6 +1050,7 @@ const Counter = { } } }; + // #region Container /** * @type { import("../typings/UserJS.d.ts").Container } @@ -1101,11 +1116,7 @@ class Container { } }); if (this.supported) { - this.shadowRoot = this.frame.attachShadow({ - mode: 'closed' - // clonable: false, - // delegatesfocus: false - }); + this.shadowRoot = this.frame.attachShadow({ mode: 'closed' }); this.ready = true; } this.cache = memory.maps.container; @@ -1124,6 +1135,7 @@ class Container { } set(delay, reason) { + const { setTimeout } = safeSelf(); return new Promise((resolve, reject) => { const id = setTimeout(() => { Object.is(reason, null) || Object.is(reason, undefined) ? resolve() : reject(reason); @@ -1134,6 +1146,7 @@ class Container { } clear(...ids) { + const { clearTimeout } = safeSelf(); this.ids = this.ids.filter((id) => { if (ids.includes(id)) { clearTimeout(id); @@ -1199,7 +1212,7 @@ class Container { Counter.cnt.total.root = this.mainbtn; for (const engine of cfg.engines) this.countframe.append(Counter.set(engine)); - const { cfgpage, table, exBtn, supported, frame, refresh, cache, urlBar, host } = this; + const { cfgpage, table, supported, frame, refresh, cache, urlBar, host } = this; class Tabs { /** @@ -1244,7 +1257,7 @@ class Container { return; } if (hostname.match(this.protoReg)[1] === 'settings') { - dom.cl.remove([cfgpage, exBtn], 'hidden'); + dom.cl.remove(cfgpage, 'hidden'); dom.cl.add(table, 'hidden'); if (!supported) { dom.attr(frame, 'style', 'height: 100%;'); @@ -1257,7 +1270,7 @@ class Container { */ active(tab, build = true) { if (!this.pool.has(tab)) this.pool.add(tab); - dom.cl.add([cfgpage, exBtn], 'hidden'); + dom.cl.add(cfgpage, 'hidden'); dom.cl.remove(table, 'hidden'); dom.cl.remove([...this.pool], 'active'); dom.cl.add(tab, 'active'); @@ -1339,8 +1352,7 @@ class Container { this.tab.create(host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => - tr.children[idx].dataset.value || tr.children[idx].innerText || tr.children[idx].textContent; + const getCellValue = (tr, idx) => tr.children[idx].dataset.value; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) @@ -1387,43 +1399,18 @@ class Container { this.tbody = make('mujs-body'); this.cfgpage = make('mujs-row', 'mujs-cfg hidden'); this.btnframe = make('mujs-column', 'btn-frame'); - this.exBtn = make('mujs-column', 'mujs-sty-flex hidden'); this.fsearch = make('mujs-btn', 'hidden'); - this.exportCFG = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_config'), - dataset: { - command: 'export-cfg' - } - }); - this.importCFG = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_config'), - dataset: { - command: 'import-cfg' - } - }); - this.exportTheme = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_theme'), - dataset: { - command: 'export-theme' - } - }); - this.importTheme = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_theme'), - dataset: { - command: 'import-theme' - } - }); this.btnHandles = make('mujs-column', 'btn-handles'); this.btnHide = make('mujs-btn', 'hide-list', { title: i18n$('min'), - innerHTML: iconSVG.load('hide'), + innerHTML: iconSVG.load('minus'), dataset: { command: 'hide-list' } }); this.btnfullscreen = make('mujs-btn', 'fullscreen', { title: i18n$('max'), - innerHTML: iconSVG.load('fullscreen'), + innerHTML: iconSVG.load('expand'), dataset: { command: 'fullscreen' } @@ -1439,7 +1426,7 @@ class Container { }); this.btncfg = make('mujs-btn', 'settings hidden', { title: 'Settings', - innerHTML: iconSVG.load('cfg'), + innerHTML: iconSVG.load('gear'), dataset: { command: 'settings' } @@ -1450,7 +1437,7 @@ class Container { ? $info.script.version : $info.script.version.slice(0, 5) })`, - innerHTML: iconSVG.load('gh'), + innerHTML: iconSVG.load('github'), dataset: { command: 'open-tab', webpage: $info.script.namespace @@ -1466,7 +1453,7 @@ class Container { }); this.btngreasy = make('mujs-btn', 'greasy hidden', { title: 'Greasy Fork', - innerHTML: iconSVG.load('gf'), + innerHTML: iconSVG.load('globe'), dataset: { command: 'open-tab', webpage: 'https://greasyfork.org/scripts/421603' @@ -1507,17 +1494,30 @@ class Container { } ]); // #endregion - - this.btnHandles.append(this.btnHide, this.btnfullscreen, this.closebtn); - this.btnframe.append(this.btnhome, this.btngreasy, this.btnissue, this.btncfg, this.btnnav); + if (isMobile) { + dom.cl.add([this.btnHide, this.btnfullscreen, this.closebtn], 'hidden'); + this.btnframe.append( + this.btnHide, + this.btnfullscreen, + this.closebtn, + this.btnhome, + this.btngreasy, + this.btnissue, + this.btncfg, + this.btnnav + ); + } else { + this.btnHandles.append(this.btnHide, this.btnfullscreen, this.closebtn); + this.btnframe.append(this.btnhome, this.btngreasy, this.btnissue, this.btncfg, this.btnnav); + } this.toolbar.append(this.btnHandles); this.urlContainer.append(this.urlBar); this.header.append(this.urlContainer, this.rateContainer, this.countframe, this.btnframe); this.tbody.append(this.table, this.cfgpage); this.main.append(this.toolbar, this.header, this.tbody, this.footer, this.promptElem); this.mainframe.append(this.mainbtn); - this.exBtn.append(this.importCFG, this.importTheme, this.exportCFG, this.exportTheme); - this.header.append(this.exBtn); + // this.exBtn.append(this.importCFG, this.importTheme, this.exportCFG, this.exportTheme); + // this.header.append(this.exBtn); this.root.append(this.mainframe, this.main); return true; @@ -1816,10 +1816,6 @@ function primaryFN() { fsearch, btnfullscreen, main, - btncfg, - btnhome, - btnissue, - btngreasy, tab, showError } = container; @@ -1864,8 +1860,75 @@ function primaryFN() { installLink.remove(); await init(); }; + const applyTo = (ujs, name, elem, root) => { + const n = ujs._mujs.code[name] ?? ujs._mujs.code.data_meta[name]; + if (isEmpty(n)) { + const el = make('mujs-a', { + textContent: i18n$('listing_none') + }); + elem.append(el); + return; + } + dom.prop(elem, 'innerHTML', ''); + dom.cl.remove(root, 'hidden'); + if (isObj(n)) { + if (name === 'resource') { + for (const [k, v] of Object.entries(n)) { + const el = make('mujs-a', { + textContent: k ?? 'ERROR' + }); + if (v.startsWith('http')) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = v; + } + elem.append(el); + } + } else { + const el = make('mujs-a', { + textContent: n.text + }); + if (n.domain) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = `https://${n.text}`; + } + elem.append(el); + } + } else if (typeof n === 'string') { + const el = make('mujs-a', { + textContent: n + }); + elem.append(el); + } else { + for (const c of n) { + if (typeof c === 'string' && c.startsWith('http')) { + const el = make('mujs-a', { + textContent: c, + dataset: { + command: 'open-tab', + webpage: c + } + }); + elem.append(el); + } else if (isObj(c)) { + const el = make('mujs-a', { + textContent: c.text + }); + if (c.domain) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = `https://${c.text}`; + } + elem.append(el); + } else { + const el = make('mujs-a', { + textContent: c + }); + elem.append(el); + } + } + } + }; // #region Main event handlers - ael(main, 'click', async (evt) => { + ael(main, isMobile ? 'touchend' : 'click', async (evt) => { try { /** @type { HTMLElement } */ const target = evt.target.closest('[data-command]'); @@ -1911,10 +1974,13 @@ function primaryFN() { } return window.open(dataset.webpage, '_blank'); } else if (cmd === 'navigation') { - if (dom.cl.has(btngreasy, 'hidden')) { - dom.cl.remove([btncfg, btngreasy, btnhome, btnissue], 'hidden'); - } else { - dom.cl.add([btncfg, btngreasy, btnhome, btnissue], 'hidden'); + for (const e of qsA('mujs-btn', target.parentElement)) { + if (dom.cl.has(e, 'nav')) continue; + if (dom.cl.has(e, 'hidden')) { + dom.cl.remove(e, 'hidden'); + } else { + dom.cl.add(e, 'hidden'); + } } } else if (cmd === 'list-description') { const arr = []; @@ -1946,10 +2012,10 @@ function primaryFN() { } else if (cmd === 'fullscreen') { if (dom.cl.has(btnfullscreen, 'expanded')) { dom.cl.remove([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('expand')); } else { dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('collapse')); } } else if (cmd === 'hide-list') { dom.cl.add(main, 'hidden'); @@ -2018,81 +2084,115 @@ function primaryFN() { dlBtn.click(); URL.revokeObjectURL(dlBtn.href); dlBtn.remove(); - } else if (cmd === 'load-userjs') { + } else if (cmd === 'load-userjs' || cmd === 'load-header') { if (!container.userjsCache.has(+dataset.userjs)) { return; } const codeArea = qs('textarea', target.parentElement.parentElement); - if (!isEmpty(codeArea.value)) { + if (!isEmpty(codeArea.value) && cmd === codeArea.dataset.load) { dom.cl.toggle(codeArea, 'hidden'); return; } + codeArea.dataset.load = cmd; const dataUserJS = container.userjsCache.get(+dataset.userjs); - const r = await dataUserJS._mujs.code.request(); - const txt = r.data; - if (typeof txt !== 'string') { + const code_obj = await dataUserJS._mujs.code.request(); + if (typeof code_obj.data_code_block !== 'string') { + codeArea.value = 'An error occured'; return; } - const code_obj = new ParseUserJS(txt); - codeArea.value = code_obj.get_code_block(); + codeArea.value = + cmd === 'load-userjs' ? code_obj.data_code_block : code_obj.data_meta_block; dom.cl.remove(codeArea, 'hidden'); - const apTo = (name, elem, root) => { - const n = dataUserJS._mujs.code[name]; - if (isEmpty(n)) { - const el = make('mujs-a', { - textContent: i18n$('listing_none') + for (const e of qsA( + 'mujs-column[data-el="matches"]', + target.parentElement.parentElement + )) { + applyTo(dataUserJS, e.dataset.type, qs('.mujs-grants', e), e); + } + } else if (cmd === 'load-page') { + if (!container.userjsCache.has(+dataset.userjs)) { + return; + } + let pageArea = qs('mujs-page', target.parentElement.parentElement); + if (!pageArea) { + pageArea = make('mujs-page'); + target.parentElement.parentElement.append(pageArea); + const dataUserJS = container.userjsCache.get(+dataset.userjs); + const engine = dataUserJS._mujs.info.engine; + let pageURL; + if (engine.name.includes('fork')) { + const { navigator } = safeSelf(); + const current = navigator.language.split('-')[0] ?? 'en'; + pageURL = dataUserJS.url.replace( + /\/scripts/, + `/${/^(zh|fr|es)/.test(current) ? navigator.language : current}/scripts` + ); + } else if (engine.name.includes('github')) { + const page_url = await Network.req(dataUserJS.page_url, 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).catch(() => { + return {}; }); - elem.append(el); + if (!page_url.download_url) { + return; + } + const page = await Network.req(page_url.download_url, 'GET', 'text'); + if (container.supported) { + const shadow = pageArea.attachShadow({ mode: 'closed' }); + const div = make('div', { + innerHTML: page + }); + shadow.append(div); + } return; + } else { + pageURL = dataUserJS.url; } - dom.prop(elem, 'innerHTML', ''); - dom.cl.remove(root, 'hidden'); - for (const c of n) { - if (typeof c === 'string' && c.startsWith('http')) { - const el = make('mujs-a', { - textContent: c, - dataset: { - command: 'open-tab', - webpage: c - } - }); - elem.append(el); - } else if (isObj(c)) { - if (name === 'resource') { - for (const [k, v] of Object.entries(c)) { - const el = make('mujs-a', { - textContent: k ?? 'ERROR' - }); - if (v.startsWith('http')) { - el.dataset.command = 'open-tab'; - el.dataset.webpage = v; - } - elem.append(el); - } - } else { - const el = make('mujs-a', { - textContent: c.text - }); - if (c.domain) { - el.dataset.command = 'open-tab'; - el.dataset.webpage = `https://${c.text}`; - } - elem.append(el); + if (!pageURL) { + return; + } + const page = await Network.req(pageURL, 'GET', 'document'); + const getContent = () => { + let content = 'An error occured'; + const h = new URL(dataUserJS.url); + const root = qs('.user-content', page.documentElement); + for (const e of qsA('[href]', root)) { + e.target = '_blank'; + e.style = 'pointer-events: auto;'; + if (e.href.startsWith('/')) { + e.href = `${h.origin}${e.href}`; } + } + for (const e of qsA('img[src]', root)) { + e.style = + 'max-width: 25em; max-height: 25em; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;'; + } + if (root) { + content = root.innerHTML; } else { - const el = make('mujs-a', { - textContent: c - }); - elem.append(el); + content = 'No additional info available'; } + return content; + }; + if (container.supported) { + const shadow = pageArea.attachShadow({ mode: 'closed' }); + const div = make('div', { + style: 'pointer-events: none;', + innerHTML: getContent() + }); + shadow.append(div); } - }; - for (const e of qsA( - 'mujs-column[data-el="matches"]', - target.parentElement.parentElement - )) { - apTo(e.dataset.type, qs('.mujs-grants', e), e); + return; + } + if (!dom.cl.has(pageArea, 'hidden')) { + dom.cl.add(pageArea, 'hidden'); + return; } + dom.cl.remove(pageArea, 'hidden'); } else if (/export-/.test(cmd)) { const str = JSON.stringify(cmd === 'export-cfg' ? cfg : cfg.theme, null, ' '); const bytes = new TextEncoder().encode(str); @@ -2193,9 +2293,50 @@ function primaryFN() { }); } } + ael(main, 'updateditem', (evt) => { + /** + * @type {import("../typings/types.d.ts").GSForkQuery} + */ + const ujs = evt.detail; + if (!ujs._mujs) return; + for (const elem of qsA('[data-name]', ujs._mujs.root)) { + const name = elem.dataset.name; + if (name === 'code') { + if (ujs._mujs.code.data_code_block) { + if (cfg.preview.code && !cfg.preview.metadata) { + elem.value = ujs._mujs.code.data_code_block; + } else if (cfg.preview.metadata && !cfg.preview.code) { + elem.value = ujs._mujs.code.data_meta_block; + } else { + elem.value = `${ujs._mujs.code.META_START_COMMENT}${ujs._mujs.code.data_meta_block}${ujs._mujs.code.META_END_COMMENT}${ujs._mujs.code.data_code_block}`; + } + } + continue; + } + if (!ujs[name]) continue; + if (name === 'license') { + dom.attr(elem, 'title', ujs.license ?? i18n$('no_license')); + dom.text(elem, `${i18n$('license')}: ${ujs.license ?? i18n$('no_license')}`); + } else if (name === 'code_updated_at') { + dom.text(elem, language.toDate(ujs.code_updated_at)); + elem.dataset.value = new Date(ujs.code_updated_at).toISOString(); + } else if (name === 'created_date') { + dom.text(elem, `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`); + elem.dataset.value = new Date(ujs.created_at).toISOString(); + } else if (name === 'total_installs') { + dom.text(elem, `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}`); + } else { + dom.text(elem, ujs[name]); + } + } + if (ujs._mujs.code.data_code_block) { + for (const e of qsA('mujs-column[data-el="matches"]', ujs._mujs.root)) { + applyTo(ujs, e.dataset.type, qs('.mujs-grants', e), e); + } + } + if (container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); + }); // #endregion - const META_START_COMMENT = '// ==UserScript=='; - const META_END_COMMENT = '// ==/UserScript=='; const TLD_EXPANSION = ['com', 'net', 'org', 'de', 'co.uk']; const APPLIES_TO_ALL_PATTERNS = [ 'http://*', @@ -2223,15 +2364,17 @@ function primaryFN() { */ data_code_block; /** - * @type { { [meta: string]: any } } + * @type { { [meta: string]: string | string[] | { [resource: string]: string } } } */ data_meta; /** - * @type { string[] } + * @type { {text: string;domain: boolean;tld_extra: boolean}[] } */ data_names; - constructor(code) { + constructor(code, isUserCSS) { this.code = code; + this.META_START_COMMENT = isUserCSS ? '/* ==UserStyle==' : '// ==UserScript=='; + this.META_END_COMMENT = isUserCSS ? '==/UserStyle== */' : '// ==/UserScript=='; this.get_meta_block(); this.get_code_block(); this.parse_meta(); @@ -2244,17 +2387,20 @@ function primaryFN() { if (this.data_meta_block) { return this.data_meta_block; } - const start_block = this.code.indexOf(META_START_COMMENT); + const start_block = this.code.indexOf(this.META_START_COMMENT); if (isNull(start_block)) { return null; } - const end_block = this.code.indexOf(META_END_COMMENT, start_block); + const end_block = this.code.indexOf(this.META_END_COMMENT, start_block); if (isNull(end_block)) { return null; } - const meta_block = this.code.substring(start_block + META_START_COMMENT.length, end_block); + const meta_block = this.code.substring( + start_block + this.META_START_COMMENT.length, + end_block + ); this.data_meta_block = meta_block; - return meta_block; + return this.data_meta_block; } get_code_block() { if (isEmpty(this.code)) { @@ -2263,28 +2409,23 @@ function primaryFN() { if (this.data_code_block) { return this.data_code_block; } - const start_block = this.code.indexOf(META_START_COMMENT); + const start_block = this.code.indexOf(this.META_START_COMMENT); if (isNull(start_block)) { return null; } - const end_block = this.code.indexOf(META_END_COMMENT, start_block); + const end_block = this.code.indexOf(this.META_END_COMMENT, start_block); if (isNull(end_block)) { return null; } const code_block = this.code.substring( - end_block + META_END_COMMENT.length, + end_block + this.META_END_COMMENT.length, this.code.length ); - const lines = []; - for (const l of code_block.split('\n')) { - if (isEmpty(l)) { - continue; - } - lines.push(l); - } - const clean_code = lines.join('\n'); - this.data_code_block = clean_code; - return clean_code; + this.data_code_block = code_block + .split('\n') + .filter((l) => !isEmpty(l)) + .join('\n'); + return this.data_code_block; } parse_meta() { if (isEmpty(this.code)) { @@ -2294,11 +2435,10 @@ function primaryFN() { return this.data_meta; } const meta = {}; - const meta_block = this.get_meta_block(); const meta_block_map = new Map(); - for (const meta_line of meta_block.split('\n')) { - const meta_match = meta_line.match(/\/\/\s+@([a-zA-Z:-]+)\s+(.*)/); - if (isNull(meta_match)) { + for (const meta_line of this.get_meta_block().split('\n')) { + const meta_match = /\/\/\s+@([a-zA-Z:-]+)\s+(.*)/.exec(meta_line); + if (!meta_match) { continue; } const key = meta_match[1].trim(); @@ -2320,9 +2460,6 @@ function primaryFN() { this.data_meta = meta; return this.data_meta; } - /** - * @returns { string[] } - */ calculate_applies_to_names() { if (isEmpty(this.code)) { return null; @@ -2330,10 +2467,9 @@ function primaryFN() { if (this.data_names) { return this.data_names; } - const meta = this.parse_meta(); let patterns = []; - for (const [k, v] of Object.entries(meta)) { - if (/include|match/.test(k)) { + for (const [k, v] of Object.entries(this.parse_meta())) { + if (/include|match/i.test(k)) { if (Array.isArray(v)) { patterns = patterns.concat(v); } else { @@ -2345,14 +2481,21 @@ function primaryFN() { return []; } if (this.intersect(patterns, APPLIES_TO_ALL_PATTERNS)) { - return []; + this.data_names = [ + { + domain: false, + text: 'All sites', + tld_extra: false + } + ]; + return this.data_names; } - const name_set = new Set(); + const name_map = new Map(); const addObj = (obj) => { - if (name_set.has(obj)) { + if (name_map.has(obj.text)) { return; } - name_set.add(obj); + name_map.set(obj.text, obj); }; for (let p of patterns) { try { @@ -2361,8 +2504,8 @@ function primaryFN() { if (p.match(/^\/(.*)\/$/)) { pre_wildcards = [p]; } else { - let m = p.match(/^\*(https?:.*)/i); - if (!isNull(m)) { + let m = /^\*(https?:.*)/i.exec(p); + if (m) { p = m[1]; } p = p @@ -2370,20 +2513,20 @@ function primaryFN() { .replace(/^\*\/\//i, 'http://') .replace(/^http\*:/i, 'http:') .replace(/^(https?):([^/])/i, '$1://$2'); - m = p.match(/^([a-z]+:\/\/)\*\.?([a-z0-9-]+(?:.[a-z0-9-]+)+.*)/i); - if (!isNull(m)) { + m = /^([a-z]+:\/\/)\*\.?([a-z0-9-]+(?:.[a-z0-9-]+)+.*)/i.exec(p); + if (m) { p = m[1] + m[2]; } - m = p.match(/^\*\.?([a-z0-9-]+\.[a-z0-9-]+.*)/i); - if (!isNull(m)) { + m = /^\*\.?([a-z0-9-]+\.[a-z0-9-]+.*)/i.exec(p); + if (m) { p = `http://${m[1]}`; } - m = p.match(/^http\*(?:\/\/)?\.?((?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+.*)/i); - if (!isNull(m)) { + m = /^http\*(?:\/\/)?\.?((?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+.*)/i.exec(p); + if (m) { p = `http://${m[1]}`; } - m = p.match(/^([a-z]+:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)*\.))\*(.*)/); - if (!isNull(m)) { + m = /^([a-z]+:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)*\.))\*(.*)/.exec(p); + if (m) { if (m[2].match(/A([0-9]+\.){2,}z/)) { p = `${m[1]}tld${m[3]}`; pre_wildcards = [p.split('*')[0]]; @@ -2433,26 +2576,12 @@ function primaryFN() { err(ex); } } - const arr = [...name_set]; - this.data_names = arr; + this.data_names = [...name_map.values()]; return this.data_names; } - intersect(a = [], b = []) { - for (const v of a) { - if (b.includes(v)) { - return true; - } - } - for (const v of b) { - if (a.includes(v)) { - return true; - } - } - return false; + intersect(a, ...arr) { + return !isBlank([...new Set(a)].filter((v) => arr.every((b) => b.includes(v)))); } - // intersect(a, ...arr) { - // return [...new Set(a)].filter((v) => arr.every((b) => b.includes(v))); - // } } const template = { id: 0, @@ -2573,11 +2702,15 @@ function primaryFN() { const eframe = make('td', 'install-btn'); const uframe = make('td', 'mujs-uframe'); const fdaily = make('td', 'mujs-list', { - textContent: ujs.daily_installs + textContent: ujs.daily_installs, + dataset: { + name: 'daily_installs' + } }); const fupdated = make('td', 'mujs-list', { textContent: language.toDate(ujs.code_updated_at), dataset: { + name: 'code_updated_at', value: new Date(ujs.code_updated_at).toISOString() } }); @@ -2605,17 +2738,22 @@ function primaryFN() { const fcreated = make('mu-js', 'mujs-list', { textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`, dataset: { + name: 'created_at', value: new Date(ujs.created_at).toISOString() } }); const flicense = make('mu-js', 'mujs-list', { title: ujs.license ?? i18n$('no_license'), textContent: `${i18n$('license')}: ${ujs.license ?? i18n$('no_license')}`, - style: - 'text-overflow: ellipsis; overflow: hidden; white-space: nowrap; width: fit-content; max-width: 20em;' + dataset: { + name: 'license' + } }); const ftotal = make('mu-js', 'mujs-list', { - textContent: `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}` + textContent: `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}`, + dataset: { + name: 'total_installs' + } }); const fratings = make('mu-js', 'mujs-list', { title: i18n$('ratings'), @@ -2625,6 +2763,7 @@ function primaryFN() { title: i18n$('good'), textContent: ujs.good_ratings, dataset: { + name: 'good_ratings', el: 'good' } }); @@ -2632,6 +2771,7 @@ function primaryFN() { title: i18n$('ok'), textContent: ujs.ok_ratings, dataset: { + name: 'ok_ratings', el: 'ok' } }); @@ -2639,6 +2779,7 @@ function primaryFN() { title: i18n$('bad'), textContent: ujs.bad_ratings, dataset: { + name: 'bad_ratings', el: 'bad' } }); @@ -2658,7 +2799,7 @@ function primaryFN() { } }); const scriptDownload = make('mu-jsbtn', { - innerHTML: `${iconSVG.load('install')} ${i18n$('saveFile')}`, + innerHTML: `${iconSVG.load('download')} ${i18n$('saveFile')}`, dataset: { command: 'download-userjs', userjs: ujs.id, @@ -2680,23 +2821,22 @@ function primaryFN() { wrap: 'soft' }); const loadCode = make('mu-jsbtn', { - innerHTML: `${iconSVG.load('search')} ${i18n$('preview_code')}`, + innerHTML: `${iconSVG.load('code')} ${i18n$('preview_code')}`, dataset: { command: 'load-userjs', userjs: ujs.id } }); - if (engine) { - tr.dataset.engine = engine; - // if (engine.includes('fork')) { - // fdaily.dataset.command = 'open-tab'; - // fdaily.dataset.webpage = `${ujs.url}/stats`; - // fupdated.dataset.command = 'open-tab'; - // fupdated.dataset.webpage = `${ujs.url}/versions`; - // } - if (!engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.url)) { - tr.dataset.good = 'upsell'; + const loadMetadata = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('code')} Metadata`, + dataset: { + command: 'load-header', + userjs: ujs.id } + }); + tr.dataset.engine = engine; + if (!engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.url)) { + tr.dataset.good = 'upsell'; } for (const u of ujs.users) { const user = make('mujs-a', { @@ -2713,7 +2853,7 @@ function primaryFN() { } uframe.append(user); } - if (engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.id)) { + if (cfg.recommend.others && goodUserJS.includes(ujs.id)) { tr.dataset.good = 'upsell'; } eframe.append(scriptInstall); @@ -2721,53 +2861,55 @@ function primaryFN() { jsInfo.append(ftotal, ratings, fver, fcreated); mkList(i18n$('code_size'), { list: ujs._mujs.code.code_size, - type: 'size', + type: 'code_size', root: jsInfo }); jsInfoB.append(flicense); + const data_meta = ujs._mujs.code?.data_meta ?? {}; mkList(i18n$('antifeatures'), { - list: ujs._mujs.code.antifeatures, + list: data_meta.antifeatures ?? [], type: 'antifeatures', root: jsInfoB }); mkList(i18n$('applies_to'), { - list: ujs._mujs.code.match, - type: 'match', + list: ujs._mujs.code?.data_names ?? [], + type: 'data_names', root: jsInfoB }); mkList('@grant', { - list: ujs._mujs.code.grant, + list: data_meta.grant ?? [], type: 'grant', root: jsInfoB }); mkList('@require', { - list: ujs._mujs.code.meta?.require, + list: data_meta.require, type: 'require', root: jsInfoB }); - const script_resources = ujs._mujs.code.meta?.resource; mkList('@resource', { - list: isNull(script_resources) ? [] : [script_resources], + list: isNull(data_meta.resource) ? [] : [data_meta.resource], type: 'resource', root: jsInfoB }); fmore.append(jsInfo, jsInfoB); - fBtns.append(scriptDownload, loadCode); + fBtns.append(scriptDownload, loadCode, loadMetadata); fname.append(ftitle, fdesc, fmore, fBtns, codeArea); - const code_data = ujs._mujs.code.data; - if (code_data) { - const code_obj = new ParseUserJS(code_data); - codeArea.value = code_obj.get_code_block(); - } + const loadPage = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('pager')} Page`, + dataset: { + command: 'load-page', + userjs: ujs.id + } + }); + fBtns.append(loadPage); if (ujs._mujs.code?.translated) tr.classList.add('translated'); for (const e of [fname, uframe, fdaily, fupdated, eframe]) tr.append(e); ujs._mujs.root = tr; - - return tr; + return ujs._mujs.root; }; // #endregion const loadFilters = () => { @@ -2825,12 +2967,19 @@ function primaryFN() { this.build = this.build.bind(this); this.toArr = this.toArr.bind(this); this.groupBy = this.groupBy.bind(this); + this.dispatch = this.dispatch.bind(this); this.sortRecords = this.sortRecords.bind(this); if (isEmpty(hostname)) hostname = container.host; this.engines = cfg.engines; this.host = hostname; } + dispatch(ujs) { + const { CustomEvent } = safeSelf(); + const customEvent = new CustomEvent('updateditem', { detail: ujs }); + main.dispatchEvent(customEvent); + } + set host(hostname) { this.intHost = hostname; @@ -2869,7 +3018,7 @@ function primaryFN() { build() { try { container.refresh(); - const { blacklisted, engines, host, toArr } = this; + const { blacklisted, engines, host, toArr, dispatch } = this; if (blacklisted || isEmpty(engines)) { container.opacityMin = '0'; mainframe.style.opacity = container.opacityMin; @@ -2903,92 +3052,59 @@ function primaryFN() { host }, code: { - antifeatures: [], - grant: [], - match: [], meta: {}, request: async function (translate = false, code_url) { - if (this.data) { + if (this.data_code_block) { return this; } - this.data = ''; + code_url = code_url ?? d.code_url; /** @type { string } */ - const code = await Network.req(code_url ?? d.code_url, 'GET', 'text').catch( - showError - ); + const code = await Network.req(code_url, 'GET', 'text').catch(showError); if (typeof code !== 'string') { return this; } - Object.assign(this, { - data: code, - code_size: [Network.format(code.length)] - }); - const grantSet = new Set(); - const afSet = new Set(); - const code_obj = new ParseUserJS(code); - const meta = code_obj.parse_meta(); - const applies_to_names = code_obj.calculate_applies_to_names(); - + const code_obj = new ParseUserJS(code, /\.user\.css/.test(code_url)); + const { data_meta } = code_obj; if (translate) { for (const k of userjs.pool.keys()) { - if (meta[`name:${k}`]) { + if (data_meta[`name:${k}`]) { Object.assign(obj, { - name: meta[`name:${k}`] + name: data_meta[`name:${k}`] }); this.translated = true; } - if (meta[`description:${k}`]) { + if (data_meta[`description:${k}`]) { Object.assign(obj, { - description: meta[`description:${k}`] + description: data_meta[`description:${k}`] }); this.translated = true; } } } - - for (const [key, value] of Object.entries(meta)) { - if (/grant/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (grantSet.has(v)) { - continue; - } - grantSet.add(v); - } - } else if (/antifeature/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (afSet.has(v)) { - continue; - } - afSet.add(v); - } - } - } - if (typeof meta.require === 'string') { - const s = meta.require; - meta.require = [s]; + if (Array.isArray(data_meta.grant)) { + data_meta.grant = union(data_meta.grant); } - if (meta.resource) { + if (data_meta.resource) { const obj = {}; - if (typeof meta.resource === 'string') { - const reg = /(.+)\s+(.+)/.exec(meta.resource); + if (typeof data_meta.resource === 'string') { + const reg = /(.+)\s+(.+)/.exec(data_meta.resource); if (reg) { obj[reg[1].trim()] = reg[2]; } } else { - for (const r of meta.resource) { + for (const r of data_meta.resource) { const reg = /(.+)\s+(http.+)/.exec(r); if (reg) { obj[reg[1].trim()] = reg[2]; } } } - meta.resource = obj; + data_meta.resource = obj; } Object.assign(this, { - meta, - match: applies_to_names, - grant: [...grantSet], - antifeatures: [...afSet] + code_size: [Network.format(code.length)], + meta: data_meta, + ...code_obj }); return this; @@ -3063,8 +3179,13 @@ function primaryFN() { finalList = union(hds, filterLang); for (const ujs of finalList) { - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + if ( + !ujs._mujs.code.data_code_block && + (cfg.preview.code || cfg.preview.metadata) + ) { + ujs._mujs.code.request().then(() => { + dispatch(ujs); + }); } createjs(ujs, engine.name); } @@ -3080,7 +3201,8 @@ function primaryFN() { } const selected = htmlDocument.documentElement; if (/openuserjs/gi.test(engine.name)) { - for (const i of qsA('.col-sm-8 .tr-link', selected)) { + const col = qsA('.col-sm-8 .tr-link', selected) ?? []; + for (const i of col) { while (isNull(qs('.script-version', i))) { await new Promise((resolve) => requestAnimationFrame(resolve)); } @@ -3109,8 +3231,13 @@ function primaryFN() { if (bsFilter.match(ujs)) { continue; } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + if ( + !ujs._mujs.code.data_code_block && + (cfg.preview.code || cfg.preview.metadata) + ) { + ujs._mujs.code.request().then(() => { + dispatch(ujs); + }); } createjs(ujs, engine.name); } @@ -3119,7 +3246,7 @@ function primaryFN() { showError(ex); } }; - const gitFN = async (data) => { + const gitFN = (data) => { try { if (isBlank(data.items)) { showError('Invalid data received from the server, TODO fix this'); @@ -3127,14 +3254,14 @@ function primaryFN() { } for (const r of data.items) { const ujs = _mujs({ - name: r.name, + id: r.repository.id ?? r.id ?? 0, + name: r.repository.name ?? r.name, description: isEmpty(r.repository.description) ? i18n$('no_license') : r.repository.description, - url: r.html_url, + url: r.repository.html_url, code_url: r.html_url.replace(/\/blob\//g, '/raw/'), - code_updated_at: r.commit || Date.now(), - total_installs: r.score, + page_url: `${r.repository.url}/contents/README.md`, users: [ { name: r.repository.owner.login, @@ -3142,11 +3269,30 @@ function primaryFN() { } ] }); - if (bsFilter.match(ujs)) { - continue; - } - if (cfg.codePreview && !ujs._mujs.code.data) { - await ujs._mujs.code.request(); + // if (bsFilter.match(ujs)) { + // continue; + // } + Network.req(r.repository.url, 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).then((repository) => { + ujs.code_updated_at = r.commit || repository.updated_at || Date.now(); + ujs.created_at = repository.created_at; + ujs.daily_installs = repository.watchers_count ?? 0; + ujs.good_ratings = repository.stargazers_count ?? 0; + if (repository.license?.name) ujs.license = repository.license.name; + dispatch(ujs); + }); + if ( + !ujs._mujs.code.data_code_block && + (cfg.preview.code || cfg.preview.metadata) + ) { + ujs._mujs.code.request().then(() => { + dispatch(ujs); + }); } createjs(ujs, engine.name); } @@ -3273,6 +3419,8 @@ function primaryFN() { command: 'reset' } }); + cbtn.append(resetbtn, savebtn); + const makesection = (name, tag) => { tag = tag ?? i18n$('no_license'); name = name ?? i18n$('no_license'); @@ -3297,7 +3445,7 @@ function primaryFN() { } const cmd = target.dataset.command; if (cmd === tag) { - const a = qsA(`label[data-${tag}]`, sec); + const a = qsA(`[data-${tag}]`, sec); if (dom.cl.has(a, 'hidden')) { dom.cl.remove(a, 'hidden'); } else { @@ -3311,133 +3459,24 @@ function primaryFN() { cfgpage.append(sec); return sec; }; - const sections = { general: makesection('General', 'general'), load: makesection('Automation', 'load'), list: makesection('List', 'list'), filters: makesection('List Filters', 'filters'), blacklist: makesection('Blacklist (WIP)', 'blacklist'), - // engine: makesection('Search Engine', 'engine'), - theme: makesection('Theme Colors', 'theme') - }; - - const makerow = (desc, type = null, nm, attrs = {}) => { - desc = desc ?? i18n$('no_license'); - nm = nm ?? i18n$('no_license'); - const sec = make('mujs-section', { - dataset: { - name: nm - } - }); - const lb = make('label'); - const divDesc = make('mu-js', { - textContent: desc - }); - lb.append(divDesc); - sec.append(lb); - cfgpage.append(sec); - if (isNull(type)) { - return lb; - } - const inp = make('input', { - type, - dataset: { - name: nm - }, - ...attrs - }); - if (!cfgMap.has(nm)) { - cfgMap.set(nm, inp); - } - if (type === 'checkbox') { - const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', { - onclick() { - inp.dispatchEvent(new MouseEvent('click')); - } - }); - inlab.append(inp, la); - lb.append(inlab); - if (nm.includes('-')) { - return inp; - } - if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { - const engine = cfg.engines.find((engine) => engine.name === nm); - if (engine) { - inp.checked = engine.enabled; - inp.dataset.engine = engine.name; - ael(inp, 'change', (evt) => { - container.unsaved = true; - container.rebuild = true; - engine.enabled = evt.target.checked; - }); - - if (engine.query) { - const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); - const urlInp = make('input', { - type: 'text', - defaultValue: '', - value: decodeURIComponent(engine.query) ?? '', - placeholder: decodeURIComponent(d.query) ?? '', - dataset: { - name: nm, - engine: engine.name - }, - onchange(evt) { - container.unsaved = true; - container.rebuild = true; - try { - engine.query = encodeURIComponent(new URL(evt.target.value).toString()); - } catch (ex) { - err(ex); - } - } - }); - sec.append(urlInp); - } - if (engine.name === 'github') { - const ghToken = make('input', { - type: 'text', - defaultValue: '', - value: engine.token ?? '', - placeholder: 'Paste Access Token', - dataset: { - engine: 'github-token' - }, - onchange(evt) { - container.unsaved = true; - container.rebuild = true; - engine.token = evt.target.value; - } - }); - sec.append(ghToken); - cfgMap.set('github-token', ghToken); - } - } - } else { - inp.checked = cfg[nm]; - ael(inp, 'change', (evt) => { - container.unsaved = true; - if (/filterlang/i.test(nm)) { - container.rebuild = true; - } - cfg[nm] = evt.target.checked; - }); - } - } else { - lb.append(inp); - } - return inp; + engine: makesection('Search Engines', 'engine'), + theme: makesection('Theme Colors', 'theme'), + exp: makesection('Import / Export', 'exp') }; - const mkSection = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { - cfgMap.set(text, value); + const makeRow = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { const lb = make('label', 'sub-section hidden', { textContent: text, dataset: { [tag]: text } }); + cfgMap.set(text, value); if (type === 'select') { const inp = make('select', { dataset: { @@ -3468,6 +3507,10 @@ function primaryFN() { ...attrs }); + if (tag === 'engine') { + inp.dataset.name = value; + } + if (sections[tag]) { sections[tag].append(lb); } @@ -3507,6 +3550,61 @@ function primaryFN() { cfg[value] = evt.target.checked; } }); + + if (tag === 'engine') { + const engine = cfg.engines.find((engine) => engine.name === value); + if (engine) { + inp.checked = engine.enabled; + inp.dataset.engine = engine.name; + ael(inp, 'change', (evt) => { + container.unsaved = true; + container.rebuild = true; + engine.enabled = evt.target.checked; + }); + + if (engine.query) { + const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); + const urlInp = make('input', { + type: 'text', + defaultValue: '', + value: decodeURIComponent(engine.query) ?? '', + placeholder: decodeURIComponent(d.query) ?? '', + dataset: { + name: nm, + engine: engine.name + }, + onchange(evt) { + container.unsaved = true; + container.rebuild = true; + try { + engine.query = encodeURIComponent(new URL(evt.target.value).toString()); + } catch (ex) { + err(ex); + } + } + }); + lb.append(urlInp); + } + if (engine.name === 'github') { + const ghToken = make('input', { + type: 'text', + defaultValue: '', + value: engine.token ?? '', + placeholder: 'Paste Access Token', + dataset: { + engine: 'github-token' + }, + onchange(evt) { + container.unsaved = true; + container.rebuild = true; + engine.token = evt.target.value; + } + }); + lb.append(ghToken); + cfgMap.set('github-token', ghToken); + } + } + } } else { if (type === 'text') { inp.defaultValue = ''; @@ -3520,11 +3618,11 @@ function primaryFN() { return lb; }; if (isGM) { - mkSection(i18n$('userjs_sync'), 'cache'); - mkSection(i18n$('userjs_autoinject'), 'autoinject', 'checkbox', 'load'); + makeRow(i18n$('userjs_sync'), 'cache'); + makeRow(i18n$('userjs_autoinject'), 'autoinject', 'checkbox', 'load'); } - mkSection(i18n$('redirect'), 'sleazyredirect'); - mkSection(`${i18n$('dtime')} (ms)`, 'time', 'number', 'general', { + makeRow(i18n$('redirect'), 'sleazyredirect'); + makeRow(`${i18n$('dtime')} (ms)`, 'time', 'number', 'general', { defaultValue: 10000, value: cfg.time, min: 0, @@ -3552,34 +3650,35 @@ function primaryFN() { } }); - mkSection(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); - mkSection(i18n$('userjs_fullscreen'), 'autoexpand', 'checkbox', 'load', { + makeRow(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); + makeRow(i18n$('userjs_fullscreen'), 'autoexpand', 'checkbox', 'load', { onchange(e) { if (e.target.checked) { dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('collapse')); } else { dom.cl.remove([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsOpen')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('expand')); } } }); - mkSection('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); + makeRow('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); - mkSection('Default Sort', 'autoSort', 'select', 'list'); - mkSection(i18n$('filter'), 'filterlang', 'checkbox', 'list'); - mkSection(i18n$('preview_code'), 'codePreview', 'checkbox', 'list'); - mkSection('Recommend author', 'recommend-author', 'checkbox', 'list'); - mkSection('Recommend scripts', 'recommend-others', 'checkbox', 'list'); + makeRow('Default Sort', 'autoSort', 'select', 'list'); + makeRow(i18n$('filter'), 'filterlang', 'checkbox', 'list'); + makeRow(i18n$('preview_code'), 'preview-code', 'checkbox', 'list'); + makeRow('Preview Metadata', 'preview-metadata', 'checkbox', 'list'); + makeRow('Recommend author', 'recommend-author', 'checkbox', 'list'); + makeRow('Recommend scripts', 'recommend-others', 'checkbox', 'list'); for (const [k, v] of Object.entries(cfg.filters)) { - mkSection(v.name, `filters-${k}`, 'checkbox', 'filters'); + makeRow(v.name, `filters-${k}`, 'checkbox', 'filters'); } - makerow('Greasy Fork', 'checkbox', 'greasyfork'); - makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); - makerow('Open UserJS', 'checkbox', 'openuserjs'); - makerow('GitHub API', 'checkbox', 'github'); + makeRow('Greasy Fork', 'greasyfork', 'checkbox', 'engine'); + makeRow('Sleazy Fork', 'sleazyfork', 'checkbox', 'engine'); + makeRow('Open UserJS', 'openuserjs', 'checkbox', 'engine'); + makeRow('GitHub API', 'github', 'checkbox', 'engine'); for (const [k, v] of Object.entries(cfg.theme)) { const lb = make('label', 'hidden', { @@ -3633,6 +3732,66 @@ function primaryFN() { sections.theme.append(lb); } + // const blacklist = make('textarea', { + // dataset: { + // name: 'blacklist' + // }, + // rows: '10', + // autocomplete: false, + // spellcheck: false, + // wrap: 'soft', + // value: JSON.stringify(cfg.blacklist, null, ' '), + // oninput(evt) { + // let isvalid = true; + // try { + // cfg.blacklist = JSON.parse(evt.target.value); + // isvalid = true; + // } catch (ex) { + // err(ex); + // isvalid = false; + // } finally { + // if (isvalid) { + // dom.cl.remove(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', false); + // } else { + // dom.cl.add(evt.target, 'mujs-invalid'); + // dom.prop(savebtn, 'disabled', true); + // } + // } + // } + // }); + // cfgMap.set('blacklist', blacklist); + // const addList = make('mujs-add', { + // textContent: '+', + // dataset: { + // command: 'new-list' + // } + // }); + // const n = make('input', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Name', + // }); + // const inpValue = make('input', { + // type: 'text', + // defaultValue: '', + // value: '', + // placeholder: 'Value', + // }); + // const label = make('label', 'new-list hidden', { + // dataset: { + // blacklist: 'new-list' + // } + // }); + // label.append(n, inpValue, addList); + // listSec.append(label); + // ael(addList, 'click', () => { + // if (isEmpty(n.value) || isEmpty(inpValue.value)) { + // return + // }; + // createList(n.value, n.value, inpValue.value); + // }); const createList = (key, v = '', disabled = false, type = 'String') => { let txt = key; if (typeof key === 'string') { @@ -3718,72 +3877,50 @@ function primaryFN() { lb.append(inp, selType); sections.blacklist.append(lb); }; - // const blacklist = make('textarea', { - // dataset: { - // name: 'blacklist' - // }, - // rows: '10', - // autocomplete: false, - // spellcheck: false, - // wrap: 'soft', - // value: JSON.stringify(cfg.blacklist, null, ' '), - // oninput(evt) { - // let isvalid = true; - // try { - // cfg.blacklist = JSON.parse(evt.target.value); - // isvalid = true; - // } catch (ex) { - // err(ex); - // isvalid = false; - // } finally { - // if (isvalid) { - // dom.cl.remove(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', false); - // } else { - // dom.cl.add(evt.target, 'mujs-invalid'); - // dom.prop(savebtn, 'disabled', true); - // } - // } - // } - // }); - // cfgMap.set('blacklist', blacklist); - // const addList = make('mujs-add', { - // textContent: '+', - // dataset: { - // command: 'new-list' - // } - // }); - // const n = make('input', { - // type: 'text', - // defaultValue: '', - // value: '', - // placeholder: 'Name', - // }); - // const inpValue = make('input', { - // type: 'text', - // defaultValue: '', - // value: '', - // placeholder: 'Value', - // }); - // const label = make('label', 'new-list hidden', { - // dataset: { - // blacklist: 'new-list' - // } - // }); - // label.append(n, inpValue, addList); - // listSec.append(label); - // ael(addList, 'click', () => { - // if (isEmpty(n.value) || isEmpty(inpValue.value)) { - // return - // }; - // createList(n.value, n.value, inpValue.value); - // }); - for (const key of cfg.blacklist) { createList(key); } - cbtn.append(resetbtn, savebtn); + const transfers = { + export: { + cfg: make('mujs-btn', 'mujs-export sub-section hidden', { + textContent: i18n$('export_config'), + dataset: { + command: 'export-cfg', + exp: 'export-cfg' + } + }), + theme: make('mujs-btn', 'mujs-export sub-section hidden', { + textContent: i18n$('export_theme'), + dataset: { + command: 'export-theme', + exp: 'export-theme' + } + }) + }, + import: { + cfg: make('mujs-btn', 'mujs-import sub-section hidden', { + textContent: i18n$('import_config'), + dataset: { + command: 'import-cfg', + exp: 'import-cfg' + } + }), + theme: make('mujs-btn', 'mujs-import sub-section hidden', { + textContent: i18n$('import_theme'), + dataset: { + command: 'import-theme', + exp: 'import-theme' + } + }) + } + }; + for (const value of Object.values(transfers)) { + for (const v of Object.values(value)) { + sections.exp.append(v); + } + } + cfgpage.append(cbtn); }; // #endregion @@ -3810,7 +3947,7 @@ function primaryFN() { dom.cl.add(mainframe, 'hidden'); if (cfg.autoexpand) { dom.cl.add([btnfullscreen, main], 'expanded'); - dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('fsClose')); + dom.prop(btnfullscreen, 'innerHTML', iconSVG.load('collapse')); } if (dom.cl.has(mainframe, 'error')) { tab.create('mujs:settings'); @@ -3938,11 +4075,8 @@ function primaryFN() { for (const v of cacheValues) { if (v.name && v.name.match(reg)) finds.add(v._mujs.root); if (v.description && v.description.match(reg)) finds.add(v._mujs.root); - const code_data = v._mujs.code.data; - if (code_data) { - const code_obj = new ParseUserJS(code_data); - const meta = code_obj.parse_meta(code_data); - for (const key of Object.keys(meta)) { + if (v._mujs.code.data_meta) { + for (const key of Object.keys(v._mujs.code.data_meta)) { if (/name|desc/i.test(key) && key.match(reg)) finds.add(v._mujs.root); } } diff --git a/src/UserJS/svg/bug-svgrepo-com.svg b/src/UserJS/svg/bug-svgrepo-com.svg deleted file mode 100644 index 32b7852..0000000 --- a/src/UserJS/svg/bug-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/UserJS/svg/close-svgrepo-com.svg b/src/UserJS/svg/close-svgrepo-com.svg deleted file mode 100644 index a4a1e54..0000000 --- a/src/UserJS/svg/close-svgrepo-com.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/src/UserJS/svg/download-svgrepo-com.svg b/src/UserJS/svg/download-svgrepo-com.svg deleted file mode 100644 index 9b8cf09..0000000 --- a/src/UserJS/svg/download-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/UserJS/svg/expand-full-fullscreen-svgrepo-com.svg b/src/UserJS/svg/expand-full-fullscreen-svgrepo-com.svg deleted file mode 100644 index 53218ff..0000000 --- a/src/UserJS/svg/expand-full-fullscreen-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/UserJS/svg/filter-svgrepo-com.svg b/src/UserJS/svg/filter-svgrepo-com.svg deleted file mode 100644 index 8a5d29e..0000000 --- a/src/UserJS/svg/filter-svgrepo-com.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/UserJS/svg/fork-svgrepo-com.svg b/src/UserJS/svg/fork-svgrepo-com.svg deleted file mode 100644 index 8087aa8..0000000 --- a/src/UserJS/svg/fork-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/UserJS/svg/fullscreen-svgrepo-com.svg b/src/UserJS/svg/fullscreen-svgrepo-com.svg deleted file mode 100644 index 15379af..0000000 --- a/src/UserJS/svg/fullscreen-svgrepo-com.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UserJS/svg/github-svgrepo-com.svg b/src/UserJS/svg/github-svgrepo-com.svg deleted file mode 100644 index eaac757..0000000 --- a/src/UserJS/svg/github-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/UserJS/svg/minus-svgrepo-com.svg b/src/UserJS/svg/minus-svgrepo-com.svg deleted file mode 100644 index 4f655c0..0000000 --- a/src/UserJS/svg/minus-svgrepo-com.svg +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/src/UserJS/svg/navigation-svgrepo-com.svg b/src/UserJS/svg/navigation-svgrepo-com.svg deleted file mode 100644 index 3b865b1..0000000 --- a/src/UserJS/svg/navigation-svgrepo-com.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - ic_fluent_navigation_24_filled - Created with Sketch. - - - - - - \ No newline at end of file diff --git a/src/UserJS/svg/plus-svgrepo-com.svg b/src/UserJS/svg/plus-svgrepo-com.svg deleted file mode 100644 index 66a5b01..0000000 --- a/src/UserJS/svg/plus-svgrepo-com.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/UserJS/svg/search-svgrepo-com.svg b/src/UserJS/svg/search-svgrepo-com.svg deleted file mode 100644 index eb7f58d..0000000 --- a/src/UserJS/svg/search-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/UserJS/svg/settings-svgrepo-com.svg b/src/UserJS/svg/settings-svgrepo-com.svg deleted file mode 100644 index eaeef67..0000000 --- a/src/UserJS/svg/settings-svgrepo-com.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 87d600a..470b48c 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -93,7 +93,7 @@ "message": "Preview Code" }, "saveFile": { - "message": "Save File" + "message": "Download" }, "newTab": { "message": "New Tab" @@ -141,7 +141,7 @@ "message": "Close Userscript+" }, "userjs_sync": { - "message": "Sync with UserScript Manager" + "message": "Sync" }, "userjs_autoinject": { "message": "Inject on load" diff --git a/src/sass/_main.scss b/src/sass/_main.scss index b4d429d..257468a 100644 --- a/src/sass/_main.scss +++ b/src/sass/_main.scss @@ -30,6 +30,12 @@ mujs-root { } mujs-root * { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + scrollbar-color: var(--mujs-txt-color, hsl(0, 0%, 100%)) hsl(224, 14%, 21%); + scrollbar-width: thin; + @supports not (scrollbar-width: thin) { ::-webkit-scrollbar { width: 1.4vw; @@ -61,9 +67,6 @@ mujs-root * { background: var(--mujs-txt-color, hsl(0, 0%, 100%)); } } - - scrollbar-color: var(--mujs-txt-color, hsl(0, 0%, 100%)) hsl(224, 14%, 21%); - scrollbar-width: thin; } @at-root mu-js { @@ -87,10 +90,6 @@ td.mujs-list { font-weight: 500; } -.mujs-sty-flex>mujs-btn { - margin: auto; -} - .mujs-invalid { border-radius: 8px !important; border-width: 2px !important; @@ -111,10 +110,6 @@ mujs-row { } mujs-column { - @media screen and (max-width: 800px) { - flex-flow: row wrap; - } - count-frame { &[data-counter="greasyfork"] { background: var(--mujs-gf-color, hsl(204, 100%, 40%)); @@ -132,6 +127,10 @@ mujs-column { background: hsla(12, 86%, 50%, 0.568); } } + + @media screen and (max-width: 800px) { + flex-flow: row wrap; + } } mujs-row { @@ -148,6 +147,13 @@ mu-js { } mujs-main { + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + background: var(--mujs-background-color, hsl(222, 14%, 33%)) !important; + border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); + border-radius: 16px; + @media screen and (max-height: 720px) { &:not(.webext-page) { height: 100% !important; @@ -157,13 +163,6 @@ mujs-main { } } - width: 100%; - width: -moz-available; - width: -webkit-fill-available; - background: var(--mujs-background-color, hsl(222, 14%, 33%)) !important; - border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); - border-radius: 16px; - &.expanded { height: 100% !important; bottom: 0rem !important; @@ -240,6 +239,10 @@ mujs-main { border-radius: 4px; background: transparent; + @media screen and (max-width: 800px) { + min-width: 6em !important; + } + &.active { background: var(--mujs-even-row, hsl(222, 14%, 18%)); } @@ -289,25 +292,33 @@ mujs-main { // background: var(--mujs-background-color, hsl(222, 14%, 33%)); background: hsla(0, 0%, 0%, 0); color: var(--mujs-txt-color, hsl(0, 0%, 100%)); - } - input:not([type='checkbox']) { - border: transparent; - outline: none !important; + &:not([type='checkbox']) { + border: transparent; + outline: none !important; + } } + mujs-page, textarea { background: inherit; overflow-y: auto; - color: var(--mujs-placeholder, hsl(81, 56%, 54%)); - // background: var(--mujs-even-row, hsl(222, 14%, 18%)); - // border: 1px solid transparent; border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); - border-radius: 10px; - resize: vertical; + border-radius: 5px; outline: none; font-family: monospace; font-size: 14px; + } + + mujs-page { + padding: 0.5em; + margin: 0.5em; + } + + textarea { + overflow-y: auto; + color: var(--mujs-placeholder, hsl(81, 56%, 54%)); + resize: vertical; &:focus { outline: none; @@ -347,8 +358,7 @@ mujs-main { align-items: center; justify-content: center; - svg, - img { + svg { width: 14px; height: 14px; background: transparent; @@ -450,9 +460,6 @@ mujs-header { order: 1; display: flex; border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); - // border-top-left-radius: 10px; - // border-top-right-radius: 10px; - // padding: .5em; padding-left: .5em; padding-right: .5em; padding-bottom: .5em; @@ -486,10 +493,6 @@ mujs-header { order: 1; } - .mujs-sty-flex { - order: 2; - } - .btn-frame { order: 999999999999; } @@ -500,7 +503,6 @@ mujs-body { overflow-x: hidden; padding: 0px; height: 100%; - border: 1px solid var(--mujs-border-b-color, hsla(0, 0%, 0%, 0)); border-bottom-left-radius: 16px; border-bottom-right-radius: 16px; @@ -528,6 +530,10 @@ mujs-body { } table { + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + @media screen and (max-width: 1180px) { thead>tr { display: table-column; @@ -538,13 +544,11 @@ mujs-body { display: flex; flex-flow: row wrap; align-items: center; - border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); padding-top: .5em; padding-bottom: .5em; td { margin: auto; - border-bottom: 1px solid transparent; >mujs-a, >mu-js, @@ -553,9 +557,33 @@ mujs-body { justify-content: center; } + >mujs-a { + width: 100%; + } + + >mujs-column { + @media screen and (max-width: 800px) { + flex-flow: column wrap; + + >mujs-row { + align-content: center; + } + + mujs-column { + justify-content: center; + } + } + } + &:not(.mujs-name, .install-btn) { width: 25%; } + + &.install-btn { + @media screen and (max-width: 800px) { + width: 100%; + } + } } .mujs-name { @@ -576,37 +604,37 @@ mujs-body { } } - width: 100%; - width: -moz-available; - width: -webkit-fill-available; - - th, - td { - border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); - } - th { position: -webkit-sticky; position: sticky; top: 0; background: hsla(222, 14%, 33%, 0.75); + border-bottom: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); &.mujs-header-name { + width: 50%; + @media screen and (max-width: 800px) { width: auto !important; } - - width: 50%; } } .frame { &:nth-child(even) { background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; + + textarea { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; + } } &:nth-child(odd) { background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; + + textarea { + background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; + } } &:not([data-engine="sleazyfork"], [data-engine="greasyfork"]) { @@ -714,13 +742,9 @@ mujs-body { } svg { + width: 12px; + height: 12px; fill: currentColor; - } - - svg, - img { - width: 14px; - height: 14px; background: transparent; } @@ -749,6 +773,10 @@ mujs-body { >mujs-column { >mu-jsbtn { padding: 0px 7px; + + @media screen and (max-width: 800px) { + width: 100%; + } } } } @@ -803,6 +831,26 @@ mujs-body { } } } + + @media screen and (max-width: 800px) { + width: 30em !important; + } + } + + [data-name="license"] { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; + // max-width: 20em; + + @media screen and (max-width: 800px) { + width: 100% !important; + width: -moz-available !important; + width: -webkit-fill-available !important; + } } } } @@ -815,36 +863,46 @@ mujs-body { } .mujs-cfg { - @media screen and (max-height: 720px) { - &:not(.webext-page) { - height: 100%; - height: -moz-available; - height: -webkit-fill-available; - width: 100%; - width: -moz-available; - width: -webkit-fill-available; - overflow-x: auto; - padding: .5em; - } - } - - height: fit-content; - height: -moz-fit-content; - height: -webkit-fit-content; - mujs-section { border-radius: 16px; padding: .5em; &:nth-child(even) { background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; + + input, + select { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)); + } + + select option { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)); + + &:hover { + background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; + } + } } &:nth-child(odd) { background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; + + input, + select { + background: var(--mujs-even-row, hsl(222, 14%, 18%)); + } + + select option { + background: var(--mujs-even-row, hsl(222, 14%, 18%)); + + &:hover { + background: var(--mujs-odd-row, hsl(222, 14%, 33%)) !important; + } + } } &[data-name='theme'], + &[data-name='exp'], &[data-name='blacklist'] { display: flex; justify-content: space-between; @@ -855,6 +913,15 @@ mujs-body { // order: 999999999999; // font-size: 20px; // } + >mujs-btn { + &:hover { + background: var(--mujs-even-row, hsl(222, 14%, 18%)) !important; + } + + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + } } input[type='text']::-webkit-input-placeholder { @@ -903,48 +970,44 @@ mujs-body { } } - &.sub-section { - padding: 0.20em; - } - - // display: flex; - // justify-content: space-between; - input:not([type='checkbox']) { font-size: 14px; position: relative; border-radius: 4px; border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); } + } - // input[type='text']::-webkit-input-placeholder { - // color: var(--mujs-placeholder, hsl(81, 56%, 54%)); - // } + select, + select option { + color: var(--mujs-txt-color, hsl(0, 0%, 100%)); + border: 1px solid transparent; + list-style: none; + outline-style: none; + pointer-events: auto; + } - // input[type='text']::-moz-placeholder { - // color: var(--mujs-placeholder, hsl(81, 56%, 54%)); - // } + select { + text-align: center; + border-radius: 4px; + } - // input[type='text']:-ms-input-placeholder { - // color: var(--mujs-placeholder, hsl(81, 56%, 54%)); - // } + >*.sub-section { + padding: 0.20em; - // input[type='text']::-ms-input-placeholder { - // color: var(--mujs-placeholder, hsl(81, 56%, 54%)); - // } + &[data-engine] { + flex-wrap: wrap; - // input[type='text']::placeholder { - // color: var(--mujs-placeholder, hsl(81, 56%, 54%)); - // } - } + input { + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + } + } - >input { - width: 100%; - width: -moz-available; - width: -webkit-fill-available; - margin-top: 5px; - border-radius: 4px; - border: 1px solid var(--mujs-txt-color, hsl(0, 0%, 100%)); + input[type='text'] { + margin: 0.2em 0px; + } } } @@ -964,9 +1027,12 @@ mujs-body { } } - &[data-name='greasyfork']:checked+label, + &[data-name='greasyfork']:checked+label { + background: var(--mujs-gf-color, hsl(204, 100%, 40%)); + } + &[data-name='sleazyfork']:checked+label { - background: var(--mujs-chck-gf, hsla(197, 100%, 50%, 0.568)); + background: var(--mujs-sf-color, hsl(12, 86%, 50%)); } &[data-name='openuserjs']:checked+label { @@ -1003,6 +1069,8 @@ mujs-body { .mujs-sty-flex { mujs-btn { + margin: auto; + &[data-command="reset"] { background: var(--mujs-sf-btn-color, hsl(12, 86%, 50%)); border-color: var(--mujs-sf-btn-color, hsl(12, 86%, 50%)); @@ -1028,6 +1096,23 @@ mujs-body { &:not(.webext-page) { margin: 1rem 25rem; } + + height: fit-content; + height: -moz-fit-content; + height: -webkit-fit-content; + + @media screen and (max-height: 720px) { + &:not(.webext-page) { + height: 100%; + height: -moz-available; + height: -webkit-fill-available; + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + overflow-x: auto; + padding: .5em; + } + } } mujs-a { @@ -1058,13 +1143,9 @@ mujs-btn { padding: 6px 15px; svg { - fill: var(--mujs-txt-color, hsl(0, 0%, 100%)); - } - - svg, - img { width: 14px; height: 14px; + fill: var(--mujs-txt-color, hsl(0, 0%, 100%)); } } @@ -1083,25 +1164,9 @@ mu-jsbtn { mujs-a, mu-jsbtn, .mujs-pointer, -.mujs-cfg mujs-section *:not(input[type='password'], input[type='text'], input[type='number'], [data-theme], [data-blacklist]), +.mujs-cfg mujs-section *:not(input[type='text'], input[type='number'], [data-theme], [data-blacklist]), .mainbtn, .mainframe, mujs-btn { cursor: pointer !important; } - -// .install-link { -// transition: box-shadow .2s; -// display: inline-block; -// background-color: hsl(120, 100%, 16%); -// padding: .5em 1em; -// color: hsl(0, 0%, 100%); -// text-decoration: none; -// border-radius: .25rem 0 0 .25rem; -// } - -// .install-help { -// background-color: hsl(120, 67%, 35%); -// color: hsl(0, 0%, 100%); -// border-radius: 0 .25rem .25rem 0; -// } diff --git a/src/sass/magicuserjs.scss b/src/sass/magicuserjs.scss index 326e3de..ec6651f 100644 --- a/src/sass/magicuserjs.scss +++ b/src/sass/magicuserjs.scss @@ -1,3 +1,3 @@ @charset 'UTF-8'; -@import 'main'; +@use 'main'; diff --git a/src/typings/UserJS.d.ts b/src/typings/UserJS.d.ts index db953c1..03fbe6e 100644 --- a/src/typings/UserJS.d.ts +++ b/src/typings/UserJS.d.ts @@ -9,6 +9,7 @@ export interface safeHandles { // createPolicy(): void; // }; XMLHttpRequest: typeof XMLHttpRequest; + CustomEvent: typeof CustomEvent; createElement: typeof document.createElement; createElementNS: typeof document.createElementNS; createTextNode: typeof document.createTextNode; diff --git a/src/typings/types.d.ts b/src/typings/types.d.ts index 3dda759..2d5c78c 100644 --- a/src/typings/types.d.ts +++ b/src/typings/types.d.ts @@ -58,14 +58,22 @@ export type GSForkQuery = { host?: string; }; code: { - antifeatures: string[]; - data?: string; - code_size?: string[]; - translated?: boolean; - grant: string[]; - match: string[]; meta: UserJSMeta | null; request(): Promise; + + code_size?: string[]; + translated?: boolean; + code?: string; + data_meta_block?: string; + data_code_block?: string; + data_meta?: { + [meta: string]: string | string[] | { [resource: string]: string }; + }; + data_names?: { + text: string; + domain: boolean; + tld_extra: boolean; + }[]; }; root?: HTMLTableRowElement; }; @@ -94,9 +102,9 @@ export type GSFork = { export type UserJSEngine = { enabled: boolean; name: string; - url: string; + url?: string; token?: string; - query?: string; + query: string; }; export interface FilterLayout { @@ -136,7 +144,10 @@ export type config = { /** * Fetch all UserScript code on load */ - codePreview: boolean; + preview: { + code: boolean; + metadata: boolean; + }; /** * `UserScript:` Fullscreen list on load */ @@ -362,9 +373,11 @@ export declare function make< A extends keyof HTMLElementTagNameMap[K] >( tagName: K, - cname?: string | { - [key in A]: Record; - }, + cname?: + | string + | { + [key in A]: Record; + }, attrs?: { [key in A]: Record; } From d96c8e1775a0835911539e7b0780b4736c987af7 Mon Sep 17 00:00:00 2001 From: Magic Date: Wed, 5 Mar 2025 15:44:26 -0800 Subject: [PATCH 18/35] Update Signed-off-by: Magic --- .github/ISSUE_TEMPLATE/01_bug_report.yml | 9 ++++++++- .github/ISSUE_TEMPLATE/02_feature_request.yml | 2 +- README.md | 4 +--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.yml b/.github/ISSUE_TEMPLATE/01_bug_report.yml index 43b0b0f..ebbcfd9 100644 --- a/.github/ISSUE_TEMPLATE/01_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -34,6 +34,13 @@ body: description: What browser are you seeing this bug on? validations: required: true + - type: input + id: userjs-manager + attributes: + label: User Script Manager + description: What user script manager are you using? - not required when using Web Extension + validations: + required: false - type: input id: url attributes: @@ -60,4 +67,4 @@ body: 1. Console error '...' 1. etc. validations: - required: false \ No newline at end of file + required: false diff --git a/.github/ISSUE_TEMPLATE/02_feature_request.yml b/.github/ISSUE_TEMPLATE/02_feature_request.yml index 389a6b1..990c982 100644 --- a/.github/ISSUE_TEMPLATE/02_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/02_feature_request.yml @@ -11,4 +11,4 @@ body: label: Feature description description: A clear and concise description, please include if your feature request is related to a problem. validations: - required: true \ No newline at end of file + required: true diff --git a/README.md b/README.md index 58acd8e..d1d7abd 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,12 @@ --- -
-

+

Magic Userscript+

-
*A complete rewrite of [Userscript+ : Show Site All UserJS](https://github.com/jae-jae/Userscript-Plus)* From 869ca4b45b210c9d9f174cdcd5d714b89492178c Mon Sep 17 00:00:00 2001 From: Magic Date: Wed, 5 Mar 2025 15:46:44 -0800 Subject: [PATCH 19/35] Updated CHANGELOG.user.md Signed-off-by: Magic --- CHANGELOG.user.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 4094647..0666047 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -3,6 +3,7 @@ ## v7.6.0 * New feature, `Preview Metadata` - same as `Preview Code` but loads userscripts metadata head +* New feature, `Page` - loads additonal information from userscripts homepage * Config changes, moved `codePreview` value to `preview: code`, recommended resetting your config to clear any old/unused settings. * If you had `Preview Code` enabled, you will need to re-enable it * When `Preview Metadata` and `Preview Code` are both enabled, it will display the entire userscript From 9b02edc5b554833ec8702dc4b5a6130f3914ff72 Mon Sep 17 00:00:00 2001 From: Magic Date: Wed, 5 Mar 2025 21:47:05 -0800 Subject: [PATCH 20/35] UserJS v7.6.1 Signed-off-by: Magic --- CHANGELOG.user.md | 4 ++++ UserJS.json | 2 +- dist/magic-userjs.meta.js | 2 +- dist/magic-userjs.user.js | 4 ++-- src/UserJS/main.js | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.user.md b/CHANGELOG.user.md index 0666047..05a730f 100644 --- a/CHANGELOG.user.md +++ b/CHANGELOG.user.md @@ -1,5 +1,9 @@ # Changelog +## v7.6.1 + +* Fixed sorting + ## v7.6.0 * New feature, `Preview Metadata` - same as `Preview Code` but loads userscripts metadata head diff --git a/UserJS.json b/UserJS.json index 24fd9a8..90189d0 100644 --- a/UserJS.json +++ b/UserJS.json @@ -1,5 +1,5 @@ { - "version": "7.6.0", + "version": "7.6.1", "name": "Magic Userscript+ : Show Site All UserJS", "description": "Finds available userscripts for the current webpage.", "author": "Magic ", diff --git a/dist/magic-userjs.meta.js b/dist/magic-userjs.meta.js index 091b951..02219d3 100644 --- a/dist/magic-userjs.meta.js +++ b/dist/magic-userjs.meta.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.6.0 +// @version 7.6.1 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS diff --git a/dist/magic-userjs.user.js b/dist/magic-userjs.user.js index 4a35efc..764d5f7 100644 --- a/dist/magic-userjs.user.js +++ b/dist/magic-userjs.user.js @@ -1,5 +1,5 @@ // ==UserScript== -// @version 7.6.0 +// @version 7.6.1 // @name Magic Userscript+ : Show Site All UserJS // @name:ar Magic Userscript+: عرض جميع ملفات UserJS // @name:de Magic Userscript+ : Website anzeigen Alle UserJS @@ -3026,7 +3026,7 @@ class Container { this.tab.create(host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => tr.children[idx].dataset.value; + const getCellValue = (tr, idx) => tr.children[idx].dataset.value || tr.children[idx].textContent; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) diff --git a/src/UserJS/main.js b/src/UserJS/main.js index 941cb25..037c9f7 100644 --- a/src/UserJS/main.js +++ b/src/UserJS/main.js @@ -1352,7 +1352,7 @@ class Container { this.tab.create(host); const tabbody = this.tabbody; - const getCellValue = (tr, idx) => tr.children[idx].dataset.value; + const getCellValue = (tr, idx) => tr.children[idx].dataset.value || tr.children[idx].textContent; const comparer = (idx, asc) => (a, b) => ((v1, v2) => v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) From 066972197394ae37a2acd9c444e9dee5a389ede1 Mon Sep 17 00:00:00 2001 From: Magic Date: Mon, 10 Mar 2025 15:28:35 -0700 Subject: [PATCH 21/35] Added FUNDING.yml Signed-off-by: Magic --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..8bcae8b --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: magicoflolis From 0823856511647fddeca9e74668388b9af70d2f2c Mon Sep 17 00:00:00 2001 From: Magic Date: Mon, 10 Mar 2025 16:15:34 -0700 Subject: [PATCH 22/35] Web Extension v6.0.0 Signed-off-by: Magic --- README.md | 24 +- dist/userscript_plus-5.0.0.xpi | Bin 162736 -> 0 bytes package.json | 2 +- src/_locales/en_GB/messages.json | 8 +- src/_locales/zh/messages.json | 2 +- src/html/background.html | 14 - src/html/form.html | 68 - src/html/popup.html | 115 +- src/html/settings.html | 26 - src/img/icon_16.png | Bin 846 -> 730 bytes src/img/icon_32.png | Bin 1144 -> 1547 bytes src/img/icon_48.png | Bin 0 -> 2376 bytes src/img/icon_64.png | Bin 0 -> 5714 bytes src/img/verified-svgrepo-com.svg | 1 + src/js/background.js | 983 ++-- src/js/config.js | 210 - src/js/constants.js | 88 + src/js/container.js | 119 + src/js/ext.js | 34 + src/js/i18n.js | 29 +- src/js/language.js | 26 - src/js/logger.js | 5 - src/js/messager.js | 124 + src/js/mu-common.js | 385 -- src/js/mu-hermes.js | 126 - src/js/network.js | 80 +- src/js/popup.js | 2393 +++++--- src/js/punycode.js | 493 ++ src/js/querySelector.js | 10 +- src/js/request-code.js | 476 +- src/js/settings.js | 294 - src/js/storage.js | 118 +- src/js/util.js | 192 +- src/manifest/chrome.json | 31 +- src/manifest/firefox.json | 58 +- src/sass/_main.scss | 2 +- src/sass/fontawesome/_animated.scss | 152 + src/sass/fontawesome/_bordered-pulled.scss | 20 + src/sass/fontawesome/_core.scss | 49 + src/sass/fontawesome/_fixed-width.scss | 7 + src/sass/fontawesome/_functions.scss | 57 + src/sass/fontawesome/_icons.scss | 12 + src/sass/fontawesome/_list.scss | 18 + src/sass/fontawesome/_mixins.scss | 65 + src/sass/fontawesome/_rotated-flipped.scss | 31 + src/sass/fontawesome/_screen-reader.scss | 14 + src/sass/fontawesome/_shims.scss | 1578 ++++++ src/sass/fontawesome/_sizing.scss | 16 + src/sass/fontawesome/_stacked.scss | 32 + src/sass/fontawesome/_variables.scss | 5044 +++++++++++++++++ src/sass/fontawesome/brands.scss | 30 + src/sass/fontawesome/fontawesome.scss | 21 + src/sass/fontawesome/regular.scss | 27 + src/sass/fontawesome/solid.scss | 27 + src/sass/fontawesome/v4-shims.scss | 11 + src/sass/fonts/Inter-Regular.woff2 | Bin 98868 -> 0 bytes src/sass/fonts/Inter-SemiBold.woff2 | Bin 105804 -> 0 bytes src/sass/web-ext.scss | 25 +- src/svg/bug-svgrepo-com.svg | 1 - src/svg/checkmark-seal-svgrepo-com.svg | 1 - src/svg/close-svgrepo-com.svg | 8 - src/svg/download-svgrepo-com.svg | 1 - .../expand-full-fullscreen-svgrepo-com.svg | 1 - src/svg/filter-svgrepo-com.svg | 1 - src/svg/fork-svgrepo-com.svg | 1 - src/svg/fullscreen-svgrepo-com.svg | 63 - src/svg/github-svgrepo-com.svg | 1 - src/svg/minus-svgrepo-com.svg | 2 - src/svg/navigation-svgrepo-com.svg | 8 - src/svg/plus-svgrepo-com.svg | 1 - src/svg/search-svgrepo-com.svg | 1 - src/svg/settings-svgrepo-com.svg | 4 - src/webfonts/fa-brands-400.ttf | Bin 0 -> 210792 bytes src/webfonts/fa-brands-400.woff2 | Bin 0 -> 118684 bytes src/webfonts/fa-regular-400.ttf | Bin 0 -> 68064 bytes src/webfonts/fa-regular-400.woff2 | Bin 0 -> 25472 bytes src/webfonts/fa-solid-900.ttf | Bin 0 -> 426112 bytes src/webfonts/fa-solid-900.woff2 | Bin 0 -> 158220 bytes src/webfonts/fa-v4compatibility.ttf | Bin 0 -> 10836 bytes src/webfonts/fa-v4compatibility.woff2 | Bin 0 -> 4796 bytes tools/webpack.config.js | 6 +- 81 files changed, 10681 insertions(+), 3191 deletions(-) delete mode 100644 dist/userscript_plus-5.0.0.xpi delete mode 100644 src/html/background.html delete mode 100644 src/html/form.html delete mode 100644 src/html/settings.html create mode 100644 src/img/icon_48.png create mode 100644 src/img/icon_64.png create mode 100644 src/img/verified-svgrepo-com.svg delete mode 100644 src/js/config.js create mode 100644 src/js/constants.js create mode 100644 src/js/container.js create mode 100644 src/js/ext.js delete mode 100644 src/js/language.js create mode 100644 src/js/messager.js delete mode 100644 src/js/mu-common.js delete mode 100644 src/js/mu-hermes.js create mode 100644 src/js/punycode.js delete mode 100644 src/js/settings.js create mode 100644 src/sass/fontawesome/_animated.scss create mode 100644 src/sass/fontawesome/_bordered-pulled.scss create mode 100644 src/sass/fontawesome/_core.scss create mode 100644 src/sass/fontawesome/_fixed-width.scss create mode 100644 src/sass/fontawesome/_functions.scss create mode 100644 src/sass/fontawesome/_icons.scss create mode 100644 src/sass/fontawesome/_list.scss create mode 100644 src/sass/fontawesome/_mixins.scss create mode 100644 src/sass/fontawesome/_rotated-flipped.scss create mode 100644 src/sass/fontawesome/_screen-reader.scss create mode 100644 src/sass/fontawesome/_shims.scss create mode 100644 src/sass/fontawesome/_sizing.scss create mode 100644 src/sass/fontawesome/_stacked.scss create mode 100644 src/sass/fontawesome/_variables.scss create mode 100644 src/sass/fontawesome/brands.scss create mode 100644 src/sass/fontawesome/fontawesome.scss create mode 100644 src/sass/fontawesome/regular.scss create mode 100644 src/sass/fontawesome/solid.scss create mode 100644 src/sass/fontawesome/v4-shims.scss delete mode 100644 src/sass/fonts/Inter-Regular.woff2 delete mode 100644 src/sass/fonts/Inter-SemiBold.woff2 delete mode 100644 src/svg/bug-svgrepo-com.svg delete mode 100644 src/svg/checkmark-seal-svgrepo-com.svg delete mode 100644 src/svg/close-svgrepo-com.svg delete mode 100644 src/svg/download-svgrepo-com.svg delete mode 100644 src/svg/expand-full-fullscreen-svgrepo-com.svg delete mode 100644 src/svg/filter-svgrepo-com.svg delete mode 100644 src/svg/fork-svgrepo-com.svg delete mode 100644 src/svg/fullscreen-svgrepo-com.svg delete mode 100644 src/svg/github-svgrepo-com.svg delete mode 100644 src/svg/minus-svgrepo-com.svg delete mode 100644 src/svg/navigation-svgrepo-com.svg delete mode 100644 src/svg/plus-svgrepo-com.svg delete mode 100644 src/svg/search-svgrepo-com.svg delete mode 100644 src/svg/settings-svgrepo-com.svg create mode 100644 src/webfonts/fa-brands-400.ttf create mode 100644 src/webfonts/fa-brands-400.woff2 create mode 100644 src/webfonts/fa-regular-400.ttf create mode 100644 src/webfonts/fa-regular-400.woff2 create mode 100644 src/webfonts/fa-solid-900.ttf create mode 100644 src/webfonts/fa-solid-900.woff2 create mode 100644 src/webfonts/fa-v4compatibility.ttf create mode 100644 src/webfonts/fa-v4compatibility.woff2 diff --git a/README.md b/README.md index d1d7abd..fc8b98f 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Finds available UserScripts and UserStyles for the current webpage, the power of [UserScript Changelog](https://github.com/magicoflolis/Userscript-Plus/blob/master/CHANGELOG.user.md) +[Web Extension Changelog](https://github.com/magicoflolis/Userscript-Plus/releases) + [List of known issues by Web Browser](https://github.com/magicoflolis/Userscript-Plus/blob/master/browser-issues.md) ## **Download** @@ -31,17 +33,23 @@ Finds available UserScripts and UserStyles for the current webpage, the power of * [Open UserJS](https://openuserjs.org/scripts/Magic/Magic_Userscript+_Show_Site_All_UserJS) - outdated * [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/blob/master/dist/magic-userjs.user.js?raw=1) -**Web Extension (under construction):** +**Web Extension:** + +*General:* + +* [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases) *Firefox:* * [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/userscript-plus/) -* [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest) *Chromium:* -* ~~[Chrome Web Store](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest)~~ -* [GitHub Repo](https://github.com/magicoflolis/Userscript-Plus/releases/tag/webext/latest) +* ~~[Chrome Web Store](https://chromewebstore.google.com/detail/kbelpalpbddhjhoakbjkfookjeiennbo)~~ - Under review + +*Microsoft Edge:* + +* ~~[Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/golkolijobdaldjgefapmcknlmkjlhdh)~~ - Under review **Bookmarklet (not recommended):** @@ -61,7 +69,6 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * Query UserScripts and UserStyles from: * [Greasy Fork](https://greasyfork.org) - enabled by default * [Sleazy Fork](https://sleazyfork.org) - disabled by default - * [Open UserJS](https://openuserjs.org) ( limited availability, will read `Too many requests...` if limit is reached ) - disabled by default * [GitHub](https://github.com/search?l=JavaScript&o=desc&q="==UserScript==") ( requires [Personal Access Token](https://github.com/settings/tokens), no permissions are required ) - disabled by default * Built-in UserScripts: * [GreasyFork Bullshit Filter](https://greasyfork.org/scripts/12179) - disabled by default @@ -88,6 +95,8 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * Maximize, minimize, or close menu * Sync config with UserScript manager or per host * Customize timeout window - can be re-injected using your managers User Script Commands menu +* Query UserScripts and UserStyles from: + * [Open UserJS](https://openuserjs.org) ( limited availability, will read `Too many requests...` if limit is reached ) - disabled by default * Automation: * Inject on load - injects menu on page load * Automatic fullscreen - maximizes menu when opened @@ -95,6 +104,11 @@ javascript:(function(){['https://cdn.jsdelivr.net/gh/magicoflolis/Userscript-Plu * Inject Userscript+ - injects menu into the page * Close Userscript+ - removes menu from the page +**Web Extension Features:** + +* General: + * You can fullscreen the list and it will open it to a new tab + ## Previews

diff --git a/dist/userscript_plus-5.0.0.xpi b/dist/userscript_plus-5.0.0.xpi deleted file mode 100644 index eec2c4a42c9dfb7b68998ff84b5c4ee85268463f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162736 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%0AIe{Ozau%skD5ecr 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 z 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", - "version": "5.0.2", + "version": "6.0.0", "license": "MIT", "homepage": "https://github.com/magicoflolis/Userscript-Plus", "bugs": { diff --git a/src/_locales/en_GB/messages.json b/src/_locales/en_GB/messages.json index 9ac0ef7..470b48c 100644 --- a/src/_locales/en_GB/messages.json +++ b/src/_locales/en_GB/messages.json @@ -42,7 +42,7 @@ "message": "Search" }, "search_placeholder": { - "message": "Search scripts" + "message": "Search for userscripts" }, "install": { "message": "Install" @@ -66,7 +66,7 @@ "message": "Good" }, "ok": { - "message": "Ok" + "message": "Okay" }, "bad": { "message": "Bad" @@ -93,7 +93,7 @@ "message": "Preview Code" }, "saveFile": { - "message": "Save File" + "message": "Download" }, "newTab": { "message": "New Tab" @@ -141,7 +141,7 @@ "message": "Close Userscript+" }, "userjs_sync": { - "message": "Sync with UserScript Manager" + "message": "Sync" }, "userjs_autoinject": { "message": "Inject on load" diff --git a/src/_locales/zh/messages.json b/src/_locales/zh/messages.json index 6304bae..ba2ca67 100644 --- a/src/_locales/zh/messages.json +++ b/src/_locales/zh/messages.json @@ -4,7 +4,7 @@ "description": "Must not exceed 45 characters" }, "extDesc": { - "message": "The power of Greasy Fork on the go! Finds available UserJS for the current webpage.", + "message": "为当前网页查找可用的 UserJS,随时随地发挥 Greasy Fork 的威力!", "description": "Must not exceed 132 characters" }, "extShortDesc": { diff --git a/src/html/background.html b/src/html/background.html deleted file mode 100644 index b268206..0000000 --- a/src/html/background.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - Magic UserJS+ Background Page - - - - - - - diff --git a/src/html/form.html b/src/html/form.html deleted file mode 100644 index 4d9e1b8..0000000 --- a/src/html/form.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - Reset - Save - diff --git a/src/html/popup.html b/src/html/popup.html index 111813b..2357f06 100644 --- a/src/html/popup.html +++ b/src/html/popup.html @@ -2,56 +2,17 @@ - - - + + - + - - - - + - - - - - + >
-

+ - - - diff --git a/src/html/settings.html b/src/html/settings.html deleted file mode 100644 index 335a789..0000000 --- a/src/html/settings.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - UserJS - Settings - - - - -

Settings

- - -
- -
-
-
- - - - - - diff --git a/src/img/icon_16.png b/src/img/icon_16.png index 03a9c49aece0c9849f911d1166897fc2546cdb12..950710b607a93809021bf747dc5ea319b521b729 100644 GIT binary patch delta 707 zcmV;!0zCcB2HFLXBYyw^b5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGq zB>(^xB>_oNB=7(L0&ht~K~y+TbyG`AqG1&N67hzHhFw&c)O1mHB`;BumWi39V2WYIJny-E(tqIacsv(@ zK;SJNk9VC;XLn*^;x&`Wl*OIBNBIKF%ga}xPzV-_1?%hU2nK`L+}uPim&4iF8HR?2 zAZR~&>`$1VpZ_U7Xti3f*=$7o$4n-ZynYh)2h-EjSN;9{Xf~TnczAe#-|t5_9A>AH zkr8;kUMLg_xPM$OjE#*^G?zVZNpc<@9^&Ta20ERNMf&>s@c#aeL?VG?G6_)&tgWqa zIx8zHSY2Jk-rgSEZa3HDVt9BMKA(?8tX3;z+~42x-r;b-Y&L^<^rfii%xE+gN#IQw zhaQba`DGdPdY#V)2M6Wc*$f5)78e(3{UV95x;r~Ne1Ab9(z@Ml6M(xlu9KRP~MX@8VweyR;wS*f7`PpDq1FG%3rh-#bOb5yB*ip*El#h zz|_6m5R^gNRE$>seo1X{0mQ1D79J*jYdN~W+xFQ@5QKN zZf=fK+}_^)ILb1_bY152dF=1+CdfGCWFUcXyYkP|&{j*k5B*%z8;Uy@(e( p;>YTU|KeGUH5Kezk0L{oegTg&YWtBPfJ6WQ002ovPDHLkV1i1zNK*g+ delta 824 zcmV-81IPT@1EX>4Tx04UFukvT{MK^TRzWh%jx$2!H6NTb!I8O;LAz-Vspi zZB%9PztNh`xF!TN;ka3JO2SLRgKMRt;$7j0xvZy!&xHFNxuEca(v32|D$e;FRGASc zl^hn12y3|-Hfq>hb}Zom;qJ6$OMY;+%xT5zimm*rS-GcrVK`&YOe?i8@JAMC@xD0WvV2Wde0v5XONBzO?ZryButeg~1K;yILz4t)V zHhgb+-q(@meIG;U2`=rbziy{D4^000McNliru=mQK7G7dT+ z$ZP-r0ZvIoK~y+Tm6NfGgFq05#qQdG5Q7K?grG$rR^lrOzJ^WOKsuWg_F4*;%3cUu z6G;Mjh<|H#ZvQ#ssWFoK;RBtW`PrG>RYtUy>?B{3?*@D$hP9XaknDZm7n-J#{2oI{ z_7ddwguthSHk%C{k4Ks?0m$u{>{V5zEX!yPx#1ZP1_K>z@;j|==^1poj532;bRa{vGq zB>(^xB>_oNB=7(L1)xbpK~z{rtyk$wmRS^kT}sr-U9*gIOiiscBF&P*!gbscj3Tix z2^Z8N6|KldEy@M=9W^vj6cPNGAA$)A`U8e>>&rj`;+HYzWq%gVoZsoWPp_}9j%Ejb z-20rno#))MUBeE@hLO(bc6WDwf8xZ6PtMNH#(n$t8EtKCKkePS_noV&YZs5FF{~Ni zjXVPb0|&~>%m3v*0n^jd6cG_Y6B84Znwm->At4kN7DlnLvDDVqMky&N|M0v%h6iI; z)adBwNDm)Aq<_-VQaK!GXlRhOv9Xa76B8*YD2Ps;JV}=?UzRcO)m+9i#*WF8u{1n9 zOr4#brke?r0BHB`-%n#>W7N^nLDA9C^!)jAdhz0gj8|4xsx=D?cgD8p2gYXxxwyE{ z%E}7$_xG!fwhbR2A3A>gxG8Uq;mg>PaA$vxkB`&Qqkl(b;ckSm0Q{IMV^dmWP;qfF z8I49da^#3CG#3I!hc+)SPi?#5zA3xIT*RS=3N(diqGbbk}T3ubG z-ripMZhvlWrl_bW%F4>3GiT1w_3PJZc6L_AdU|^Fed_A!XmoVcobSTWX`r>Wm27Nm zXnA?rvJh-knVFfSsIRY2{sxCfMn;mGn;Vstl~GeuldMxMP+MCo!lDlsg*G^lb@R7Q z`hD8j*=-P_u&|KU*4DJ6zfydByo_UW{DA2`rhoQvf)dw{WOytjtz?CjqY5)$a<&6~stM|U4(t;dcX6HRPJN{IaY ze1Ekmd3box;lqao2M-?9`3UW3hlYlTGbpb1H~uylM@B~U_^vQGIJmBbB8 z^YioC@m~l+KwD}pToWDwK$D7(gVCxz`I-?K4aUjINvf}}*CzsSGqeaY>Mvo**4EbK z@9$3w3k%xuU&!=2a&mI0qM||o4^sSBuYX=ii!_e*(4j-0aRr~CrVAG?=o0}f^z`(U zzPhuxxH$23%tg%DN(f8ff<-imJcB(rhR7AXGo54#EU?5^fT!$K2nFrRer6at71I(B z;VkhLb|VC%jbTWK5t=Y{z*4KKs`NVp1_lP`?%li6zjyDRv{qJD-zr2hLx}F*zkg2; z9z2l4aKOyWjHn5&`SRsUN>5K0z!ToQc|+H(U8A|VIWai!HnRyfGi5*7?uJ6os^hr_~=GQGUKB*}z_hl>F4UweCdL3elex|$Fz3Q@Gs#Ny(jcKjED zhvAywf?Zu*GVkiutFSLbV4YlRYJY0vFOcWq6_|uPjw?XT$8!X@0wkaF=g*4(@OcOb ze^{&5LKR-WlEw~xfkHfB9xgrJ(cf*=Tj~>b4 z8c+#uS&myIeiPQg8&D5I3v(z&@n$F}C=hE_FCcgW1VSJ8oRN_s?uu{5rUtiN!jq~e zIXU@nTnAEVb#=9r-*|@cn6!u;$aWAWG&J-t4r1_g*wl9;D+WR*%BZ&tWHJ~mfIbon gV*8JbZIZ$8AIz+%9Clj0Qvd(}07*qoM6N<$f_S6RnE(I) delta 1124 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 JRHa}U^* \ No newline at end of file diff --git a/src/js/background.js b/src/js/background.js index e8c2464..8ca0098 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -1,133 +1,312 @@ 'use strict'; + +import { webext, runtime } from './ext.js'; +import { hermes } from './messager.js'; import { log, err, info } from './logger.js'; -import { i18n$ } from './i18n.js'; -// import Config from './config.js'; import Network from './network.js'; -import { reqCode } from './request-code.js'; -import { language } from './language.js'; -import { isBlank, isNull, isEmpty, normalizeTarget, template } from './util.js'; -import { XMap } from './XMap.js'; -import storage, { storageByPrefix } from './storage.js'; - -const MUJS = { - cache: new XMap() -}; - -window.MUJS = MUJS; -window.Config = storage; -window.storageByPrefix = storageByPrefix; +import { isBlank, isNull, isEmpty, union, loadFilters, isRegExp, isObj, formatURL } from './util.js'; +import { BLANK_PAGE, template, builtinList } from './constants.js'; +import storage, { DEFAULT_CONFIG } from './storage.js'; +import { BaseContainer, BaseList } from './container.js'; /** * @type { import("../typings/types").config } */ -const cfg = {}; -/** - * @type { import("../typings/types").config } - */ -const DEFAULT_CONFIG = { - // cache: true, - codePreview: false, - // autoexpand: false, - filterlang: false, - sleazyredirect: false, - // time: 10000, - blacklist: [ - { - enabled: true, - regex: true, - flags: '', - name: 'Blacklist 1', - url: '(gov|cart|checkout|login|join|signin|signup|sign-up|password|reset|password_reset)' - }, - { - enabled: true, - regex: true, - flags: '', - name: 'Blacklist 2', - url: '(pay|bank|money|localhost|authorize|checkout|bill|wallet|router)' - }, - { - enabled: true, - regex: false, - flags: '', - name: 'Blacklist 3', - url: 'https://home.bluesnap.com' - }, - { - enabled: true, - regex: false, - flags: '', - name: 'Blacklist 4', - url: ['zalo.me', 'skrill.com'] - } - ], - engines: [ - { - enabled: true, - name: 'greasyfork', - url: 'https://greasyfork.org' - }, - { - enabled: false, - name: 'sleazyfork', - url: 'https://sleazyfork.org' - }, - { - enabled: false, - name: 'openuserjs', - url: 'https://openuserjs.org/?q=' - }, - { - enabled: false, - name: 'github', - url: 'https://api.github.com/search/code?q=', - token: '' - } - ], - theme: { - 'even-row': '', - 'odd-row': '', - 'even-err': '', - 'odd-err': '', - 'background-color': '', - 'gf-color': '', - 'sf-color': '', - 'border-b-color': '', - 'gf-btn-color': '', - 'sf-btn-color': '', - 'sf-txt-color': '', - 'txt-color': '', - 'chck-color': '', - 'chck-gf': '', - 'chck-git': '', - 'chck-open': '', - placeholder: '', - 'position-top': '', - 'position-bottom': '', - 'position-left': '', - 'position-right': '', - 'font-family': '' - }, - recommend: { - author: true, - others: true - } -}; - +let cfg = {}; const initCfg = async () => { const c = await storage.config.getMulti(); if (!c) { await storage.config.set(DEFAULT_CONFIG); } - Object.assign(cfg, c); + cfg = { + ...DEFAULT_CONFIG, + ...c + }; return cfg; }; initCfg(); -const { hermes } = userjs; +class Container extends BaseContainer { + constructor(url) { + super(url); + } + + checkBlacklist(str) { + str = str || this.host; + let blacklisted = false; + if (/accounts*\.google\./.test(str)) { + blacklisted = true; + } + const blacklist = cfg.blacklist ?? []; + for (const b of blacklist) { + if (typeof b === 'string') { + if (b.startsWith('userjs-')) { + const r = /userjs-(\w+)/.exec(b)[1]; + const biList = builtinList[r]; + if (isRegExp(biList)) { + if (!biList.test(str)) continue; + blacklisted = true; + } else if (isObj(biList) && biList.host === this.host) { + blacklisted = true; + } + } + } else if (isObj(b)) { + if (!b.enabled) { + continue; + } + if (b.regex === true) { + const reg = new RegExp(b.url, b.flags); + if (!reg.test(str)) continue; + blacklisted = true; + } + if (Array.isArray(b.url)) { + for (const c of b.url) { + if (!str.includes(c)) continue; + blacklisted = true; + } + } + if (!str.includes(b.url)) continue; + blacklisted = true; + } + } + this.isBlacklisted = blacklisted; + return this.isBlacklisted; + } +} +const container = new Container(); +// #region List +class List extends BaseList { + constructor(hostname = undefined, tabId = -2) { + super(hostname, container, cfg); + this.build = this.build.bind(this); + if (isEmpty(hostname)) hostname = BLANK_PAGE; + this.engines = cfg.engines; + this.host = hostname; + this.tabId = tabId; + } + + // #region Builder + async build() { + await initCfg(); + this.engines = cfg.engines; + const { container, blacklisted, engines, host, tabId } = this; + if (blacklisted || isEmpty(engines) || host === BLANK_PAGE) { + return []; + } + const records = []; + const fetchRecords = []; + const bsFilter = loadFilters(cfg); + const hostCache = Array.from(this); + info('Building list', { hostCache, engines, container, list: this }); + try { + const g = this.groupBy(); + if (isEmpty(g)) { + const toFetch = engines.filter((engine) => !g[engine.name]); + for (const engine of toFetch) { + info(`Fetching from "${engine.name}" for "${host}"`); + const respError = (error) => { + if (!error.cause) error.cause = engine.name; + if (error.message.startsWith('429')) { + err(`Engine: "${engine.name}" Too many requests...`); + return; + } + err(`Engine: "${engine.name}"`, error.message); + }; + const _mujs = (d) => { + const obj = { + ...template, + ...d, + _mujs: { + root: {}, + info: { + tabId, + engine, + host + }, + code: { + meta: {} + } + } + }; + // obj._mujs.code.request = (translate = false, code_url) => { + // requestUserJS.call(obj._mujs.code, translate, code_url ?? obj.code_url, obj); + // }; + return obj; + }; + /** + * Prior to UserScript v7.0.0 + * @template {string} F + * @param {F} fallback + * @returns {F} + */ + const toQuery = (fallback) => { + if (engine.query) { + return decodeURIComponent(engine.query).replace(/\{host\}/g, host); + } + return fallback; + }; + /** + * @param { import("../typings/types.d.ts").GSFork } dataQ + */ + const forkFN = async (dataQ) => { + if (!dataQ) { + err('Invalid data received from the server, check internet connection'); + return; + } + /** + * @type { import("../typings/types.d.ts").GSForkQuery[] } + */ + const dq = Array.isArray(dataQ) ? dataQ : Array.isArray(dataQ.query) ? dataQ.query : []; + const dataA = dq + .filter(Boolean) + .filter((d) => !d.deleted) + .filter(bsFilter.match); + if (isBlank(dataA)) { + // records.push(_mujs({})); + return; + } + const data = dataA.map(_mujs); + const otherLng = []; + /** + * @param {import("../typings/types.d.ts").GSForkQuery} d + * @returns {boolean} + */ + const inUserLanguage = (d) => { + if (userjs.pool.has(d.locale.split('-')[0] ?? d.locale)) { + return true; + } + otherLng.push(d); + return false; + }; + const filterLang = data.filter((d) => { + if (cfg.filterlang && !inUserLanguage(d)) { + return false; + } + return true; + }); + let finalList = filterLang; + const hds = []; + for (const ujs of otherLng) { + const c = await ujs._mujs.code.request(true); + if (c.translated) { + hds.push(ujs); + } + } + finalList = union(hds, filterLang); + + for (const ujs of finalList) { + // if (!ujs._mujs.code.data_code_block && (cfg.preview.code || cfg.preview.metadata)) { + // ujs._mujs.code.request().then(() => { + // dispatch(ujs); + // }); + // } + if (!container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); + } + records.push(...finalList); + }; + const gitFN = async (data) => { + try { + if (isBlank(data.items)) { + err('Invalid data received from the server, TODO fix this'); + return; + } + for (const r of data.items) { + const ujs = _mujs({ + id: r.repository.id ?? r.id ?? 0, + name: r.repository.name ?? r.name, + description: isEmpty(r.repository.description) + ? 'N/A' + : r.repository.description, + url: r.repository.html_url, + code_url: r.html_url.replace(/\/blob\//g, '/raw/'), + page_url: `${r.repository.url}/contents/README.md`, + users: [ + { + name: r.repository.owner.login, + url: r.repository.owner.html_url + } + ] + }); + Network.req(r.repository.url, 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).then((repository) => { + ujs.code_updated_at = r.commit || repository.updated_at || Date.now(); + ujs.created_at = repository.created_at; + ujs.daily_installs = repository.watchers_count ?? 0; + ujs.good_ratings = repository.stargazers_count ?? 0; + if (repository.license?.name) ujs.license = repository.license.name; + // dispatch(ujs); + }); + // if (!ujs._mujs.code.data_code_block && (cfg.preview.code || cfg.preview.metadata)) { + // ujs._mujs.code.request().then(() => { + // dispatch(ujs); + // }); + // } + if (!container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); + records.push(ujs); + } + } catch (ex) { + err(ex); + } + }; + let netFN; + if (/github/gi.test(engine.name)) { + if (isEmpty(engine.token)) { + err(`"${engine.name}" requires a token to use`); + continue; + } + netFN = Network.req( + toQuery( + `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30` + ), + 'GET', + 'json', + { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + } + ) + .then(gitFN) + .then(() => { + Network.req('https://api.github.com/rate_limit', 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).catch(respError); + }); + } else { + netFN = Network.req( + toQuery(`${engine.url}/scripts/by-site/${host}.json?language=all`) + ).then(forkFN); + } + if (netFN) { + fetchRecords.push(netFN.catch(respError)); + } + } + } + if (!isBlank(fetchRecords)) { + await Promise.allSettled(fetchRecords); + } + } catch (ex) { + err(ex); + } + return Array.from(this); + } + // #endregion +} +// #endregion const msgCache = {}; -webext.runtime.onConnect.addListener((p) => { +runtime.onConnect.addListener((p) => { hermes.port = p; /** * Default post message to send to all connected scripts @@ -138,532 +317,148 @@ webext.runtime.onConnect.addListener((p) => { log('Background Script: received message from content script', root); const r = root.msg; if (root.channel === 'Save') { - const v = isNull(r.value) ? cfg[r.prop] : r.value; - storage.config.setOne(r.prop, v); - } - if (root.channel === 'Reset') { + if (r.cfg) { + storage.config.set(r.cfg).then(initCfg); + } else { + const v = isNull(r.value) ? cfg[r.prop] : r.value; + storage.config.setOne(r.prop, v).then(initCfg); + } + } else if (root.channel === 'Reset') { storage.config.set(DEFAULT_CONFIG); + } else if (root.channel === 'Clear') { + const cache = Array.from(container).filter(({ _mujs }) => _mujs.info.host === r.host); + for (const ujs of cache) container.userjsCache.delete(ujs.id); + } else if (root.channel === 'Engine' && cfg.engines) { + const engine = cfg.engines.find((engine) => engine.name === r.engine.name); + for (const [k, v] of Object.entries(r.engine)) { + engine[k] = v; + } + storage.config.set(cfg).then(initCfg); } }); }); -// Unsupport webpages for each engine -const unsupported = { - greasyfork: ['pornhub.com'], - sleazyfork: ['pornhub.com'], - openuserjs: [], - github: [] -}; - -const formatURL = (txt) => - txt - .split('.') - .splice(-2) - .join('.') - .replace(/\/|https:/g, ''); - +const MUList = new List(); /** * @param {chrome.tabs.Tab} tab - * @returns {string} */ -const getTabUrl = (tab) => tab.pendingUrl || tab.url || ''; -// const queryOptions = { active: true, lastFocusedWindow: true }; -const queryOptions = { active: true, currentWindow: true }; - -// class Website { -// constructor(e) { -// this.engine = e.engine ?? {}; -// this.data = e.data ?? []; -// this.host = e.host ?? 'about:blank'; -// this.link = e.link ?? 'about:blank'; -// } - -// setData(v) { -// this.data = v ?? []; -// } -// } - -// class Engine { -// constructor(host, engine) { -// this.host = host ?? 'about:blank'; -// this.engine = engine ?? {}; -// this.data = []; -// } - -// setEngine(engine) { -// this.engine = engine; -// return this; -// } - -// setHost(host) { -// if (host !== this.host) { -// this.host = host; -// } -// return this; -// } - -// async getData() { -// if (isEmpty(this.host) || this.host === 'about:blank') { -// return [] -// } -// const engine = this.engine; -// /** -// * @param { import("../typings/types").GSFork } dataQ -// */ -// const forkFN = async (dataQ) => { -// if (!dataQ) { -// err('Invalid data received from the server, check internet connection'); -// return []; -// } -// /** -// * @type { import("../typings/types").GSForkQuery[] } -// */ -// const dq = Array.isArray(dataQ) ? dataQ : Array.isArray(dataQ.query) ? dataQ.query : []; -// const data = dq.filter((d) => !d.deleted); -// if (isBlank(data)) { -// return []; -// } -// const hideData = []; -// const inUserLanguage = (d) => { -// const dlocal = d.locale.split('-')[0] ?? d.locale; -// if (language.cache.includes(dlocal)) { -// return true; -// } -// hideData.push(d); -// return false; -// }; -// const filterLang = data.filter((d) => { -// if (cfg.filterlang && !inUserLanguage(d)) { -// return false; -// } -// return true; -// }); - -// let finalList = filterLang; -// const hds = []; -// for (const ujs of hideData) { -// await reqCode(ujs, true); -// if (ujs.translated) { -// hds.push(ujs); -// } -// } -// finalList = [...new Set([...hds, ...filterLang])]; - -// this.data.push(...finalList); -// return finalList; -// }; -// const gitFN = async (data) => { -// const records = []; -// try { -// if (isBlank(data.items)) { -// err('Invalid data received from the server, TODO fix this'); -// return; -// } -// for (const r of data.items) { -// const ujs = template.merge({ -// name: r.name, -// description: isEmpty(r.repository.description) -// ? i18n$('no_license') -// : r.repository.description, -// url: r.html_url, -// code_url: r.html_url.replace(/\/blob\//g, '/raw/'), -// code_updated_at: r.commit || Date.now(), -// total_installs: r.score, -// users: [ -// { -// name: r.repository.owner.login, -// url: r.repository.owner.html_url -// } -// ] -// }); -// if (cfg.codePreview && !ujs.code_data) { -// await reqCode(ujs); -// } -// records.push(ujs); -// } -// this.data.push(...records); -// } catch (ex) { -// err(ex); -// } -// return records; -// }; -// if (engine.name.includes('fork')) { -// await Network.req(`${engine.url}/scripts/by-site/${this.host}.json?language=all`) -// .then(forkFN) -// .catch(err); -// } else if (/github/gi.test(engine.name)) { -// if (isEmpty(engine.token)) { -// err(`"${engine.name}" requires a token to use`); -// return; -// } -// await Network.req( -// `${engine.url}"// ==UserScript=="+${this.host}+ "// ==/UserScript=="+in:file+language:js&per_page=30`, -// 'GET', -// 'json', -// { -// headers: { -// Accept: 'application/vnd.github+json', -// Authorization: `Bearer ${engine.token}`, -// 'X-GitHub-Api-Version': '2022-11-28' -// } -// } -// ) -// .then(gitFN) -// .catch(err); -// } -// return this.data; -// } -// } -// const eng = new Engine(); - -// const cac = new Map(); - -const webFetcher = async (loc, tabId = -2, link) => { - if (isBlank(loc)) { - return []; +const setCount = (tab, tabId) => { + let url; + try { + url = new URL(tab.url); + } catch (ex) { + err(ex); } - const host = formatURL(loc); - - let isBlacklisted = false; - for (const b of cfg.blacklist.filter((b) => b.enabled)) { - if (b.regex === true) { - const reg = new RegExp(b.url, b.flags); - if (!reg.test(host)) continue; - isBlacklisted = true; - } - if (Array.isArray(b.url)) { - for (const c of b.url) { - if (!host.includes(c)) continue; - isBlacklisted = true; - } - } - if (!host.includes(b.url)) continue; - isBlacklisted = true; - } - - // log('Blacklisted:', isBlacklisted, host); - if (isBlacklisted) { - return []; - } - - if (!MUJS.cache.has(host)) { - const engineTemplate = {}; - for (const engine of cfg.engines) { - engineTemplate[engine.name] = []; - } - MUJS.cache.set(host, engineTemplate); - } - - const isSupported = (name) => { - for (const [k, v] of Object.entries(unsupported)) { - if (k !== name) { - continue; - } - if (v.includes(host)) { - return false; - } - } - return true; - }; - const engines = cfg.engines.filter((e) => e.enabled && isSupported(e.name)); - if (isEmpty(engines)) { - return []; - } - const cache = MUJS.cache.get(host); - const sites = []; - - info('Building list', { cfg, cache, engines, allCache: MUJS.cache, sites }); - - - // for (const engine of engines) { - // if (!isEmpty(cache[`${engine.name}`])) { - // sites.push({ - // engine, - // data: normalizeTarget(cache[`${engine.name}`]), - // host, - // link - // // tab - // }); - // continue; - // } - // eng.setHost(host).setEngine(engine); - // await eng.getData(); - // } - // log(eng.data); - - for (const engine of engines) { - if (!isEmpty(cache[`${engine.name}`])) { - sites.push({ - engine, - data: normalizeTarget(cache[`${engine.name}`]), - host, - link - // tab - }); - continue; - } - const engineArr = cache[engine.name]; - /** - * @param { import("../typings/types").GSFork } dataQ - */ - const forkFN = async (dataQ) => { - if (!dataQ) { - err('Invalid data received from the server, check internet connection'); - return []; - } - /** - * @type { import("../typings/types").GSForkQuery[] } - */ - const dq = Array.isArray(dataQ) ? dataQ : Array.isArray(dataQ.query) ? dataQ.query : []; - const data = dq.filter((d) => !d.deleted); - if (isBlank(data)) { - return []; - } - const hideData = []; - const inUserLanguage = (d) => { - const dlocal = d.locale.split('-')[0] ?? d.locale; - if (language.cache.includes(dlocal)) { - return true; - } - hideData.push(d); - return false; - }; - const filterLang = data.filter((d) => { - if (cfg.filterlang && !inUserLanguage(d)) { - return false; - } - return true; - }); - - let finalList = filterLang; - const hds = []; - for (const ujs of hideData) { - await reqCode(ujs, true); - if (ujs.translated) { - hds.push(ujs); - } - } - finalList = [...new Set([...hds, ...filterLang])]; - - // for (const ujs of finalList) { - // if (!cac.has(ujs.id)) { - // cac.set(ujs.id, { - // ...ujs, - // mujs: { - // engine, - // host, - // timestamp: Date.now(), - // } - // }) - // } - // } - - engineArr.push(...finalList); - return finalList; - }; - const gitFN = async (data) => { - const records = []; - try { - if (isBlank(data.items)) { - err('Invalid data received from the server, TODO fix this'); - return; - } - for (const r of data.items) { - const ujs = template.merge({ - name: r.name, - description: isEmpty(r.repository.description) - ? i18n$('no_license') - : r.repository.description, - url: r.html_url, - code_url: r.html_url.replace(/\/blob\//g, '/raw/'), - code_updated_at: r.commit || Date.now(), - total_installs: r.score, - users: [ - { - name: r.repository.owner.login, - url: r.repository.owner.html_url - } - ] - }); - if (cfg.codePreview && !ujs.code_data) { - await reqCode(ujs); - } - // createjs(ujs, engine.name); - records.push(ujs); - } - engineArr.push(...records); - } catch (ex) { - err(ex); - } - return records; - }; - if (engine.name.includes('fork')) { - const data = await Network.req(`${engine.url}/scripts/by-site/${host}.json?language=all`) - .then(forkFN) - .catch(err); - sites.push({ - engine, - data, - host, - link - // tab - }); - } else if (/github/gi.test(engine.name)) { - if (isEmpty(engine.token)) { - err(`"${engine.name}" requires a token to use`); - continue; - } - const data = await Network.req( - `${engine.url}"// ==UserScript=="+${host}+ "// ==/UserScript=="+in:file+language:js&per_page=30`, - 'GET', - 'json', - { - headers: { - Accept: 'application/vnd.github+json', - Authorization: `Bearer ${engine.token}`, - 'X-GitHub-Api-Version': '2022-11-28' - } - } - ) - .then(gitFN) - .catch(err); - sites.push({ - engine, - data, - host, - link - // tab + if (url !== undefined) { + if (!Object.is(url.origin, 'null')) { + MUList.host = formatURL(url.host); + MUList.tabId = tabId ?? tab.id ?? -2; + webext.action.setBadgeText({ + text: `${Array.from(MUList).length ?? 0}` }); + return; } } - if (tabId > -1) { - webext.tabs.get(tabId, updateCount); - } - // log(cac); - return sites; + webext.action.setBadgeText({ + text: '0' + }); }; let requestId = -2; -// let isRedirect = false; webext.webRequest.onHeadersReceived.addListener( (e) => { if (Object.is(e.type, 'main_frame')) { - // log(e, isRedirect); - if (requestId !== e.requestId) { + if (cfg.autofetch && requestId !== e.requestId) { requestId = e.requestId; const loc = new URL(e.url); - webFetcher(loc.host, e.tabId, e.url); + MUList.host = formatURL(loc.host); + MUList.tabId = e.tabId ?? -2; + MUList.build().then(() => { + setCount(e, e.tabId) + }); } } }, { - urls: [ - // 'http://*/*', - 'https://*/*' - ] + urls: ['https://*/*'] } ); -// webext.webRequest.onBeforeRedirect.addListener( -// (e) => { -// if (Object.is(e.type, 'main_frame')) { -// log(e); -// if (requestId === e.requestId) { -// isRedirect = true; -// requestId = -2; -// } -// // if (requestId !== e.requestId) { -// // log(e); -// // requestId = e.requestId; -// // const loc = new URL(e.url); -// // webFetcher(loc.host, e.tabId); -// // } -// } -// }, -// { -// urls: [ -// // 'http://*/*', -// 'https://*/*' -// ] -// } -// ); /** * [onMessage description] - * @param {*} message - The message itself. This is a JSON-ifiable object. + * @param {object} message - The message itself. This is a JSON-ifiable object. * @param {chrome.runtime.MessageSender} sender * @param {(response: any) => void} sendResponse - A function to call, at most once, to send a response to the message. The function takes a single argument, which may be any JSON-ifiable object. This argument is passed back to the message sender. */ function onMessage(message, sender, sendResponse) { if (sender.url.includes('popup.html')) { - if (message.location) { - webFetcher(message.location).then((data) => sendResponse(data)); - } else { - webext.tabs.query(queryOptions, (tabs) => { - const tab = tabs[0]; - const loc = new URL(getTabUrl(tab)); - webFetcher(loc.host, tab.id, getTabUrl(tab)).then((data) => sendResponse(data)); - }); - } - } - - if (message.name) { - if (sender.url.includes('settings.html')) { - storage.config.setOne(message.name, message.value); - sendResponse({ - name: message.name, - value: message.value + if (message.type === 'getData') { + if (MUList.host !== message.hostname) { + MUList.host = message.hostname ?? BLANK_PAGE; + MUList.tabId = message.currentTab?.id ?? -2; + }; + MUList.build().then((data) => { + if (message.init) { + sendResponse({ cfg, data }) + } else { + sendResponse({ data }) + } }); + } else if (message.type === 'save') { + if (message.cfg) { + storage.config.set(message.cfg).then(initCfg); + } else { + const v = isNull(message.value) ? cfg[message.prop] : message.value; + storage.config.setOne(message.prop, v).then(initCfg); + } + } else if (message.type === 'reset') { + storage.config.set(DEFAULT_CONFIG); + } else if (message.type === 'clear') { + const cache = Array.from(container).filter(({ _mujs }) => _mujs.info.host === message.host); + for (const ujs of cache) container.userjsCache.delete(ujs.id); + } else if (message.type === 'engine') { + const engine = cfg.engines.find((engine) => engine.name === message.engine.name); + for (const [k, v] of Object.entries(message.engine)) { + engine[k] = v; + } + storage.config.set(cfg).then(initCfg); + } else if (message.location) { + MUList.host = formatURL(message.location); + MUList.build().then(sendResponse); } else { - sendResponse({ value: cfg[message.name] }); + sendResponse({ cfg }); } } return true; } -webext.runtime.onMessage.addListener(onMessage); +function start() { + runtime.onMessage.addListener(onMessage); -const tc = (tab) => { - const loc = new URL(tab.url); - const host = formatURL(loc.host); - return { - loc, - host, - cache: MUJS.cache.get(host) - }; -}; -const updateCount = (tab) => { - const { cache } = tc(tab); - let cnt = 0; - if (cache) { - for (const v of Object.values(cache)) { - cnt += v.length; - } - } - webext.browserAction.setBadgeText({ - text: `${cnt}` + webext.tabs.onRemoved.addListener((tabId) => { + const cache = Array.from(container.userjsCache.values()).filter(({ _mujs }) => { + return !isEmpty(_mujs) && _mujs.info.tabId === tabId; + }); + for (const ujs of cache) container.userjsCache.delete(ujs.id); }); -}; -// webext.tabs.onCreated.addListener((tab) => { -// updateCount(tab); -// }); + webext.tabs.onCreated.addListener(setCount); -webext.tabs.onActivated.addListener((activeInfo) => { - const { tabId } = activeInfo; - webext.tabs.get(tabId, updateCount); - // if (currentTab.tabId !== tabId) { - // currentTab.tabId = tabId; - // } - // log('onActivated', currentTab); -}); + webext.tabs.onActivated.addListener((activeInfo) => { + const { tabId } = activeInfo; + webext.tabs.get(tabId, setCount); + }); -webext.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { - updateCount(tab); - // if (changeInfo.status === 'complete') { - // if (currentTab.tabId !== tabId) { - // currentTab.tabId = tabId; - // currentTab.url = getTabUrl(tab); - // } - // } -}); + webext.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (tab.status === 'complete') { + setCount(tab, tabId); + } + }); + + webext.action.setBadgeText({ + text: '0' + }); +} + +start(); diff --git a/src/js/config.js b/src/js/config.js deleted file mode 100644 index 65599d1..0000000 --- a/src/js/config.js +++ /dev/null @@ -1,210 +0,0 @@ -'use strict'; - -const storage = webext.storage; -const Config = { - configLocalListeners: [], - configSyncListeners: [], - syncDefaults: { - // cache: true, - codePreview: false, - // autoexpand: false, - filterlang: false, - sleazyredirect: false, - // time: 10000, - blacklist: [ - { - enabled: true, - regex: true, - flags: '', - name: 'Blacklist 1', - url: '(gov|cart|checkout|login|join|signin|signup|sign-up|password|reset|password_reset)' - }, - { - enabled: true, - regex: true, - flags: '', - name: 'Blacklist 2', - url: '(pay|bank|money|localhost|authorize|checkout|bill|wallet|router)' - }, - { - enabled: true, - regex: false, - flags: '', - name: 'Blacklist 3', - url: 'https://home.bluesnap.com' - }, - { - enabled: true, - regex: false, - flags: '', - name: 'Blacklist 4', - url: ['zalo.me', 'skrill.com'] - } - ], - engines: [ - { - enabled: true, - name: 'greasyfork', - url: 'https://greasyfork.org' - }, - { - enabled: false, - name: 'sleazyfork', - url: 'https://sleazyfork.org' - }, - { - enabled: false, - name: 'openuserjs', - url: 'https://openuserjs.org/?q=' - }, - { - enabled: false, - name: 'github', - url: 'https://api.github.com/search/code?q=', - token: '' - } - ], - theme: { - 'even-row': '', - 'odd-row': '', - 'even-err': '', - 'odd-err': '', - 'background-color': '', - 'gf-color': '', - 'sf-color': '', - 'border-b-color': '', - 'gf-btn-color': '', - 'sf-btn-color': '', - 'sf-txt-color': '', - 'txt-color': '', - 'chck-color': '', - 'chck-gf': '', - 'chck-git': '', - 'chck-open': '', - placeholder: '', - 'position-top': '', - 'position-bottom': '', - 'position-left': '', - 'position-right': '', - 'font-family': '' - }, - recommend: { - author: true, - others: true - } - }, - cachedSyncConfig: {}, - /** - * @type { import("../typings/types").config } - */ - cachedLocalStorage: {}, - resetToDefault -}; - -function configProxy() { - storage.onChanged.addListener((changes = storage.StorageChange, areaName) => { - if (areaName === 'sync') { - for (const key in changes) { - Config.cachedSyncConfig[key] = changes[key].newValue; - } - for (const callback of Config.configSyncListeners) { - callback(changes); - } - } else if (areaName === 'local') { - for (const key in changes) { - Config.cachedLocalStorage[key] = changes[key].newValue; - } - for (const callback of Config.configLocalListeners) { - callback(changes); - } - } - }); - - const syncHandler = { - set(prop, value) { - Config.cachedSyncConfig[prop] = value; - storage.sync.set({ - [prop]: value - }); - return true; - }, - get(obj, prop) { - const data = Config.cachedSyncConfig[prop]; - return obj[prop] || data; - }, - deleteProperty(prop) { - storage.sync.remove(prop); - return true; - } - }; - - const localHandler = { - set(prop, value) { - Config.cachedLocalStorage[prop] = value; - storage.local.set({ - [prop]: value - }); - return true; - }, - get(obj, prop) { - const data = Config.cachedLocalStorage[prop]; - return obj[prop] || data; - }, - deleteProperty(prop) { - storage.local.remove(prop); - return true; - } - }; - return { - sync: new Proxy({ handler: syncHandler }, syncHandler), - local: new Proxy({ handler: localHandler }, localHandler) - }; -} - -async function fetchConfig() { - await Promise.all([ - new Promise((resolve) => { - storage.sync.get(null, function (items) { - Config.cachedSyncConfig = items; - resolve(); - }); - }), - new Promise((resolve) => { - storage.local.get(null, function (items) { - Config.cachedLocalStorage = items; - resolve(); - }); - }) - ]); -} - -async function setupConfig() { - await fetchConfig(); - for (const key in Config.syncDefaults) { - if (!Object.hasOwn(Config.cachedSyncConfig, key)) { - Config.cachedSyncConfig[key] = Config.syncDefaults[key]; - } - if (!Object.hasOwn(Config.cachedLocalStorage, key)) { - Config.cachedLocalStorage[key] = Config.syncDefaults[key]; - } - } - const config = configProxy(); - Config.config = config.sync; - Config.local = config.local; -} - -function resetToDefault() { - Config.cachedLocalStorage = Config.syncDefaults; - Config.cachedSyncConfig = Config.syncDefaults; - storage.local.set({ - ...Config.syncDefaults - }); - storage.sync.set({ - ...Config.syncDefaults - }); - return Config; -} - -setupConfig(); - -export default Config; diff --git a/src/js/constants.js b/src/js/constants.js new file mode 100644 index 0000000..a479978 --- /dev/null +++ b/src/js/constants.js @@ -0,0 +1,88 @@ +'use strict'; + +const template = { + id: 0, + bad_ratings: 0, + good_ratings: 0, + ok_ratings: 0, + daily_installs: 0, + total_installs: 0, + name: 'NOT FOUND', + description: 'NOT FOUND', + version: '0.0.0', + url: 'about:blank', + code_url: 'about:blank', + created_at: Date.now(), + code_updated_at: Date.now(), + locale: 'NOT FOUND', + deleted: false, + users: [] +}; +/** Unsupport host for search engines */ +const engineUnsupported = { + greasyfork: ['pornhub.com'], + sleazyfork: ['pornhub.com'], + openuserjs: [], + github: [] +}; +const builtinList = { + local: /localhost|router|gov|(\d+\.){3}\d+/, + finance: + /school|pay|bank|money|cart|checkout|authorize|bill|wallet|venmo|zalo|skrill|bluesnap|coin|crypto|currancy|insurance|finance/, + social: /login|join|signin|signup|sign-up|password|reset|password_reset/, + unsupported: { + host: 'fakku.net', + pathname: '/hentai/.+/read/page/.+' + } +}; +const BLANK_PAGE = 'about:blank'; +/** Lets highlight me :) */ +const authorID = 166061; +/** + * Some UserJS I personally enjoy - `https://greasyfork.org/scripts/{id}` + */ +const goodUserJS = [ + 33005, + 394820, + 438684, + 4870, + 394420, + 25068, + 483444, + 1682, + 22587, + 789, + 28497, + 386908, + 24204, + 404443, + 4336, + 368183, + 393396, + 473830, + 12179, + 423001, + 376510, + 23840, + 40525, + 6456, + 'https://openuserjs.org/install/Patabugen/Always_Remember_Me.user.js', + 'https://openuserjs.org/install/nokeya/Direct_links_out.user.js', + 'https://github.com/jijirae/y2monkey/raw/main/y2monkey.user.js', + 'https://github.com/jijirae/r2monkey/raw/main/r2monkey.user.js', + 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/Manga_OnlineViewer.user.js', + 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', + 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' +]; +/** Remove UserJS from banned accounts */ +const badUserJS = [478597]; + +export { + authorID, + template, + engineUnsupported, + builtinList, + BLANK_PAGE, + goodUserJS, + badUserJS +} diff --git a/src/js/container.js b/src/js/container.js new file mode 100644 index 0000000..5f89410 --- /dev/null +++ b/src/js/container.js @@ -0,0 +1,119 @@ +'use strict'; + +import { isEmpty, isFN } from './util.js'; +import { BLANK_PAGE, engineUnsupported } from './constants.js'; +import { webext } from './ext.js'; + +const MUJS_ORIGIN = webext.runtime.getURL('').replace(/\/$/, ''); + +export class BaseContainer { + constructor() { + this.toElem = this.toElem.bind(this); + this.cache = new Map(); + /** + * @type { Map } + */ + this.userjsCache = new Map(); + } + + checkBlacklist() { + return true; + } + + toElem() { + return Array.from(this).map(({ _mujs }) => { + return _mujs.root; + }); + } + + *[Symbol.iterator]() { + const arr = Array.from(this.userjsCache.values()).filter(({ _mujs }) => { + return !isEmpty(_mujs) && _mujs.info.engine.enabled; + }); + for (const userjs of arr) { + yield userjs; + } + } +} + +export class BaseList { + intEngines; + intHost; + constructor(hostname = undefined, container = new BaseContainer(), cfg = {}) { + this.groupBy = this.groupBy.bind(this); + this.container = container; + this.intEngines = cfg.engines ?? []; + this.host = hostname; + } + + setEngines(engines = []) { + const { host } = this; + return engines.filter((e) => { + if (!e.enabled) { + return false; + } + const v = engineUnsupported[e.name] ?? []; + if (v.includes(host)) { + return false; + } + return true; + }); + } + + set engines(engines) { + this.intEngines = this.setEngines(engines); + } + + get engines() { + return this.intEngines; + } + + set host(hostname) { + if (!MUJS_ORIGIN.includes(hostname)) { + this.intHost = hostname ?? BLANK_PAGE; + } else if (isEmpty(this.intHost)) { + this.intHost = BLANK_PAGE + } + + if (!this.container.cache.has(hostname)) { + const engineTemplate = {}; + for (const engine of this.engines) { + engineTemplate[engine.name] = []; + } + this.container.cache.set(hostname, engineTemplate); + } + this.blacklisted = this.container.checkBlacklist(hostname); + this.intEngines = this.setEngines(this.engines); + } + + get host() { + return this.intHost; + } + + groupBy() { + const arr = Array.from(this); + const callback = ({ _mujs }) => _mujs.info.engine.name; + if (isFN(Object.groupBy)) { + return Object.groupBy(arr, callback); + } + /** [Object.groupBy polyfill](https://gist.github.com/gtrabanco/7c97bd41aa74af974fa935bfb5044b6e) */ + return arr.reduce((acc = {}, ...args) => { + const key = callback(...args); + acc[key] ??= []; + acc[key].push(args[0]); + return acc; + }, {}); + } + + *[Symbol.iterator]() { + const { intHost, engines } = this; + const arr = Array.from(this.container).filter( + ({ _mujs }) => + _mujs.info.host === intHost && + engines.find((engine) => engine.enabled && engine.name === _mujs.info.engine.name) + ); + for (const userjs of arr) { + yield userjs; + } + } +} diff --git a/src/js/ext.js b/src/js/ext.js new file mode 100644 index 0000000..ebd6ec7 --- /dev/null +++ b/src/js/ext.js @@ -0,0 +1,34 @@ +export const webext = + self.browser instanceof Object && self.browser instanceof Element === false + ? self.browser + : self.chrome; +export const runtime = webext.runtime; + +/******************************************************************************/ + +// The extension's service worker can be evicted at any time, so when we +// send a message, we try a few more times when the message fails to be sent. + +export function sendMessage(msg) { + return new Promise((resolve, reject) => { + let i = 5; + const send = () => { + runtime + .sendMessage(msg) + .then((response) => { + resolve(response); + }) + .catch((reason) => { + i -= 1; + if (i <= 0) { + reject(reason); + } else { + setTimeout(send, 200); + } + }); + }; + send(); + }); +} + +/******************************************************************************/ diff --git a/src/js/i18n.js b/src/js/i18n.js index 959a1f3..b929550 100644 --- a/src/js/i18n.js +++ b/src/js/i18n.js @@ -1,17 +1,31 @@ 'use strict'; -/******************************************************************************/ - +// #region i18n const i18n = self.browser instanceof Object && self.browser instanceof Element === false ? self.browser.i18n : self.chrome.i18n; -const i18n$ = (...args) => i18n.getMessage(...args); - -/******************************************************************************/ +const i18n$ = (...args) => { + return i18n.getMessage(...args); +}; +/** + * @param {string | Date | number} str + */ +const toDate = (str = '') => { + return new Intl.DateTimeFormat(navigator.language).format( + typeof str === 'string' ? new Date(str) : str + ); +}; +/** + * @param {number | bigint} number + */ +const toNumber = (number) => { + return new Intl.NumberFormat(navigator.language).format(number); +}; +// #endregion -const isBackgroundProcess = document.title === 'Magic UserJS+ Background Page'; +const isBackgroundProcess = document && document.title === 'Magic UserJS+ Background Page'; if (isBackgroundProcess !== true) { // Helper to deal with the i18n'ing of HTML files. @@ -35,5 +49,6 @@ if (isBackgroundProcess !== true) { }; i18n.render(); } +const language = { i18n$, toDate, toNumber }; -export { i18n, i18n$ }; +export { i18n, i18n$, toDate, toNumber, language }; diff --git a/src/js/language.js b/src/js/language.js deleted file mode 100644 index f1f817e..0000000 --- a/src/js/language.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -class LanguageHandler { - constructor() { - this.current = (navigator.language ?? 'en').split('-')[0] ?? 'en'; - this.cache = []; - - const languages = navigator.languages ?? []; - for (const nlang of languages) { - const lg = nlang.split('-')[0]; - if (this.cache.indexOf(lg) === -1) { - this.cache.push(lg); - } - } - - if (!this.cache.includes(this.current)) { - this.cache.push(this.current); - } - } -} - -const language = new LanguageHandler(); - -export { - language -}; \ No newline at end of file diff --git a/src/js/logger.js b/src/js/logger.js index 40c1863..cbf0e2f 100644 --- a/src/js/logger.js +++ b/src/js/logger.js @@ -20,11 +20,6 @@ const err = (...msg) => { 'color: rgb(249, 24, 128);', ...msg ); - for (const ex of msg) { - if (typeof ex === 'object' && 'cause' in ex && typeof alert !== 'undefined') { - alert(`[Magic Userscript+] (${ex.cause}) ${ex.message}`); - } - } }; const info = (...msg) => { console.info( diff --git a/src/js/messager.js b/src/js/messager.js new file mode 100644 index 0000000..934ab67 --- /dev/null +++ b/src/js/messager.js @@ -0,0 +1,124 @@ +'use strict'; + +import { webext } from './ext.js'; + +export const hermes = { + port: null, + portTimer: null, + portTimerDelay: 10000, + msgIdGenerator: 1, + pending: new Map(), + waitStartTime: 0, + shuttingDown: false, + shutdown: function () { + this.shuttingDown = true; + this.destroyPort(); + }, + disconnectListener: function () { + void webext.runtime.lastError; + this.port = null; + this.destroyPort(); + }, + disconnectListenerBound: null, + messageListener: function (details) { + if (typeof details !== 'object' || details === null) { + return; + } + // Response to specific message previously sent + if (details.msgId !== undefined) { + const resolver = this.pending.get(details.msgId); + if (resolver !== undefined) { + this.pending.delete(details.msgId); + resolver(details.msg); + return; + } + } + }, + messageListenerBound: null, + canDestroyPort: function () { + return this.pending.size === 0; + }, + portPoller: function () { + this.portTimer = null; + if (this.port !== null && this.canDestroyPort()) { + return this.destroyPort(); + } + this.portTimer = setTimeout(this.portPollerBound, this.portTimerDelay); + this.portTimerDelay = Math.min(this.portTimerDelay * 2, 60 * 60 * 1000); + }, + portPollerBound: null, + destroyPort: function () { + if (this.portTimer !== null) { + clearTimeout(this.portTimer); + this.portTimer = null; + } + const port = this.port; + if (port !== null) { + port.disconnect(); + port.onMessage.removeListener(this.messageListenerBound); + port.onDisconnect.removeListener(this.disconnectListenerBound); + this.port = null; + } + // service pending callbacks + if (this.pending.size !== 0) { + const pending = this.pending; + this.pending = new Map(); + for (const resolver of pending.values()) { + resolver(); + } + } + }, + createPort: function () { + if (this.shuttingDown) { + return null; + } + if (this.messageListenerBound === null) { + this.messageListenerBound = this.messageListener.bind(this); + this.disconnectListenerBound = this.disconnectListener.bind(this); + this.portPollerBound = this.portPoller.bind(this); + } + try { + this.port = webext.runtime.connect({ name: 'hermes' }) || null; + // eslint-disable-next-line no-unused-vars + } catch (ex) { + this.port = null; + } + if (this.port === null) { + return null; + } + this.port.onMessage.addListener(this.messageListenerBound); + this.port.onDisconnect.addListener(this.disconnectListenerBound); + this.portTimerDelay = 10000; + if (this.portTimer === null) { + this.portTimer = setTimeout(this.portPollerBound, this.portTimerDelay); + } + return this.port; + }, + getPort: function () { + return this.port ?? this.createPort(); + }, + send: function (channel, msg) { + // Too large a gap between the last request and the last response means + // the main process is no longer reachable: memory leaks and bad + // performance become a risk -- especially for long-lived, dynamic + // pages. Guard against this. + if (this.pending.size > 64) { + if (Date.now() - this.waitStartTime > 60000) { + this.shutdown(); + } + } + const port = this.getPort(); + if (port === null) { + return Promise.resolve(); + } + if (this.pending.size === 0) { + this.waitStartTime = Date.now(); + } + const msgId = this.msgIdGenerator++; + const promise = new Promise((resolve) => { + this.pending.set(msgId, resolve); + }); + port.postMessage({ channel, msgId, msg }); + return promise; + } +}; diff --git a/src/js/mu-common.js b/src/js/mu-common.js deleted file mode 100644 index a7d6863..0000000 --- a/src/js/mu-common.js +++ /dev/null @@ -1,385 +0,0 @@ -'use strict'; - -/** - * @typedef { object } userjs - */ - -// if (typeof userjs === 'undefined') { -// let userjs = (self.userjs = {}); -// } - -if (typeof userjs === 'object' && userjs.isNull instanceof Function === false) { - const win = self ?? window; - const doc = win.document; - const isMobile = /Mobile|Tablet/.test(navigator.userAgent); - /** - * Object is typeof `Element` - * @template O - * @param { O } obj - * @returns { boolean } - */ - const isElem = (obj) => { - /** @type { string } */ - const s = Object.prototype.toString.call(obj); - return s.includes('Element'); - }; - /** - * Object is typeof `Function` - * @template O - * @param { O } obj - * @returns { boolean } - */ - const isFN = (obj) => { - /** @type { string } */ - const s = Object.prototype.toString.call(obj); - return s.includes('Function'); - }; - /** - * Object is typeof `object` / JSON Object - * @template O - * @param { O } obj - * @returns { boolean } - */ - const isObj = (obj) => { - /** @type { string } */ - const s = Object.prototype.toString.call(obj); - return s.includes('Object'); - }; - /** - * Object is `null` or `undefined` - * @template O - * @param { O } obj - * @returns { boolean } - */ - const isNull = (obj) => { - return Object.is(obj, null) || Object.is(obj, undefined); - }; - /** - * Object is Blank - * @template O - * @param { O } obj - * @returns { boolean } - */ - const isBlank = (obj) => { - return ( - (typeof obj === 'string' && Object.is(obj.trim(), '')) || - ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) || - (Array.isArray(obj) && Object.is(obj.length, 0)) || - (isObj(obj) && Object.is(Object.keys(obj).length, 0)) - ); - }; - /** - * Object is Empty - * @template O - * @param { O } obj - * @returns { boolean } - */ - const isEmpty = (obj) => { - return isNull(obj) || isBlank(obj); - }; - /** - * @template T - * @param { T } target - * @param { boolean } toQuery - * @param { Element | Document | undefined } root - * @returns { T[] } - */ - const normalizeTarget = (target, toQuery = true, root) => { - if (Object.is(target, null) || Object.is(target, undefined)) { - return []; - } - if (Array.isArray(target)) { - return target; - } - if (typeof target === 'string') { - return toQuery ? Array.from((root || document).querySelectorAll(target)) : [target]; - } - if (isElem(target)) { - return [target]; - } - return Array.from(target); - }; - /** - * Add Event Listener - * @template { HTMLElement } E - * @template { keyof HTMLElementEventMap } K - * @param { E } el - * @param { K } event - * @param { (this: E, ev: HTMLElementEventMap[K]) => any } callback - * @param { boolean | AddEventListenerOptions } options - */ - const ael = (el, event, callback, options = {}) => { - try { - for (const elem of normalizeTarget(el)) { - if (!elem) { - continue; - } - if (isMobile && event === 'click') { - elem.addEventListener('touchstart', callback); - return; - } - if (event === 'fclick') { - event = 'click'; - } - elem.addEventListener(event, callback, options); - } - } catch (ex) { - console.error(ex); - } - }; - /** - * Form Attributes of Element - * @template { keyof HTMLElementTagNameMap } K - * @param { K } elem - * @param { keyof HTMLElement } attr - */ - const formAttrs = (elem, attr = {}) => { - for (const key in attr) { - if (typeof attr[key] === 'object') { - formAttrs(elem[key], attr[key]); - } else if (isFN(attr[key])) { - if (key === 'container') { - key(); - continue; - } - if (/^on/.test(key)) { - elem[key] = attr[key]; - continue; - } - ael(elem, key, attr[key]); - } else if (key === 'class') { - elem.className = attr[key]; - } else { - elem[key] = attr[key]; - } - } - }; - /** - * Make Element - * @template { keyof HTMLElementTagNameMap } K - * @param { K } tagName - * @param { string } cname - * @param { keyof HTMLElement } attrs - * @returns { HTMLElementTagNameMap[K] } - */ - const make = (tagName, cname, attrs = {}) => { - let el = null; - try { - el = document.createElement(tagName); - if (typeof cname === 'string' && !isEmpty(cname)) { - el.className = cname; - } - if (!isEmpty(attrs)) { - formAttrs(el, attrs); - } - } catch (ex) { - console.error(ex); - } - return el; - }; - /** - * setTimeout w/ Promise - * @param { number } timeout - Timeout in milliseconds (ms) - * @returns { Promise } Promise object - */ - const delay = (timeout = 5000) => new Promise((resolve) => setTimeout(resolve, timeout)); - const Network = { - /** - * Fetch a URL with fetch API as fallback - * - * When GM is supported, makes a request like XMLHttpRequest, with some special capabilities, not restricted by same-origin policy - * @link https://violentmonkey.github.io/api/gm/#gm_xmlhttprequest - * @link https://developer.mozilla.org/docs/Web/API/Fetch_API - * @param { RequestInfo | URL } url - The URL to fetch - * @param { Request['method'] } method - Fetch method - * @param { 'buffer' | 'json' | 'text' | 'blob' | 'document' } responseType - Response type - * @param { RequestInit } data - Fetch parameters - * @returns { Promise } Fetch results - */ - async req(url, method = 'GET', responseType = 'json', data = {}) { - if (isEmpty(url)) { - throw new Error('"url" parameter is empty'); - } - method = Network.bscStr(method, false); - responseType = Network.bscStr(responseType); - const params = { - method, - ...data - }; - return await new Promise((resolve, reject) => { - /** - * @param { Response } response - * @returns { Response | Document } - */ - const fetchResp = (response_1) => { - if (!response_1.ok) reject(response_1); - const check = (str_2 = 'text') => { - return isFN(response_1[str_2]) ? response_1[str_2]() : response_1; - }; - if (responseType.match(/buffer/i)) { - resolve(check('arrayBuffer')); - } else if (responseType.match(/json/i)) { - resolve(check('json')); - } else if (responseType.match(/text/i)) { - resolve(check('text')); - } else if (responseType.match(/blob/i)) { - resolve(check('blob')); - } else if (responseType.match(/formdata/i)) { - resolve(check('formData')); - } else if (responseType.match(/clone/i)) { - resolve(check('clone')); - } else if (responseType.match(/document/i) && isFN(response_1.text)) { - const domParser = new DOMParser(); - const respTxt = response_1.text(); - if (respTxt instanceof Promise) { - respTxt.then((txt) => { - const doc = domParser.parseFromString(txt, 'text/html'); - resolve(doc); - }); - } else { - const doc = domParser.parseFromString(respTxt, 'text/html'); - resolve(doc); - } - } else { - resolve(response_1); - } - }; - fetch(url, params).then(fetchResp).catch(reject); - }); - }, - format(bytes, decimals = 2) { - if (Number.isNaN(bytes)) return '0 Bytes'; - const k = 1024; - const dm = decimals < 0 ? 0 : decimals; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${Network.sizes[i]}`; - }, - sizes: ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - /** - * @template { string } S - * @param { S } str - * @param { boolean } lowerCase - * @returns { S } - */ - bscStr(str = '', lowerCase = true) { - const txt = str[lowerCase ? 'toLowerCase' : 'toUpperCase'](); - return txt.replaceAll(/\W/g, ''); - } - }; - // const i18n$ = (...args) => { - // const arr = []; - // for (const arg of args) { - // arr.push(webext.i18n.getMessage(arg)); - // } - // return arr.length !== 1 ? arr : arr[0]; - // }; - - class Timeout { - constructor() { - this.ids = []; - } - - set(delay, reason) { - return new Promise((resolve, reject) => { - const id = setTimeout(() => { - isNull(reason) ? resolve() : reject(reason); - this.clear(id); - }, delay); - this.ids.push(id); - }); - } - - clear(...ids) { - this.ids = this.ids.filter((id) => { - if (ids.includes(id)) { - clearTimeout(id); - return false; - } - return true; - }); - } - } - class MUError extends Error { - /** - * @param {string} fnName - (Optional) Function name - * @param {...string} params - Extra error parameters - */ - constructor(fnName = 'muError', ...params) { - super(...params); - if (Error.captureStackTrace) { - Error.captureStackTrace(this, MUError); - } else { - this.stack = new Error().stack; - } - this.fn = `[${fnName}]`; - this.name = this.constructor.name; - } - } - - userjs.error = MUError; - userjs.isMobile = isMobile; - userjs.Timeout = Timeout; - userjs.isElem = isElem; - userjs.isFN = isFN; - userjs.isObj = isObj; - userjs.isNull = isNull; - userjs.isBlank = isBlank; - userjs.isEmpty = isEmpty; - userjs.ael = ael; - userjs.formAttrs = formAttrs; - userjs.make = make; - userjs.delay = delay; - userjs.normalizeTarget = normalizeTarget; - - Object.assign(userjs, { - makeImage(imgSrc = '', attrs = {}, cname) { - const img = new Image(); - img.alt = ''; - img.referrerPolicy = 'no-referrer'; - img.src = imgSrc; - if (!isEmpty(cname)) { - img.className = cname; - } - if (!isEmpty(attrs)) { - for (const key in attrs) { - img[key] = attrs[key]; - } - } - return img; - }, - halt(e) { - e.preventDefault(); - e.stopPropagation(); - }, - injScript(text, remove = true) { - const inj = make('script', 'mu-injected', { - type: 'text/javascript', - innerHTML: text - }); - (doc.head || doc.documentElement || doc).appendChild(inj); - if (!remove) { - return inj; - } - delay(1000).then(() => inj.remove()); - }, - /** - * @param {Node} element - * @param {MutationCallback} callback - * @param {MutationObserverInit} options - */ - observe(element, callback, options = { subtree: true, childList: true }) { - const observer = new MutationObserver(callback); - callback([], observer); - observer.observe(element, options); - return observer; - }, - /** - * @param {string} url - URL of webpage to open - * @param {object} params - GM parameters - */ - openInTab(url, params = {}) { - params = Object.is(params, {}) ? '_blank' : params; - return win.open(url, params); - } - }); -} diff --git a/src/js/mu-hermes.js b/src/js/mu-hermes.js deleted file mode 100644 index 9772b05..0000000 --- a/src/js/mu-hermes.js +++ /dev/null @@ -1,126 +0,0 @@ -'use strict'; - -if (typeof userjs === 'object') { - userjs.hermes = { - port: null, - portTimer: null, - portTimerDelay: 10000, - msgIdGenerator: 1, - pending: new Map(), - waitStartTime: 0, - shuttingDown: false, - shutdown: function () { - this.shuttingDown = true; - this.destroyPort(); - }, - disconnectListener: function () { - void webext.runtime.lastError; - this.port = null; - this.destroyPort(); - }, - disconnectListenerBound: null, - messageListener: function (details) { - if (typeof details !== 'object' || details === null) { - return; - } - // Response to specific message previously sent - if (details.msgId !== undefined) { - const resolver = this.pending.get(details.msgId); - if (resolver !== undefined) { - this.pending.delete(details.msgId); - resolver(details.msg); - return; - } - } - }, - messageListenerBound: null, - canDestroyPort: function () { - return this.pending.size === 0; - }, - portPoller: function () { - this.portTimer = null; - if (this.port !== null && this.canDestroyPort()) { - return this.destroyPort(); - } - this.portTimer = setTimeout(this.portPollerBound, this.portTimerDelay); - this.portTimerDelay = Math.min(this.portTimerDelay * 2, 60 * 60 * 1000); - }, - portPollerBound: null, - destroyPort: function () { - if (this.portTimer !== null) { - clearTimeout(this.portTimer); - this.portTimer = null; - } - const port = this.port; - if (port !== null) { - port.disconnect(); - port.onMessage.removeListener(this.messageListenerBound); - port.onDisconnect.removeListener(this.disconnectListenerBound); - this.port = null; - } - // service pending callbacks - if (this.pending.size !== 0) { - const pending = this.pending; - this.pending = new Map(); - for (const resolver of pending.values()) { - resolver(); - } - } - }, - createPort: function () { - if (this.shuttingDown) { - return null; - } - if (this.messageListenerBound === null) { - this.messageListenerBound = this.messageListener.bind(this); - this.disconnectListenerBound = this.disconnectListener.bind(this); - this.portPollerBound = this.portPoller.bind(this); - } - try { - this.port = webext.runtime.connect({ name: 'hermes' }) || null; - // eslint-disable-next-line no-unused-vars - } catch (ex) { - this.port = null; - } - if (this.port === null) { - return null; - } - this.port.onMessage.addListener(this.messageListenerBound); - this.port.onDisconnect.addListener(this.disconnectListenerBound); - this.portTimerDelay = 10000; - if (this.portTimer === null) { - this.portTimer = setTimeout(this.portPollerBound, this.portTimerDelay); - } - return this.port; - }, - getPort: function () { - return this.port !== null ? this.port : this.createPort(); - }, - send: function (channel, msg) { - // Too large a gap between the last request and the last response means - // the main process is no longer reachable: memory leaks and bad - // performance become a risk -- especially for long-lived, dynamic - // pages. Guard against this. - if (this.pending.size > 64) { - if (Date.now() - this.waitStartTime > 60000) { - this.shutdown(); - } - } - const port = this.getPort(); - if (port === null) { - return Promise.resolve(); - } - if (this.pending.size === 0) { - this.waitStartTime = Date.now(); - } - const msgId = this.msgIdGenerator++; - const promise = new Promise((resolve) => { - this.pending.set(msgId, resolve); - }); - port.postMessage({ channel, msgId, msg }); - return promise; - } - }; -} - -void 0; \ No newline at end of file diff --git a/src/js/network.js b/src/js/network.js index 50fc613..7a8440d 100644 --- a/src/js/network.js +++ b/src/js/network.js @@ -9,59 +9,57 @@ const Network = { if (isEmpty(url)) { throw new Error('"url" parameter is empty'); } - method = Network.bscStr(method, false); - responseType = Network.bscStr(responseType); + data = Object.assign({}, data); + method = this.bscStr(method, false); + responseType = this.bscStr(responseType); const params = { method, ...data }; - return await new Promise((resolve, reject) => { - /** - * @param { Response } response - * @returns { Response | Document } - */ - const fetchResp = (response_1) => { - if (!response_1.ok) reject(response_1); - const check = (str_2 = 'text') => { - return isFN(response_1[str_2]) ? response_1[str_2]() : response_1; - }; - if (responseType.match(/buffer/i)) { - resolve(check('arrayBuffer')); - } else if (responseType.match(/json/i)) { - resolve(check('json')); - } else if (responseType.match(/text/i)) { - resolve(check('text')); - } else if (responseType.match(/blob/i)) { - resolve(check('blob')); - } else if (responseType.match(/formdata/i)) { - resolve(check('formData')); - } else if (responseType.match(/clone/i)) { - resolve(check('clone')); - } else if (responseType.match(/document/i) && isFN(response_1.text)) { - const domParser = new DOMParser(); - const respTxt = response_1.text(); - if (respTxt instanceof Promise) { - respTxt.then((txt) => { - const doc = domParser.parseFromString(txt, 'text/html'); + return new Promise((resolve, reject) => { + fetch(url, params) + .then((response_1) => { + if (!response_1.ok) reject(response_1); + const check = (str_2 = 'text') => { + return isFN(response_1[str_2]) ? response_1[str_2]() : response_1; + }; + if (responseType.match(/buffer/)) { + resolve(check('arrayBuffer')); + } else if (responseType.match(/json/)) { + resolve(check('json')); + } else if (responseType.match(/text/)) { + resolve(check('text')); + } else if (responseType.match(/blob/)) { + resolve(check('blob')); + } else if (responseType.match(/formdata/)) { + resolve(check('formData')); + } else if (responseType.match(/clone/)) { + resolve(check('clone')); + } else if (responseType.match(/document/)) { + const respTxt = check('text'); + const domParser = new DOMParser(); + if (respTxt instanceof Promise) { + respTxt.then((txt) => { + const doc = domParser.parseFromString(txt, 'text/html'); + resolve(doc); + }); + } else { + const doc = domParser.parseFromString(respTxt, 'text/html'); resolve(doc); - }); + } } else { - const doc = domParser.parseFromString(respTxt, 'text/html'); - resolve(doc); + resolve(response_1); } - } else { - resolve(response_1); - } - }; - fetch(url, params).then(fetchResp).catch(reject); + }) + .catch(reject); }); }, format(bytes, decimals = 2) { - if (Number.isNaN(bytes)) return '0 Bytes'; + if (Number.isNaN(bytes)) return `0 ${this.sizes[0]}`; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const i = Math.floor(Math.log(bytes) / Math.log(k)); - return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${Network.sizes[i]}`; + return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${this.sizes[i]}`; }, sizes: ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], bscStr(str = '', lowerCase = true) { @@ -70,4 +68,4 @@ const Network = { } }; -export default Network; \ No newline at end of file +export default Network; diff --git a/src/js/popup.js b/src/js/popup.js index cde4b29..cc2373c 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1,74 +1,95 @@ 'use strict'; + +import { webext, runtime, sendMessage } from './ext.js'; import { err, log, info } from './logger.js'; -import { i18n$ } from './i18n.js'; -import { dom, normalizeTarget, qs, qsA } from './querySelector.js'; -import { reqCode, parse_meta } from './request-code.js'; -import { ael, make, isBlank, isNull, isEmpty, isObj, isString, hasOwn, openInTab } from './util.js'; -import { XMap } from './XMap.js'; +import { i18n$, language } from './i18n.js'; +import { dom, qs, qsA } from './querySelector.js'; +import { ParseUserJS } from './request-code.js'; +import Network from './network.js'; +import { + ael, + make, + isNull, + isEmpty, + isElem, + isObj, + openInTab, + strToURL, + isRegExp, + loadFilters, + formatURL +} from './util.js'; +import { builtinList, template, BLANK_PAGE, badUserJS, authorID, goodUserJS } from './constants.js'; +import { DEFAULT_CONFIG } from './storage.js'; +import { BaseContainer, BaseList } from './container.js'; +/******************************************************************************/ /** * @type { import("../typings/types").config } */ let cfg = {}; +/******************************************************************************/ + +/** + * @type { chrome.tabs.Tab | browser.tabs.Tab } + */ +const currentTab = {}; +const tabURL = new URL(runtime.getURL('/')); -const { hermes } = userjs; +/******************************************************************************/ -// Lets highlight me :) -const authorID = 166061; -// Some UserJS I personally enjoy -const goodUserJS = [ - 423001, - 376510, - 23840, - 40525, - 6456, - 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/Manga_OnlineViewer.user.js', - 'https://github.com/jesus2099/konami-command/raw/master/INSTALL-USER-SCRIPT.user.js', - 'https://github.com/TagoDR/MangaOnlineViewer/raw/master/dist/Manga_OnlineViewer_Adult.user.js' -]; +function normalizedHostname(hn) { + return hn.replace(/^www\./, ''); +} + +/******************************************************************************/ + +const params = new URLSearchParams(location.search); +//#region Icon SVGs const iconSVG = { - install: { - viewBox: '0 0 16 16', - html: '' - }, - search: { - viewBox: '0 0 24 24', - html: '' - }, + close: 'fa-solid fa-xmark', + code: 'fa-solid fa-code', + collapse: 'fa-solid fa-compress', + download: 'fa-solid fa-file-arrow-down', + expand: 'fa-solid fa-arrow-up-right-from-square', // fa-expand + gear: 'fa-solid fa-gear', + github: 'fa-brands fa-github', + globe: 'fa-solid fa-globe', + install: 'fa-solid fa-download', + issue: 'fa-solid fa-bug', + minus: 'fa-solid fa-minus', + nav: 'fa-solid fa-bars', + pager: 'fa-solid fa-pager', verified: { viewBox: '0 0 56 56', fill: 'currentColor', stroke: 'currentColor', html: '' }, - refresh: { - viewBox: '0 0 1024 1024', - fill: 'currentColor', - html: '' - }, - // get(type, container) { - // return new Promise((resolve) => { - // const img = new Image(); - // img.src = webext.runtime.getURL(`/img/${type}.svg`); - // img.onload = () => { - // if (container) { - // container.appendChild(img); - // } - // resolve(img); - // } - // }) - // }, + refresh: 'fa-solid fa-rotate-right', load(type, container) { - const xmlns = 'http://www.w3.org/2000/svg'; - const svgElem = document.createElementNS(xmlns, 'svg'); - for (const [k, v] of Object.entries(iconSVG[type])) { - if (k === 'html') { - continue; + let svgElem; + if (typeof iconSVG[type] === 'string') { + svgElem = make('i', iconSVG[type], { + id: `mujs_${type ?? 'Unknown'}` + }); + } else { + svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + for (const [k, v] of Object.entries(iconSVG[type])) { + if (k === 'html') { + continue; + } + svgElem.setAttributeNS(null, k, v); + } + try { + if (typeof iconSVG[type].html === 'string') { + svgElem.innerHTML = iconSVG[type].html; + dom.attr(svgElem, 'id', `mujs_${type ?? 'Unknown'}`); + } + // eslint-disable-next-line no-unused-vars + } catch (ex) { + /* empty */ } - svgElem.setAttributeNS(null, k, v); - } - if (isString(iconSVG[type].html)) { - svgElem.innerHTML = iconSVG[type].html; } if (container) { container.appendChild(svgElem); @@ -77,78 +98,8 @@ const iconSVG = { return svgElem.outerHTML; } }; - -const main = qs('mujs-main'); -const cfgpage = qs('form'); -const footer = qs('.mujs-footer'); -const rateContainer = qs('.rate-container'); - -const table = qs('table'); -const tabbody = qs('tbody'); -const tabhead = qs('thead'); - -const urlBar = qs('.mujs-url-bar'); -const btncfg = qs('mujs-btn.settings'); -const btngreasy = qs('mujs-btn.greasy'); -const btnissue = qs('mujs-btn.issue'); -const btnhome = qs('mujs-btn.github'); - -const toolbar = qs('mujs-toolbar'); - -const promptElem = make('mujs-row', 'mujs-prompt'); -main.append(promptElem); - -const makeTHead = (rows) => { - const tr = make('tr'); - for (const r of normalizeTarget(rows)) { - const tparent = make('th', r.class ?? '', r); - tr.append(tparent); - } - tabhead.append(tr); - table.append(tabhead, tabbody); -}; -makeTHead([ - { - class: 'mujs-header-name', - textContent: i18n$('name') - }, - { - textContent: i18n$('createdby') - }, - { - textContent: i18n$('daily_installs') - }, - { - textContent: i18n$('updated') - }, - { - textContent: i18n$('install') - } -]); - -const renderTheme = (theme) => { - theme = theme || cfg.theme; - if (isEmpty(theme)) { - return; - } - // if (theme === defcfg.theme) { - // return; - // } - const sty = qs('mujs-root').style; - for (const [k, v] of Object.entries(theme)) { - const str = `--mujs-${k}`; - const prop = sty.getPropertyValue(str); - if (isEmpty(v)) { - theme[k] = prop; - } - if (prop === v) { - continue; - } - sty.removeProperty(str); - sty.setProperty(str, v); - } -}; -const cfgMap = new XMap(); +//#endregion +const cfgMap = new Map(); const rebuildCfg = () => { for (const engine of cfg.engines) { if (cfgMap.has(engine.name)) { @@ -172,88 +123,457 @@ const rebuildCfg = () => { } } } - dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); - dom.prop(cfgMap.get('theme'), 'value', JSON.stringify(cfg.theme, null, ' ')); - renderTheme(cfg.theme); + // dom.prop(cfgMap.get('blacklist'), 'value', JSON.stringify(cfg.blacklist, null, ' ')); + for (const [k, v] of Object.entries(cfg.theme)) { + dom.prop(cfgMap.get(k), 'value', v); + } + container.renderTheme(cfg.theme); }; -const getHost = (str = '') => { - return str.split('.').splice(-2).join('.'); +const Counter = { + cnt: { + total: { + count: 0 + } + }, + set(engine) { + if (!this.cnt[engine.name]) { + const counter = make('count-frame', engine.enabled ? '' : 'hidden', { + dataset: { + counter: engine.name + }, + title: engine.query ? decodeURIComponent(engine.query) : engine.url, + textContent: '0' + }); + this.cnt[engine.name] = { + root: counter, + count: 0 + }; + return counter; + } + return this.cnt[engine.name].root; + }, + update(count, engine) { + this.cnt[engine.name].count += count; + this.cnt.total.count += count; + this.updateAll(); + }, + updateAll() { + for (const v of Object.values(this.cnt)) dom.text(v.root, v.count); + webext.action.setBadgeText({ + text: `${this.cnt.total.count}` + }); + document.title = `Magic UserJS+ (${this.cnt.total.count})`; + }, + reset() { + for (const [k, v] of Object.entries(this.cnt)) { + dom.text(v.root, 0); + v.count = 0; + const engine = cfg.engines.find((engine) => k === engine.name); + if (engine) { + dom.cl[engine.enabled ? 'remove' : 'add'](v.root, 'hidden'); + } + } + webext.action.setBadgeText({ + text: '0' + }); + document.title = 'Magic UserJS+ (0)'; + } }; -const ContainerHandler = class { - constructor() { +// #region Container +class Container extends BaseContainer { + constructor(url) { + super(url); + this.refresh = this.refresh.bind(this); this.showError = this.showError.bind(this); - // this.cleanup = this.cleanup.bind(this); - this.setHost(window.top.document.location.href); - this.cache = new XMap(); - this.userjsCache = new XMap(); + + this.webpage = strToURL(url); + this.host = this.getHost(this.webpage.host); + this.domain = this.getDomain(this.webpage.host); + this.unsaved = false; this.isBlacklisted = false; this.rebuild = false; - this.counters = { - total: 0 - }; - } + this.root = qs('mujs-root'); - setHost(link) { + this.init(); + } + // #region init + init() { try { - this.webpage = new URL(link); + this.mainbtn = make('count-frame', 'mainbtn', { + textContent: '0' + }); + this.promptElem = make('mujs-row', 'mujs-prompt'); + + this.urlBar = qs('.mujs-url-bar'); + this.rateContainer = qs('.rate-container'); + this.footer = qs('.mujs-footer'); + this.countframe = qs('.counter-container'); + this.toolbar = qs('mujs-toolbar'); + this.table = qs('table'); + this.tabhead = qs('thead'); + this.cfgpage = qs('.mujs-cfg'); + this.main = qs('mujs-main'); + this.tabbody = qs('tbody'); + this.btnframe = qs('.btn-frame'); + + this.btnfullscreen = make('mujs-btn', 'fullscreen', { + title: i18n$('max'), + innerHTML: iconSVG.load('expand'), + dataset: { + command: 'fullscreen' + } + }); + this.btnHandles = make('mujs-column', 'btn-handles'); + this.btncfg = make('mujs-btn', 'settings hidden', { + title: 'Settings', + innerHTML: iconSVG.load('gear'), + dataset: { + command: 'settings' + } + }); + this.btnhome = make('mujs-btn', 'github hidden', { + title: 'GitHub', + innerHTML: iconSVG.load('github'), + dataset: { + command: 'open-tab', + webpage: 'https://github.com/magicoflolis/Userscript-Plus' + } + }); + this.btnissue = make('mujs-btn', 'issue hidden', { + innerHTML: iconSVG.load('issue'), + title: i18n$('issue'), + dataset: { + command: 'open-tab', + webpage: 'https://github.com/magicoflolis/Userscript-Plus/issues' + } + }); + this.btngreasy = make('mujs-btn', 'greasy hidden', { + title: 'Greasy Fork', + innerHTML: iconSVG.load('globe'), + dataset: { + command: 'open-tab', + webpage: 'https://greasyfork.org/scripts/421603' + } + }); + this.btnnav = make('mujs-btn', 'nav', { + title: 'Navigation', + innerHTML: iconSVG.load('nav'), + dataset: { + command: 'navigation' + } + }); + if (params.size === 0) { + this.btnHandles.append(this.btnfullscreen); + } + + this.toolbar.append(this.btnHandles); + this.btnframe.append(this.btnhome, this.btngreasy, this.btnissue, this.btncfg, this.btnnav); + this.main.append(this.promptElem); + + const { host, refresh, cache, table } = this; + class Tabs { + /** + * @param { HTMLElement } root + */ + constructor(root) { + /** + * @type { Set } + */ + this.pool = new Set(); + this.blank = BLANK_PAGE; + this.protocal = 'mujs:'; + this.protoReg = new RegExp(`${this.protocal}(.+)`, 'i'); + this.el = { + add: make('mujs-addtab', { + textContent: '+', + dataset: { + command: 'new-tab' + } + }), + head: make('mujs-tabs'), + root + }; + this.el.head.append(this.el.add); + this.el.root.append(this.el.head); + this.custom = () => {}; + } + /** + * @param {string} hostname + */ + getTab(hostname) { + return [...this.pool].find(({ dataset }) => hostname === dataset.host); + } + getActive() { + return [...this.pool].find((tab) => tab.classList.contains('active')); + } + /** + * @param {string} hostname + */ + intFN(hostname) { + if (!hostname.startsWith(this.protocal)) { + return; + } + const p = this.protoReg.exec(hostname); + if (!p) { + return; + } + if (p[1] === 'settings') { + dom.cl.remove(cfgpage, 'hidden'); + dom.cl.add(table, 'hidden'); + urlBar.placeholder = 'Search settings'; + } + } + /** + * @param {HTMLElement} tab + * @param {boolean} [build] + */ + active(tab, build = true) { + if (!this.pool.has(tab)) this.pool.add(tab); + dom.cl.add([table, cfgpage], 'hidden'); + dom.cl.remove([...this.pool], 'active'); + dom.cl.add(tab, 'active'); + if (!build) { + dom.cl.remove(table, 'hidden'); + return; + } + const host = tab.dataset.host ?? this.blank; + if (host === this.blank) { + dom.cl.add(cfgpage, 'hidden'); + dom.cl.remove(table, 'hidden'); + refresh(); + } else if (host.startsWith(this.protocal)) { + this.intFN(host); + } else { + dom.cl.add(cfgpage, 'hidden'); + dom.cl.remove(table, 'hidden'); + this.custom(host); + } + } + /** @param { HTMLElement } tab */ + close(tab) { + if (this.pool.has(tab)) this.pool.delete(tab); + const host = tab.dataset.host; + if (cfg.clearTabCache && cache.has(host)) { + cache.delete(host); + sendMessage({ + type: 'clear', + host + }); + } + if (tab.classList.contains('active')) refresh(); + const sibling = tab.nextElementSibling ?? tab.previousElementSibling; + if (sibling) { + if (sibling.dataset.command !== 'new-tab') { + this.active(sibling); + } + } + tab.remove(); + } + /** + * @param {string} [hostname] + */ + create(hostname = undefined) { + if (typeof hostname === 'string') { + const createdTab = this.getTab(hostname); + if (this.protoReg.test(hostname) && createdTab) { + this.active(createdTab); + return; + } + } + const tab = make('mujs-tab', { + dataset: { + command: 'switch-tab' + }, + style: `order: ${this.el.head.childElementCount};` + }); + const tabClose = make('mu-js', { + dataset: { + command: 'close-tab' + }, + title: i18n$('close'), + textContent: 'X' + }); + const tabHost = make('mujs-host'); + const p = this.protoReg.exec(hostname); + tab.append(tabHost, tabClose); + this.el.head.append(tab); + this.active(tab, false); + if (isNull(hostname)) { + refresh(); + tab.dataset.host = this.blank; + tabHost.title = i18n$('newTab'); + tabHost.textContent = i18n$('newTab'); + // hostname.startsWith(this.protocal) + } else if (p) { + tab.dataset.host = hostname || host; + tabHost.title = p[1] || tab.dataset.host; + tabHost.textContent = tabHost.title; + this.intFN(hostname); + } else { + tab.dataset.host = hostname || host; + tabHost.title = hostname || host; + tabHost.textContent = tabHost.title; + // this.custom(host); + } + return tab; + } + } + this.Tabs = new Tabs(this.toolbar); + + const makeTHead = (rows = []) => { + const tr = make('tr'); + for (const r of rows) { + const tparent = make('th', r.class ?? '', r); + tr.append(tparent); + } + this.tabhead.append(tr); + this.table.append(this.tabhead, this.tabbody); + }; + makeTHead([ + { + class: 'mujs-header-name', + textContent: i18n$('name') + }, + { + textContent: i18n$('createdby') + }, + { + textContent: i18n$('daily_installs') + }, + { + textContent: i18n$('updated') + }, + { + textContent: i18n$('install') + } + ]); + + const tabbody = this.tabbody; + const getCellValue = (tr, idx) => + tr.children[idx].dataset.value || tr.children[idx].textContent; + const comparer = (idx, asc) => (a, b) => + ((v1, v2) => + v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) + ? v1 - v2 + : v1.toString().localeCompare(v2))( + getCellValue(asc ? a : b, idx), + getCellValue(asc ? b : a, idx) + ); + for (const th of this.tabhead.rows[0].cells) { + if (dom.text(th) === i18n$('install')) continue; + dom.cl.add(th, 'mujs-pointer'); + ael(th, 'click', () => { + /** [Stack Overflow Reference](https://stackoverflow.com/questions/14267781/sorting-html-table-with-javascript/53880407#53880407) */ + Array.from(tabbody.querySelectorAll('tr')) + .sort(comparer(Array.from(th.parentNode.children).indexOf(th), (this.asc = !this.asc))) + .forEach((tr) => tabbody.appendChild(tr)); + }); + } + return true; } catch (ex) { - err(ex, { cause: 'ContainerHandler' }); - this.webpage = window.location; + err(ex); } - this.host = getHost(this.webpage.hostname); + return false; + } + initFn() { + Counter.cnt.total.root = this.mainbtn; + for (const engine of cfg.engines) this.countframe.append(Counter.set(engine)); + } + // #endregion + setHost(link) { + this.webpage = strToURL(link); + this.host = this.getHost(this.webpage.host); + this.domain = this.getDomain(this.webpage.host); } - checkBlacklist(str) { str = str || this.host; let blacklisted = false; - for (const b of cfg.blacklist.filter((b) => b.enabled)) { - if (b.regex === true) { - const reg = new RegExp(b.url, b.flags); - if (!reg.test(str)) continue; - blacklisted = true; - } - if (Array.isArray(b.url)) { - for (const c of b.url) { - if (!str.includes(c)) continue; + if (/accounts*\.google\./.test(this.webpage.host)) { + blacklisted = true; + } + const blacklist = cfg.blacklist ?? []; + for (const b of blacklist) { + if (typeof b === 'string') { + if (b.startsWith('userjs-')) { + const r = /userjs-(\w+)/.exec(b)[1]; + const biList = builtinList[r]; + if (isRegExp(biList)) { + if (!biList.test(str)) continue; + blacklisted = true; + } else if (isObj(biList) && biList.host === this.host) { + blacklisted = true; + } + } + } else if (isObj(b)) { + if (!b.enabled) { + continue; + } + if (b.regex === true) { + const reg = new RegExp(b.url, b.flags); + if (!reg.test(str)) continue; blacklisted = true; } + if (Array.isArray(b.url)) { + for (const c of b.url) { + if (!str.includes(c)) continue; + blacklisted = true; + } + } + if (!str.includes(b.url)) continue; + blacklisted = true; } - if (!str.includes(b.url)) continue; - blacklisted = true; - } - if (blacklisted) { - this.showError('Blacklisted'); } this.isBlacklisted = blacklisted; - return blacklisted; + return this.isBlacklisted; } - - updateCounter(count, engine) { - this.counters[engine.name] += count; - this.counters.total += count; - this.updateCounters(); + getInfo(url) { + const webpage = strToURL(url || this.webpage); + const host = this.getHost(webpage.host); + const domain = this.getDomain(webpage.host); + return { + domain, + host, + webpage + }; } - - updateCounters() { - for (const [k, v] of Object.entries(this.counters)) { - if (k === 'total') { - continue; + /** + * @template { string } S + * @param { S } str + */ + getHost(str = '') { + return str.split('.').splice(-2).join('.'); + } + /** + * @template { string } S + * @param { S } str + */ + getDomain(str = '') { + return str.split('.').at(-2) ?? BLANK_PAGE; + } + renderTheme(theme) { + theme = theme || cfg.theme || DEFAULT_CONFIG.theme; + if (theme === DEFAULT_CONFIG.theme) { + return; + } + const sty = this.root.style; + for (const [k, v] of Object.entries(theme)) { + const str = `--mujs-${k}`; + const prop = sty.getPropertyValue(str); + if (isEmpty(v)) { + theme[k] = prop; } - if (qs(`count-frame[data-counter="${k}"]`)) { - dom.text(qs(`count-frame[data-counter="${k}"]`), v); + if (prop === v) { + continue; } + sty.removeProperty(str); + sty.setProperty(str, v); } - webext.browserAction.setBadgeText({ - text: `${this.counters.total}` - }); - document.title = `Magic UserJS+ (${this.counters.total})`; } - makePrompt(txt, dataset = {}, usePrompt = true) { - if (qs('.prompt', promptElem)) { - for (const elem of qsA('.prompt', promptElem)) { + if (qs('.prompt', this.promptElem)) { + for (const elem of qsA('.prompt', this.promptElem)) { if (elem.dataset.prompt) { elem.remove(); } @@ -285,217 +605,56 @@ const ContainerHandler = class { elPrompt.append(elYes, elNo); el.append(elPrompt); } - promptElem.append(el); + this.promptElem.append(el); } - save() { this.unsaved = false; - // MU.storage.setValue('Config', cfg); + sendMessage({ + type: 'save', + cfg + }); info('Saved:', cfg); } - + /** + * @template {string | Error} E + * @param {...E} ex + */ showError(...ex) { err(...ex); const error = make('mu-js', 'error'); let str = ''; for (const e of ex) { - str += `${isString(e) ? e : `${e.message} ${e.stack}`}\n`; - } - error.appendChild(document.createTextNode(str)); - footer.append(error); - } - - refresh() { - urlBar.placeholder = i18n$('newTab'); - this.counters.total = 0; - for (const engine of cfg.engines) { - this.counters[engine.name] = 0; - } - this.updateCounters(); - dom.prop([tabbody, rateContainer, footer], 'innerHTML', ''); - } -}; -const MUJS = new ContainerHandler(); - -class Tabs { - constructor() { - this.Tab = new XMap(); - this.blank = 'about:blank'; - this.protocal = 'mujs:'; - this.protoReg = new RegExp(`${this.protocal}(.+)`); - this.el = { - add: make('mujs-addtab', '', { - textContent: '+', - dataset: { - command: 'new-tab' - } - }), - head: make('mujs-tabs') - }; - this.el.head.append(this.el.add); - toolbar.append(this.el.head); - } - hasTab(...params) { - for (const p of params) { - if (!this.Tab.has(p)) { - return false; - } - const content = normalizeTarget(this.Tab.get(p)).filter((t) => p === t.dataset.host); - if (isBlank(content)) { - return false; - } - } - return true; - } - storeTab(host) { - const h = host ?? this.blank; - if (!this.Tab.has(h)) { - this.Tab.set(h, new Set()); - } - return this.Tab.get(h); - } - cache(host, ...tabs) { - const h = host ?? this.blank; - const tabCache = this.storeTab(h); - for (const t of normalizeTarget(tabs)) { - if (tabCache.has(t)) { - continue; - } - tabCache.add(t); - } - this.Tab.set(h, tabCache); - return tabCache; - } - mujs(host) { - if (!host.startsWith(this.protocal)) { - return; - } - const type = host.match(this.protoReg)[1]; - if (type === 'settings') { - dom.cl.remove([cfgpage], 'hidden'); - dom.cl.add(table, 'hidden'); - urlBar.placeholder = i18n$('search_placeholder'); - } - } - active(tab, build = true) { - for (const t of normalizeTarget(tab, false)) { - dom.cl.add([cfgpage], 'hidden'); - dom.cl.remove(table, 'hidden'); - dom.cl.remove(qsA('mujs-tab', this.el.head), 'active'); - dom.cl.add(t, 'active'); - if (!build) { - continue; - } - const host = t.dataset.host ?? this.blank; - if (host === this.blank) { - MUJS.refresh(); - } else if (host.startsWith(this.protocal)) { - this.mujs(host); - } else { - buildlist(host); - } - } - } - /** @param { HTMLElement } tab */ - close(tab) { - for (const t of normalizeTarget(tab, false)) { - const host = t.dataset.host; - if (MUJS.cache.has(host)) { - MUJS.cache.delete(host); - } - if (dom.cl.has(t, 'active')) { - MUJS.refresh(); - } - const sibling = t.previousElementSibling ?? t.nextElementSibling; - if (sibling) { - if (sibling.dataset.command !== 'new-tab') { - this.active(sibling); + str += `${typeof e === 'string' ? e : `${e.cause ? `[${e.cause}] ` : ''}${e.message}${e.stack ? ` ${e.stack}` : ''}`}\n`; + if (isObj(e)) { + if (e.notify) { + dom.cl.add(this.mainframe, 'error'); } } - if (this.Tab.has(host)) { - this.Tab.delete(host); - } - t.remove(); } + error.appendChild(document.createTextNode(str)); + this.footer.append(error); } - create(host = undefined) { - if (isString(host)) { - if (host.startsWith(this.protocal) && this.hasTab(host)) { - this.active(this.Tab.get(host)); - return; - } - const content = normalizeTarget(this.storeTab(host)).filter((t) => host === t.dataset.host); - if (!isEmpty(content)) { - return; - } - } - const tab = make('mujs-tab', '', { - dataset: { - command: 'switch-tab' - }, - style: `order: ${this.el.head.childElementCount};` - }); - const tabClose = make('mu-js', '', { - dataset: { - command: 'close-tab' - }, - title: i18n$('close'), - textContent: 'X' - }); - const tabHost = make('mujs-host'); - tab.append(tabHost, tabClose); - this.el.head.append(tab); - this.active(tab, false); - this.cache(host, tab); - if (isNull(host)) { - MUJS.refresh(); - // urlBar.placeholder = i18n$('newTab'); - tab.dataset.host = this.blank; - tabHost.title = i18n$('newTab'); - tabHost.textContent = i18n$('newTab'); - } else if (host.startsWith(this.protocal)) { - const type = host.match(this.protoReg)[1]; - tab.dataset.host = host || MUJS.host; - tabHost.title = type || tab.dataset.host; - tabHost.textContent = tabHost.title; - this.mujs(host); - } else { - tab.dataset.host = host || MUJS.host; - tabHost.title = host || MUJS.host; - tabHost.textContent = tabHost.title; - } - return tab; + refresh() { + this.urlBar.placeholder = i18n$('newTab'); + Counter.reset(); + dom.cl.remove(this.toElem(), 'hidden'); + dom.cl.remove(qsA('mujs-section[data-name]', this.cfgpage), 'hidden'); + dom.prop([this.tabbody, this.rateContainer, this.footer], 'innerHTML', ''); } } -const tab = new Tabs(); - -const template = { - id: 0, - bad_ratings: 0, - good_ratings: 0, - ok_ratings: 0, - daily_installs: 0, - total_installs: 0, - name: 'NOT FOUND', - description: 'NOT FOUND', - version: '0.0.0', - url: 'about:blank', - code_url: 'about:blank', - created_at: Date.now(), - code_updated_at: Date.now(), - users: [ - { - name: '', - url: '' - } - ] +const container = new Container(window.top.document.location.href); +// #endregion +const { urlBar, tabbody, cfgpage, main, Tabs, showError } = container; +container.Tabs.custom = (host) => { + MUList.host = host; + MUList.build(); }; + const mkList = (txt = '', obj = {}) => { if (!obj.root || !obj.type) { return; } const { root, type } = obj; - const list = obj.list ?? []; const appliesTo = make('mu-js', 'mujs-list', { textContent: `${txt}: ` }); @@ -508,26 +667,48 @@ const mkList = (txt = '', obj = {}) => { }); ujsURLs.append(appliesTo, applyList); root.append(ujsURLs); + + const list = obj.list ?? []; if (isEmpty(list)) { const elem = make('mujs-a', '', { textContent: i18n$('listing_none') }); applyList.append(elem); - if (type === 'antifeatures') { - dom.cl.add(ujsURLs, 'hidden'); - } + dom.cl.add(ujsURLs, 'hidden'); return; } for (const c of list) { - if (isObj(c)) { + if (typeof c === 'string' && c.startsWith('http')) { const elem = make('mujs-a', '', { - textContent: c.text + textContent: c, + dataset: { + command: 'open-tab', + webpage: c + } }); - if (c.domain) { - elem.dataset.command = 'open-tab'; - elem.dataset.webpage = `https://${c.text}`; - } applyList.append(elem); + } else if (isObj(c)) { + if (type === 'resource') { + for (const [k, v] of Object.entries(c)) { + const elem = make('mujs-a', '', { + textContent: k ?? 'ERROR' + }); + if (v.startsWith('http')) { + elem.dataset.command = 'open-tab'; + elem.dataset.webpage = v; + } + applyList.append(elem); + } + } else { + const elem = make('mujs-a', '', { + textContent: c.text + }); + if (c.domain) { + elem.dataset.command = 'open-tab'; + elem.dataset.webpage = `https://${c.text}`; + } + applyList.append(elem); + } } else { const elem = make('mujs-a', '', { textContent: c @@ -535,35 +716,35 @@ const mkList = (txt = '', obj = {}) => { applyList.append(elem); } } - if (type === 'antifeatures') { - dom.cl.remove(ujsURLs, 'hidden'); - } -}; -const toLocaleDate = (str = '') => { - return new Intl.DateTimeFormat(navigator.language).format(new Date(str)); }; // #region Create UserJS +/** + * @param { import("../typings/types.d.ts").GSForkQuery } ujs + * @param { string } engine + */ const createjs = (ujs, engine) => { - for (const key in template) { - if (hasOwn(ujs, key)) { - continue; - } - ujs[key] = template[key]; - } // Lets not add this UserJS to the list if (ujs.id === 421603) { return; } - if (!MUJS.userjsCache.has(ujs.id)) { - MUJS.userjsCache.set(ujs.id, ujs); + if (badUserJS.includes(ujs.id) || badUserJS.includes(ujs.url)) { + return; } + if (!container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); const eframe = make('td', 'install-btn'); const uframe = make('td', 'mujs-uframe'); const fdaily = make('td', 'mujs-list', { - textContent: ujs.daily_installs + textContent: ujs.daily_installs, + dataset: { + name: 'daily_installs' + } }); const fupdated = make('td', 'mujs-list', { - textContent: toLocaleDate(ujs.code_updated_at) + textContent: language.toDate(ujs.code_updated_at), + dataset: { + name: 'code_updated_at', + value: new Date(ujs.code_updated_at).toISOString() + } }); const fname = make('td', 'mujs-name'); const fmore = make('mujs-column', 'mujs-list hidden', { @@ -587,16 +768,24 @@ const createjs = (ujs, engine) => { textContent: `${i18n$('version_number')}: ${ujs.version}` }); const fcreated = make('mu-js', 'mujs-list', { - textContent: `${i18n$('created_date')}: ${toLocaleDate(ujs.created_at)}` + textContent: `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`, + dataset: { + name: 'created_at', + value: new Date(ujs.created_at).toISOString() + } }); const flicense = make('mu-js', 'mujs-list', { title: ujs.license ?? i18n$('no_license'), textContent: `${i18n$('license')}: ${ujs.license ?? i18n$('no_license')}`, - style: - 'text-overflow: ellipsis; overflow: hidden; white-space: nowrap; width: fit-content; max-width: 20em;' + dataset: { + name: 'license' + } }); const ftotal = make('mu-js', 'mujs-list', { - textContent: `${i18n$('total_installs')}: ${ujs.total_installs}` + textContent: `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}`, + dataset: { + name: 'total_installs' + } }); const fratings = make('mu-js', 'mujs-list', { title: i18n$('ratings'), @@ -606,6 +795,7 @@ const createjs = (ujs, engine) => { title: i18n$('good'), textContent: ujs.good_ratings, dataset: { + name: 'good_ratings', el: 'good' } }); @@ -613,6 +803,7 @@ const createjs = (ujs, engine) => { title: i18n$('ok'), textContent: ujs.ok_ratings, dataset: { + name: 'ok_ratings', el: 'ok' } }); @@ -620,6 +811,7 @@ const createjs = (ujs, engine) => { title: i18n$('bad'), textContent: ujs.bad_ratings, dataset: { + name: 'bad_ratings', el: 'bad' } }); @@ -630,18 +822,16 @@ const createjs = (ujs, engine) => { command: 'list-description' } }); - const sIcon = ujs.code_url.endsWith('.user.css') ? '🧾' : ujs.code_url.endsWith('.user.js') ? '🐵' : '💾'; const scriptInstall = make('mu-jsbtn', 'install', { - // innerHTML: `${iconSVG.load('install')} ${i18n$('install')}`, - innerHTML: `${sIcon} ${i18n$('install')}`, + innerHTML: `${iconSVG.load('install')} ${i18n$('install')}`, title: `${i18n$('install')} "${ujs.name}"`, dataset: { command: 'install-script', userjs: ujs.code_url } }); - const scriptDownload = make('mu-jsbtn', '', { - innerHTML: `${iconSVG.load('install')} ${i18n$('saveFile')}`, + const scriptDownload = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('download')} ${i18n$('saveFile')}`, dataset: { command: 'download-userjs', userjs: ujs.id, @@ -662,21 +852,26 @@ const createjs = (ujs, engine) => { spellcheck: false, wrap: 'soft' }); - const loadCode = make('mu-jsbtn', '', { - innerHTML: `${iconSVG.load('search')} ${i18n$('preview_code')}`, + const loadCode = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('code')} ${i18n$('preview_code')}`, dataset: { command: 'load-userjs', userjs: ujs.id } }); - if (engine) { - tr.dataset.engine = engine; - if (!engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.url)) { - tr.dataset.good = 'upsell'; + const loadMetadata = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('code')} Metadata`, + dataset: { + command: 'load-header', + userjs: ujs.id } + }); + tr.dataset.engine = engine; + if (!engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.url)) { + tr.dataset.good = 'upsell'; } for (const u of ujs.users) { - const user = make('mujs-a', '', { + const user = make('mujs-a', { innerHTML: u.name, title: u.url, dataset: { @@ -690,54 +885,211 @@ const createjs = (ujs, engine) => { } uframe.append(user); } - if (engine.includes('fork') && cfg.recommend.others && goodUserJS.includes(ujs.id)) { + if (cfg.recommend.others && goodUserJS.includes(ujs.id)) { tr.dataset.good = 'upsell'; } eframe.append(scriptInstall); ratings.append(fratings, fgood, fok, fbad); jsInfo.append(ftotal, ratings, fver, fcreated); - mkList('Size', { - list: ujs.code_size, - type: 'size', + mkList(i18n$('code_size'), { + list: ujs._mujs.code.code_size, + type: 'code_size', root: jsInfo }); jsInfoB.append(flicense); + const data_meta = ujs._mujs.code?.data_meta ?? {}; mkList(i18n$('antifeatures'), { - list: ujs.antifeatures, + list: data_meta.antifeatures ?? [], type: 'antifeatures', root: jsInfoB }); mkList(i18n$('applies_to'), { - list: ujs.code_match, - type: 'match-urls', + list: ujs._mujs.code?.data_names ?? [], + type: 'data_names', root: jsInfoB }); mkList('@grant', { - list: ujs.code_grant, - type: 'grants', + list: data_meta.grant ?? [], + type: 'grant', + root: jsInfoB + }); + mkList('@require', { + list: data_meta.require, + type: 'require', + root: jsInfoB + }); + mkList('@resource', { + list: isNull(data_meta.resource) ? [] : [data_meta.resource], + type: 'resource', root: jsInfoB }); fmore.append(jsInfo, jsInfoB); - fBtns.append(scriptDownload, loadCode); + fBtns.append(scriptDownload, loadCode, loadMetadata); fname.append(ftitle, fdesc, fmore, fBtns, codeArea); - if (ujs.code_data) { - codeArea.value = ujs.code_data; - } + const loadPage = make('mu-jsbtn', { + innerHTML: `${iconSVG.load('pager')} Page`, + dataset: { + command: 'load-page', + userjs: ujs.id + } + }); + fBtns.append(loadPage); - for (const e of [fname, uframe, fdaily, fupdated, eframe]) { - tr.append(e); - } - tabbody.append(tr); + if (ujs._mujs.code?.translated) tr.classList.add('translated'); + + for (const e of [fname, uframe, fdaily, fupdated, eframe]) tr.append(e); + ujs._mujs.root = tr; + return ujs._mujs.root; }; // #endregion +const applyTo = (ujs, name, elem, root) => { + const n = ujs._mujs.code[name] ?? ujs._mujs.code.data_meta[name]; + if (isEmpty(n)) { + const el = make('mujs-a', { + textContent: i18n$('listing_none') + }); + elem.append(el); + return; + } + dom.prop(elem, 'innerHTML', ''); + dom.cl.remove(root, 'hidden'); + if (isObj(n)) { + if (name === 'resource') { + for (const [k, v] of Object.entries(n)) { + const el = make('mujs-a', { + textContent: k ?? 'ERROR' + }); + if (v.startsWith('http')) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = v; + } + elem.append(el); + } + } else { + const el = make('mujs-a', { + textContent: n.text + }); + if (n.domain) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = `https://${n.text}`; + } + elem.append(el); + } + } else if (typeof n === 'string') { + const el = make('mujs-a', { + textContent: n + }); + elem.append(el); + } else { + for (const c of n) { + if (typeof c === 'string' && c.startsWith('http')) { + const el = make('mujs-a', { + textContent: c, + dataset: { + command: 'open-tab', + webpage: c + } + }); + elem.append(el); + } else if (isObj(c)) { + const el = make('mujs-a', { + textContent: c.text + }); + if (c.domain) { + el.dataset.command = 'open-tab'; + el.dataset.webpage = `https://${c.text}`; + } + elem.append(el); + } else { + const el = make('mujs-a', { + textContent: c + }); + elem.append(el); + } + } + } +}; const doInstallProcess = (installLink) => { - const queryOptions = { active: true, currentWindow: true }; - webext.tabs.query(queryOptions, (tabs) => { - webext.tabs.update(tabs[0].id, { url: installLink }); - }); + if (typeof currentTab.id === 'number') { + webext.tabs.update(currentTab.id, { url: installLink }); + } }; + +// #region List +class List extends BaseList { + constructor(hostname = undefined) { + super(hostname, container, cfg); + this.build = this.build.bind(this); + this.sortRecords = this.sortRecords.bind(this); + } + + // #region Builder + async build(results) { + try { + const { engines, container, host } = this; + if (isEmpty(engines)) { + for (const e of cfg.engines.filter((engine) => engine.enabled)) { + showError(`Engine: "${e.name}" unsupported on "${host}"`); + } + return; + } + if (container.checkBlacklist(host)) { + showError(`Blacklisted "${host}"`); + return; + } + container.refresh(); + if (!results) { + const { data } = await sendMessage({ + type: 'getData', + currentTab, + hostname: host + }); + results = data; + } + for (const ujs of results ?? []) { + ujs._mujs.code.request = async (translate = false, code_url) => { + if (ujs._mujs.code.data_code_block) { + return ujs._mujs.code; + } + const p = new ParseUserJS(); + await p.request(translate, code_url ?? ujs.code_url, ujs); + for (const [k, v] of Object.entries(p)) { + ujs._mujs.code[k] = v; + } + return ujs._mujs.code; + }; + createjs(ujs, ujs._mujs.info.engine.name); + } + urlBar.placeholder = i18n$('search_placeholder'); + urlBar.value = ''; + this.sortRecords(); + } catch (ex) { + showError(ex); + } + } + + sortRecords() { + const arr = Array.from(this); + for (const ujs of arr.flat().sort((a, b) => { + const sortType = cfg.autoSort ?? 'daily_installs'; + return b[sortType] - a[sortType]; + })) { + if (isElem(ujs._mujs.root)) tabbody.append(ujs._mujs.root); + } + for (const [name, value] of Object.entries(this.groupBy(arr))) { + Counter.update(value.length, { name }); + } + } + // #endregion +} +const MUList = new List(); +// #endregion + +container.renderTheme(); + +// #region Main event handlers ael(main, 'click', async (evt) => { try { /** @type { HTMLElement } */ @@ -758,7 +1110,7 @@ ael(main, 'click', async (evt) => { if (cmd === 'install-script' && dataset.userjs) { let installCode = dataset.userjs; if (!prmpt && dataset.userjs.endsWith('.user.css')) { - MUJS.makePrompt(i18n$('prmpt_css'), dataset); + container.makePrompt(i18n$('prmpt_css'), dataset); return; } else if (prmpt !== prmptChoice) { installCode = dataset.userjs.replace(/\.user\.css$/, '.user.js'); @@ -766,11 +1118,17 @@ ael(main, 'click', async (evt) => { doInstallProcess(installCode); } else if (cmd === 'open-tab' && dataset.webpage) { openInTab(dataset.webpage); + } else if (cmd === 'fullscreen') { + const tab = container.Tabs.getActive(); + openInTab(`${location.href}?host=${tab.dataset.host}`); } else if (cmd === 'navigation') { - if (dom.cl.has(btngreasy, 'hidden')) { - dom.cl.remove([btncfg, btngreasy, btnhome, btnissue], 'hidden'); - } else { - dom.cl.add([btncfg, btngreasy, btnhome, btnissue], 'hidden'); + for (const e of qsA('mujs-btn', target.parentElement)) { + if (dom.cl.has(e, 'nav')) continue; + if (dom.cl.has(e, 'hidden')) { + dom.cl.remove(e, 'hidden'); + } else { + dom.cl.add(e, 'hidden'); + } } } else if (cmd === 'list-description') { const arr = []; @@ -795,119 +1153,160 @@ ael(main, 'click', async (evt) => { } else { dom.cl.add(arr, 'hidden'); } - } else if (cmd === 'show-filter') { - dom.cl.toggle(qs('.mujs-fltlist').parentElement, 'hidden'); } else if (cmd === 'save') { if (!dom.prop(target, 'disabled')) { - MUJS.save(); - // sleazyRedirect(); - if (MUJS.rebuild) { - MUJS.cache.clear(); - buildlist(); + container.save(); + if (container.rebuild) { + container.cache.clear(); + MUList.build(); } - MUJS.unsaved = false; - MUJS.rebuild = false; + container.unsaved = false; + container.rebuild = false; } } else if (cmd === 'reset') { - // cfg = defcfg; - MUJS.unsaved = true; - MUJS.rebuild = true; + sendMessage({ type: 'reset' }); + cfg = DEFAULT_CONFIG; + container.unsaved = true; + container.rebuild = true; rebuildCfg(); } else if (cmd === 'settings') { - if (MUJS.unsaved) { - MUJS.showError('Unsaved changes'); + if (container.unsaved) { + showError('Unsaved changes'); } - tab.create('mujs:settings'); - MUJS.rebuild = false; + Tabs.create('mujs:settings'); + container.rebuild = false; } else if (cmd === 'new-tab') { - tab.create(); + Tabs.create(); } else if (cmd === 'switch-tab') { - tab.active(target); + Tabs.active(target); } else if (cmd === 'close-tab' && target.parentElement) { - tab.close(target.parentElement); + Tabs.close(target.parentElement); } else if (cmd === 'download-userjs') { - if (!MUJS.userjsCache.has(+dataset.userjs)) { + if (!container.userjsCache.has(+dataset.userjs)) { return; } - const dataUserJS = MUJS.userjsCache.get(+dataset.userjs); - const txt = await reqCode(dataUserJS); + const dataUserJS = container.userjsCache.get(+dataset.userjs); + let installCode = dataUserJS.code_url; + if (!prmpt && dataUserJS.code_url.endsWith('.user.css')) { + container.makePrompt('Download as UserStyle?', dataset); + return; + } else if (prmpt !== prmptChoice) { + installCode = dataUserJS.code_url.replace(/\.user\.css$/, '.user.js'); + } + const r = await dataUserJS._mujs.code.request(false, installCode); + const txt = r.data; if (typeof txt !== 'string') { return; } + const userjsName = dataset.userjsName ?? dataset.userjs; + const userjsExt = prmpt !== prmptChoice ? '.user.js' : '.user.css'; const makeUserJS = new Blob([txt], { type: 'text/plain' }); const dlBtn = make('a', 'mujs_Downloader'); dlBtn.href = URL.createObjectURL(makeUserJS); - dlBtn.download = `${dataset.userjsName ?? dataset.userjs}.user.js`; + dlBtn.download = `${userjsName}${userjsExt}`; dlBtn.click(); URL.revokeObjectURL(dlBtn.href); dlBtn.remove(); - } else if (cmd === 'load-userjs') { - if (!MUJS.userjsCache.has(+dataset.userjs)) { + } else if (cmd === 'load-userjs' || cmd === 'load-header') { + if (!container.userjsCache.has(+dataset.userjs)) { return; } const codeArea = qs('textarea', target.parentElement.parentElement); - if (!isEmpty(codeArea.value)) { + if (!isEmpty(codeArea.value) && cmd === codeArea.dataset.load) { dom.cl.toggle(codeArea, 'hidden'); return; } - const dataUserJS = MUJS.userjsCache.get(+dataset.userjs); - const txt = await reqCode(dataUserJS); - if (typeof txt !== 'string') { + codeArea.dataset.load = cmd; + const dataUserJS = container.userjsCache.get(+dataset.userjs); + const code_obj = await dataUserJS._mujs.code.request(); + if (typeof code_obj.data_code_block !== 'string') { + codeArea.value = 'An error occured'; return; } - codeArea.value = txt; + codeArea.value = cmd === 'load-userjs' ? code_obj.data_code_block : code_obj.data_meta_block; dom.cl.remove(codeArea, 'hidden'); - - const apTo = (name, elem) => { - if (isEmpty(dataUserJS[name])) { - const el = make('mujs-a', '', { - textContent: i18n$('listing_none') + for (const e of qsA('mujs-column[data-el="matches"]', target.parentElement.parentElement)) { + applyTo(dataUserJS, e.dataset.type, qs('.mujs-grants', e), e); + } + } else if (cmd === 'load-page') { + if (!container.userjsCache.has(+dataset.userjs)) { + return; + } + let pageArea = qs('mujs-page', target.parentElement.parentElement); + if (!pageArea) { + pageArea = make('mujs-page'); + target.parentElement.parentElement.append(pageArea); + const dataUserJS = container.userjsCache.get(+dataset.userjs); + const engine = dataUserJS._mujs.info.engine; + let pageURL; + if (engine.name.includes('fork')) { + const current = navigator.language.split('-')[0] ?? 'en'; + pageURL = dataUserJS.url.replace( + /\/scripts/, + `/${/^(zh|fr|es)/.test(current) ? navigator.language : current}/scripts` + ); + } else if (engine.name.includes('github')) { + const page_url = await Network.req(dataUserJS.page_url, 'GET', 'json', { + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${engine.token}`, + 'X-GitHub-Api-Version': '2022-11-28' + } + }).catch(() => { + return {}; }); - elem.append(el); - if (name === 'antifeatures') { - dom.cl.add(elem, 'hidden'); + if (!page_url.download_url) { + return; } + const page = await Network.req(page_url.download_url, 'GET', 'text'); + const shadow = pageArea.attachShadow({ mode: 'closed' }); + const div = make('div', { + innerHTML: page + }); + shadow.append(div); + return; } else { - for (const c of dataUserJS[name]) { - if (isObj(c)) { - const el = make('mujs-a', '', { - textContent: c.text - }); - if (c.domain) { - el.dataset.command = 'open-tab'; - el.dataset.webpage = `https://${c.text}`; - } - elem.append(el); - } else { - const el = make('mujs-a', '', { - textContent: c - }); - elem.append(el); + pageURL = dataUserJS.url; + } + if (!pageURL) { + return; + } + const page = await Network.req(pageURL, 'GET', 'document'); + const getContent = () => { + let content = 'An error occured'; + const h = new URL(dataUserJS.url); + const root = qs('.user-content', page.documentElement); + for (const e of qsA('[href]', root)) { + e.target = '_blank'; + e.style = 'pointer-events: auto;'; + if (e.href.startsWith('/')) { + e.href = `${h.origin}${e.href}`; } } - if (name === 'antifeatures') { - dom.cl.remove(elem, 'hidden'); + for (const e of qsA('img[src]', root)) { + e.style = + 'max-width: 25em; max-height: 25em; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;'; } - } - }; - const matchElem = qs( - '[data-type="match-urls"] > .mujs-grants', - target.parentElement.parentElement - ); - const grantElem = qs( - '[data-type="grants"] > .mujs-grants', - target.parentElement.parentElement - ); - const afElem = qs( - '[data-type="antifeatures"] > .mujs-grants', - target.parentElement.parentElement - ); - const sizeElem = qs('[data-type="size"] > .mujs-grants', target.parentElement.parentElement); - dom.prop([matchElem, grantElem, afElem, sizeElem], 'innerHTML', ''); - apTo('code_match', matchElem); - apTo('code_grant', grantElem); - apTo('antifeatures', afElem); - apTo('code_size', sizeElem); + if (root) { + content = root.innerHTML; + } else { + content = 'No additional info available'; + } + return content; + }; + const shadow = pageArea.attachShadow({ mode: 'closed' }); + const div = make('div', { + style: 'pointer-events: none;', + innerHTML: getContent() + }); + shadow.append(div); + return; + } + if (!dom.cl.has(pageArea, 'hidden')) { + dom.cl.add(pageArea, 'hidden'); + return; + } + dom.cl.remove(pageArea, 'hidden'); } else if (/export-/.test(cmd)) { const str = JSON.stringify(cmd === 'export-cfg' ? cfg : cfg.theme, null, ' '); const bytes = new TextEncoder().encode(str); @@ -936,29 +1335,28 @@ ael(main, 'click', async (evt) => { if (result.blacklist) { log(`Imported config: { ${file.name} }`, result); cfg = result; - MUJS.unsaved = true; - MUJS.rebuild = true; + container.unsaved = true; + container.rebuild = true; rebuildCfg(); - MUJS.save(); - // sleazyRedirect(); - MUJS.cache.clear(); - buildlist(); - MUJS.unsaved = false; - MUJS.rebuild = false; + container.save(); + container.cache.clear(); + MUList.build(); + container.unsaved = false; + container.rebuild = false; } else { log(`Imported theme: { ${file.name} }`, result); cfg.theme = result; - renderTheme(cfg.theme); + container.renderTheme(cfg.theme); } inpJSON.remove(); }; reader.onerror = () => { - MUJS.showError(reader.error); + showError(reader.error); inpJSON.remove(); }; }); } catch (ex) { - MUJS.showError(ex); + showError(ex); inpJSON.remove(); } } @@ -967,7 +1365,7 @@ ael(main, 'click', async (evt) => { inpJSON.click(); } } catch (ex) { - MUJS.showError(ex); + showError(ex); } }); ael(main, 'auxclick', (evt) => { @@ -982,61 +1380,179 @@ ael(main, 'auxclick', (evt) => { const dataset = target.dataset; const cmd = dataset.command; if (cmd === 'switch-tab' || cmd === 'close-tab') { - tab.close(target); + Tabs.close(target); } else if (cmd === 'new-tab') { - tab.create(); + Tabs.create(); } }); -renderTheme(cfg.theme); -const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent; -const comparer = (idx, asc) => (a, b) => - ((v1, v2) => - v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2))( - getCellValue(asc ? a : b, idx), - getCellValue(asc ? b : a, idx) - ); -for (const th of tabhead.rows[0].cells) { - if (dom.text(th) === i18n$('install')) continue; - dom.cl.add(th, 'mujs-pointer'); - ael(th, 'click', () => { - /** [Stack Overflow Reference](https://stackoverflow.com/questions/14267781/sorting-html-table-with-javascript/53880407#53880407) */ - Array.from(tabbody.querySelectorAll('tr')) - .sort(comparer(Array.from(th.parentNode.children).indexOf(th), (this.asc = !this.asc))) - .forEach((tr) => tabbody.appendChild(tr)); - }); -} +ael(main, 'updateditem', (evt) => { + /** + * @type {import("../typings/types.d.ts").GSForkQuery} + */ + const ujs = evt.detail; + if (!ujs._mujs) return; + for (const elem of qsA('[data-name]', ujs._mujs.root)) { + const name = elem.dataset.name; + if (name === 'code') { + if (ujs._mujs.code.data_code_block) { + if (cfg.preview.code && !cfg.preview.metadata) { + elem.value = ujs._mujs.code.data_code_block; + } else if (cfg.preview.metadata && !cfg.preview.code) { + elem.value = ujs._mujs.code.data_meta_block; + } else { + elem.value = `${ujs._mujs.code.META_START_COMMENT}${ujs._mujs.code.data_meta_block}${ujs._mujs.code.META_END_COMMENT}${ujs._mujs.code.data_code_block}`; + } + } + continue; + } + if (!ujs[name]) continue; + if (name === 'license') { + dom.attr(elem, 'title', ujs.license ?? i18n$('no_license')); + dom.text(elem, `${i18n$('license')}: ${ujs.license ?? i18n$('no_license')}`); + } else if (name === 'code_updated_at') { + dom.text(elem, language.toDate(ujs.code_updated_at)); + elem.dataset.value = new Date(ujs.code_updated_at).toISOString(); + } else if (name === 'created_date') { + dom.text(elem, `${i18n$('created_date')}: ${language.toDate(ujs.created_at)}`); + elem.dataset.value = new Date(ujs.created_at).toISOString(); + } else if (name === 'total_installs') { + dom.text(elem, `${i18n$('total_installs')}: ${language.toNumber(ujs.total_installs)}`); + } else { + dom.text(elem, ujs[name]); + } + } + if (ujs._mujs.code.data_code_block) { + for (const e of qsA('mujs-column[data-el="matches"]', ujs._mujs.root)) { + applyTo(ujs, e.dataset.type, qs('.mujs-grants', e), e); + } + } + if (container.userjsCache.has(ujs.id)) container.userjsCache.set(ujs.id, ujs); +}); ael(urlBar, 'input', (evt) => { evt.preventDefault(); if (urlBar.placeholder === i18n$('newTab')) { return; } + /** + * @type { string } + */ const val = evt.target.value; + const section = qsA('mujs-section[data-name]', cfgpage); if (isEmpty(val)) { - dom.cl.remove(qsA('tr[data-engine]', tabbody), 'hidden'); + dom.cl.remove(container.toElem(), 'hidden'); + dom.cl.remove(section, 'hidden'); return; } - const reg = new RegExp(val, 'gi'); const finds = new Set(); - const userjsCache = MUJS.userjsCache; - for (const [k, v] of userjsCache) { - const elem = qs(`tr[data-script-id="${k}"]`, tabbody); - if (!elem) { - continue; + if (!dom.cl.has(cfgpage, 'hidden')) { + const reg = new RegExp(val, 'gi'); + for (const elem of section) { + if (!isElem(elem)) { + continue; + } + if (finds.has(elem)) { + continue; + } + if (dom.text(elem).match(reg)) { + finds.add(elem); + } } - if (finds.has(elem)) { - continue; + dom.cl.add(section, 'hidden'); + dom.cl.remove([...finds], 'hidden'); + return; + } + const cacheValues = Array.from(container).filter(({ _mujs }) => { + return !finds.has(_mujs.root); + }); + /** + * @param {RegExpMatchArray} regExp + * @param {keyof import("../typings/types.d.ts").GSForkQuery} key + */ + const ezQuery = (regExp, key) => { + const q_value = val.replace(regExp, ''); + const reg = new RegExp(q_value, 'gi'); + for (const v of cacheValues) { + let k = v[key]; + if (typeof k === 'number') { + k = `${v[key]}`; + } + if (k && k.match(reg)) { + finds.add(v._mujs.root); + } + } + }; + if (val.match(/^(code_url|url):/)) { + ezQuery(/^(code_url|url):/, 'code_url'); + } else if (val.match(/^(author|users?):/)) { + const parts = /^[\w_]+:(.+)/.exec(val); + if (parts) { + const reg = new RegExp(parts[1], 'gi'); + for (const v of cacheValues.filter((v) => !isEmpty(v.users))) { + for (const user of v.users) { + for (const value of Object.values(user)) { + if (typeof value === 'string' && value.match(reg)) { + finds.add(v._mujs.root); + } else if (typeof value === 'number' && `${value}`.match(reg)) { + finds.add(v._mujs.root); + } + } + } + } } - if (v.name && v.name.match(reg)) { - finds.add(elem); + } else if (val.match(/^(locale|i18n):/)) { + ezQuery(/^(locale|i18n):/, 'locale'); + } else if (val.match(/^id:/)) { + ezQuery(/^id:/, 'id'); + } else if (val.match(/^license:/)) { + ezQuery(/^license:/, 'license'); + } else if (val.match(/^name:/)) { + ezQuery(/^name:/, 'name'); + } else if (val.match(/^description:/)) { + ezQuery(/^description:/, 'description'); + } else if (val.match(/^(search_engine|engine):/)) { + const parts = /^[\w_]+:(\w+)/.exec(val); + if (parts) { + const reg = new RegExp(parts[1], 'gi'); + for (const { _mujs } of cacheValues) { + if (!_mujs.info.engine.name.match(reg)) { + continue; + } + finds.add(_mujs.root); + } } - if (v.description && v.description.match(reg)) { - finds.add(elem); + } else if (val.match(/^filter:/)) { + const parts = /^\w+:(.+)/.exec(val); + if (parts) { + const bsFilter = loadFilters(cfg); + const filterType = bsFilter.get(parts[1].trim().toLocaleLowerCase()); + if (filterType) { + const { reg } = filterType; + for (const { name, users, _mujs } of cacheValues) { + if ([{ name }, ...users].find((o) => o.name.match(reg))) { + continue; + } + finds.add(_mujs.root); + } + } } - if (v.code_data) { - const meta = parse_meta(v.code_data); - for (const key of Object.keys(meta)) { - if (/name|desc/i.test(key) && key.match(reg)) { - finds.add(elem); + } else if (val.match(/^recommend:/)) { + for (const { url, id, users, _mujs } of cacheValues) { + if ( + users.find((u) => u.id === authorID) || + goodUserJS.includes(url) || + goodUserJS.includes(id) + ) { + finds.add(_mujs.root); + } + } + } else { + const reg = new RegExp(val, 'gi'); + for (const v of cacheValues) { + if (v.name && v.name.match(reg)) finds.add(v._mujs.root); + if (v.description && v.description.match(reg)) finds.add(v._mujs.root); + if (v._mujs.code.data_meta) { + for (const key of Object.keys(v._mujs.code.data_meta)) { + if (/name|desc/i.test(key) && key.match(reg)) finds.add(v._mujs.root); } } } @@ -1047,356 +1563,543 @@ ael(urlBar, 'input', (evt) => { ael(urlBar, 'change', (evt) => { evt.preventDefault(); const val = evt.target.value; - if (urlBar.placeholder === i18n$('newTab') && qs('mujs-tab.active', toolbar)) { - const tabElem = qs('mujs-tab.active', toolbar); - const tabHost = qs('mujs-host', tabElem); - if (val.startsWith('mujs:')) { - tab.close(tabElem); - if (tab.hasTab(val)) { - tab.active(tab.Tab.get(val)); + const tabElem = Tabs.getActive(); + if (urlBar.placeholder === i18n$('newTab') && tabElem) { + const tabHost = tabElem.firstElementChild; + const host = formatURL(normalizedHostname(val)); + if (Tabs.protoReg.test(val)) { + const createdTab = Tabs.getTab(val); + Tabs.close(tabElem); + if (createdTab) { + Tabs.active(createdTab); } else { - tab.create(val); + Tabs.create(val); } - return; - } else if (val === '*') { - tabElem.dataset.host = val; + evt.target.placeholder = i18n$('search_placeholder'); + evt.target.value = ''; + } else if (host === 'all-urls') { + tabElem.dataset.host = '*'; tabHost.title = ''; tabHost.textContent = ''; - buildlist(val); - return; - } - const value = getHost(val); - if (MUJS.checkBlacklist(value)) { - MUJS.showError(`Host blacklisted "${value}"`); - return; + MUList.host = '*'; + MUList.build(); + } else if (container.checkBlacklist(host)) { + showError(`Blacklisted "${host}"`); + } else { + tabElem.dataset.host = host; + tabHost.title = host; + tabHost.textContent = host; + MUList.host = host; + MUList.build(); } - tabElem.dataset.host = value; - tabHost.title = value; - tabHost.textContent = value; - buildlist(value); - return; } }); +// #endregion -async function buildlist(host = undefined) { - try { - if (isEmpty(host)) { - host = MUJS.host; - } - if (MUJS.checkBlacklist(host)) { - return; - } - if (!qs(`mujs-tab[data-host="${host}"]`)) { - tab.create(host); - } - MUJS.refresh(); - webext.runtime.sendMessage( - { - location: host - }, - (data) => { - if (isEmpty(data)) { - return; - } - for (const tabData of data) { - const { engine, host } = tabData; - if (!qs(`mujs-tab[data-host="${host}"]`)) { - tab.create(host); - } - for (const ujs of tabData.data) { - createjs(ujs, engine.name); - } - MUJS.updateCounter(tabData.data.length, engine); - } - urlBar.placeholder = i18n$('search_placeholder'); - urlBar.value = ''; - } - ); - } catch (ex) { - err(ex); - } -} +Tabs.custom = (host) => { + MUList.host = host; + MUList.build(); +}; -//#region Make Config +// #region Make Config const makecfg = () => { - const exBtn = make('mu-js', 'mujs-sty-flex'); - const exportCFG = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_config'), - dataset: { - command: 'export-cfg' - } - }); - const importCFG = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_config'), - dataset: { - command: 'import-cfg' - } - }); - const exportTheme = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_theme'), + const cbtn = make('mu-js', 'mujs-sty-flex'); + const savebtn = make('mujs-btn', 'save', { + textContent: i18n$('save'), dataset: { - command: 'export-theme' - } + command: 'save' + }, + disabled: false }); - const importTheme = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_theme'), + const resetbtn = make('mujs-btn', 'reset', { + textContent: i18n$('reset'), dataset: { - command: 'import-theme' + command: 'reset' } }); - exBtn.append(importCFG, importTheme, exportCFG, exportTheme); - cfgpage.append(exBtn); + cbtn.append(resetbtn, savebtn); - const makerow = (desc, type = null, nm, attrs = {}) => { - desc = desc ?? i18n$('no_license'); - nm = nm ?? i18n$('no_license'); - const sec = make('mujs-section', 'mujs-cfg-section', { - style: nm === 'cache' ? 'display: none;' : '' + const makesection = (name, tag) => { + tag = tag ?? i18n$('no_license'); + name = name ?? i18n$('no_license'); + const sec = make('mujs-section', { + dataset: { + name: tag + } + }); + const lb = make('label', { + dataset: { + command: tag + } + }); + const divDesc = make('mu-js', { + textContent: name }); - const lb = make('label'); - const divDesc = make('mu-js', 'mujs-cfg-desc', { - textContent: desc + ael(sec, 'click', (evt) => { + /** @type { HTMLElement } */ + const target = evt.target.closest('[data-command]'); + if (!target) { + return; + } + const cmd = target.dataset.command; + if (cmd === tag) { + const a = qsA(`[data-${tag}]`, sec); + if (dom.cl.has(a, 'hidden')) { + dom.cl.remove(a, 'hidden'); + } else { + dom.cl.add(a, 'hidden'); + } + } }); + lb.append(divDesc); sec.append(lb); cfgpage.append(sec); - if (isNull(type)) { + return sec; + }; + const sections = { + general: makesection('General', 'general'), + load: makesection('Automation', 'load'), + list: makesection('List', 'list'), + filters: makesection('List Filters', 'filters'), + blacklist: makesection('Blacklist (WIP)', 'blacklist'), + engine: makesection('Search Engines', 'engine'), + theme: makesection('Theme Colors', 'theme'), + exp: makesection('Import / Export', 'exp') + }; + const makeRow = (text, value, type = 'checkbox', tag = 'general', attrs = {}) => { + const lb = make('label', 'sub-section hidden', { + textContent: text, + dataset: { + [tag]: text + } + }); + cfgMap.set(text, value); + if (type === 'select') { + const inp = make('select', { + dataset: { + [tag]: text + }, + ...attrs + }); + for (const selV of Object.keys(template)) { + if (selV === 'deleted' || selV === 'users') continue; + const o = make('option', { + value: selV, + textContent: selV + }); + inp.append(o); + } + inp.value = cfg[value]; + lb.append(inp); + if (sections[tag]) { + sections[tag].append(lb); + } return lb; } - const inp = make('input', 'mujs-cfg-input', { + const inp = make('input', { type, dataset: { - name: nm + [tag]: text }, ...attrs }); - if (!cfgMap.has(nm)) { - cfgMap.set(nm, inp); + + if (tag === 'engine') { + inp.dataset.name = value; + } + + if (sections[tag]) { + sections[tag].append(lb); } + if (type === 'checkbox') { const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', '', { + const la = make('label', { onclick() { inp.dispatchEvent(new MouseEvent('click')); } }); inlab.append(inp, la); lb.append(inlab); - if (nm.includes('-')) { - return inp; - } - if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { - for (const i of cfg.engines) { - if (i.name !== nm) continue; - inp.checked = i.enabled; - inp.dataset.engine = i.name; + + const nm = /^(\w+)-(.+)/.exec(value); + if (nm) { + if (nm[1] === 'filters') { + inp.checked = cfg[nm[1]][nm[2]].enabled; + } else { + inp.checked = cfg[nm[1]][nm[2]]; + } + } else { + inp.checked = cfg[value]; + } + ael(inp, 'change', (evt) => { + container.unsaved = true; + if (/filterlang/i.test(value)) { + container.rebuild = true; + } + if (nm) { + if (nm[1] === 'filters') { + cfg[nm[1]][nm[2]].enabled = evt.target.checked; + } else { + cfg[nm[1]][nm[2]] = evt.target.checked; + } + } else { + cfg[value] = evt.target.checked; + } + sendMessage({ + type: 'save', + cfg + }); + }); + + if (tag === 'engine') { + const engine = cfg.engines.find((engine) => engine.name === value); + if (engine) { + inp.checked = engine.enabled; + inp.dataset.engine = engine.name; ael(inp, 'change', (evt) => { - // MUJS.unsaved = true; - // MUJS.rebuild = true; - i.enabled = evt.target.checked; - hermes.send('Save', { - prop: 'engines', - value: cfg.engines + container.unsaved = true; + container.rebuild = true; + engine.enabled = evt.target.checked; + sendMessage({ + type: 'engine', + engine }); }); + + if (engine.query) { + const d = DEFAULT_CONFIG.engines.find((e) => e.name === engine.name); + const urlInp = make('input', { + type: 'text', + defaultValue: '', + value: decodeURIComponent(engine.query) ?? '', + placeholder: decodeURIComponent(d.query) ?? '', + dataset: { + name: nm, + engine: engine.name + }, + onchange(evt) { + container.unsaved = true; + container.rebuild = true; + try { + engine.query = encodeURIComponent(new URL(evt.target.value).toString()); + sendMessage({ + type: 'engine', + engine + }); + } catch (ex) { + err(ex); + } + } + }); + lb.append(urlInp); + } + if (engine.name === 'github') { + const ghToken = make('input', { + type: 'text', + defaultValue: '', + value: engine.token ?? '', + placeholder: 'Paste Access Token', + dataset: { + engine: 'github-token' + }, + onchange(evt) { + container.unsaved = true; + container.rebuild = true; + engine.token = evt.target.value; + sendMessage({ + type: 'engine', + engine + }); + } + }); + lb.append(ghToken); + cfgMap.set('github-token', ghToken); + } } - } else { - inp.checked = cfg[nm]; - ael(inp, 'change', (evt) => { - // MUJS.unsaved = true; - // if (/filterlang/i.test(nm)) { - // MUJS.rebuild = true; - // } - cfg[nm] = evt.target.checked; - hermes.send('Save', { - prop: nm, - value: cfg[nm] - }); - }); } } else { + if (type === 'text') { + inp.defaultValue = ''; + inp.value = value ?? ''; + inp.placeholder = value ?? ''; + } + lb.append(inp); } - return inp; + + return lb; }; - makerow(i18n$('redirect'), 'checkbox', 'sleazyredirect'); - makerow(i18n$('filter'), 'checkbox', 'filterlang'); - makerow(i18n$('preview_code'), 'checkbox', 'codePreview'); - for (const inp of [ - makerow('Recommend author', 'checkbox', 'recommend-author'), - makerow('Recommend scripts', 'checkbox', 'recommend-others') - ]) { - const nm = inp.dataset.name === 'recommend-author' ? 'author' : 'others'; - inp.checked = cfg.recommend[nm]; - ael(inp, 'change', (evt) => { - // MUJS.unsaved = true; - cfg.recommend[nm] = evt.target.checked; - hermes.send('Save', { - prop: 'recommend', - value: cfg.recommend - }); + makeRow(i18n$('redirect'), 'sleazyredirect'); + + makeRow(i18n$('auto_fetch'), 'autofetch', 'checkbox', 'load'); + makeRow('Clear on Tab close', 'clearTabCache', 'checkbox', 'load'); + + makeRow('Default Sort', 'autoSort', 'select', 'list'); + makeRow(i18n$('filter'), 'filterlang', 'checkbox', 'list'); + makeRow(i18n$('preview_code'), 'preview-code', 'checkbox', 'list'); + makeRow('Preview Metadata', 'preview-metadata', 'checkbox', 'list'); + makeRow('Recommend author', 'recommend-author', 'checkbox', 'list'); + makeRow('Recommend scripts', 'recommend-others', 'checkbox', 'list'); + + for (const [k, v] of Object.entries(cfg.filters)) { + makeRow(v.name, `filters-${k}`, 'checkbox', 'filters'); + } + + makeRow('Greasy Fork', 'greasyfork', 'checkbox', 'engine'); + makeRow('Sleazy Fork', 'sleazyfork', 'checkbox', 'engine'); + // makeRow('Open UserJS', 'openuserjs', 'checkbox', 'engine'); + makeRow('GitHub API', 'github', 'checkbox', 'engine'); + + for (const [k, v] of Object.entries(cfg.theme)) { + const lb = make('label', 'hidden', { + textContent: k, + dataset: { + theme: k + } }); + const inp = make('input', { + type: 'text', + defaultValue: '', + value: v ?? '', + placeholder: v ?? '', + dataset: { + theme: k + }, + onchange(evt) { + let isvalid = true; + try { + const val = evt.target.value; + const sty = container.root.style; + const str = `--mujs-${k}`; + const prop = sty.getPropertyValue(str); + if (isEmpty(val)) { + cfg.theme[k] = DEFAULT_CONFIG.theme[k]; + sty.removeProperty(str); + return; + } + if (prop === val) { + return; + } + sty.removeProperty(str); + sty.setProperty(str, val); + cfg.theme[k] = val; + sendMessage({ + type: 'save', + cfg + }); + } catch (ex) { + err(ex); + isvalid = false; + } finally { + if (isvalid) { + dom.cl.remove(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', false); + } else { + dom.cl.add(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', true); + } + } + } + }); + cfgMap.set(k, inp); + lb.append(inp); + sections.theme.append(lb); } - makerow('Greasy Fork', 'checkbox', 'greasyfork'); - makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); - makerow('Open UserJS', 'checkbox', 'openuserjs'); - makerow('GitHub API', 'checkbox', 'github'); - const ghAPI = cfg.engines.find((c) => c.name === 'github'); - const ghToken = makerow('GitHub API (Token)', 'text', 'github', { - defaultValue: '', - value: ghAPI.token ?? '', - placeholder: 'Paste Access Token', - onchange(evt) { - MUJS.unsaved = true; - MUJS.rebuild = true; - ghAPI.token = evt.target.value; - hermes.send('Save', { - prop: 'engines', - value: cfg.engines - }); + const createList = (key, v = '', disabled = false, type = 'String') => { + let txt = key; + if (typeof key === 'string') { + if (key.startsWith('userjs-')) { + disabled = true; + const s = key.substring(7); + txt = `Built-in "${s}"`; + v = builtinList[s]; + } + } else { + if (!key.enabled) { + return; + } } - }); - ghToken.dataset.engine = 'github-token'; - cfgMap.set('github-token', ghToken); - const cbtn = make('mu-js', 'mujs-sty-flex'); - const savebtn = make('mujs-btn', 'save', { - textContent: i18n$('save'), - dataset: { - command: 'save' - }, - disabled: false - }); - const resetbtn = make('mujs-btn', 'reset', { - textContent: i18n$('reset'), - dataset: { - command: 'reset' + if (isRegExp(v)) { + v = v.toString(); + type = 'RegExp'; + } else { + v = JSON.stringify(v); + type = 'Object'; } - }); - const blacklist = make('textarea', '', { - dataset: { - name: 'blacklist' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.blacklist, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.blacklist = JSON.parse(evt.target.value); - isvalid = true; - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); - } + + const lb = make('label', 'hidden', { + textContent: txt, + dataset: { + blacklist: key } - } - }); - const theme = make('textarea', '', { - dataset: { - name: 'theme' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.theme, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.theme = JSON.parse(evt.target.value); - isvalid = true; - renderTheme(JSON.parse(evt.target.value)); - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); + }); + const inp = make('input', { + type: 'text', + defaultValue: '', + value: v ?? '', + placeholder: v ?? '', + dataset: { + blacklist: key + }, + onchange(evt) { + let isvalid = true; + try { + const val = evt.target.value; + if (isEmpty(val)) { + return; + } + isvalid = true; + } catch (ex) { + err(ex); + isvalid = false; + } finally { + if (isvalid) { + dom.cl.remove(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', false); + } else { + dom.cl.add(evt.target, 'mujs-invalid'); + dom.prop(savebtn, 'disabled', true); + } } } + }); + const selType = make('select', { + disabled, + dataset: { + blacklist: key + } + }); + if (disabled) { + inp.readOnly = true; + const o = make('option', { + value: type, + textContent: type + }); + selType.append(o); + } else { + for (const selV of ['String', 'RegExp', 'Object']) { + const o = make('option', { + value: selV, + textContent: selV + }); + selType.append(o); + } } - }); - cfgMap.set('blacklist', blacklist); - cfgMap.set('theme', theme); - cbtn.append(resetbtn, savebtn); - cfgpage.append(blacklist, theme, cbtn); -}; -//#endregion - -const locSearch = location.search; + selType.value = type; + lb.append(inp, selType); + sections.blacklist.append(lb); + }; + for (const key of cfg.blacklist) { + createList(key); + } -const p = hermes.getPort(); -p.onMessage.addListener((root = {}) => { - const m = root.msg; - if (root.channel === 'Config' && isEmpty(cfg)) { - cfg = m.cfg || cfg; - for (const engine of cfg.engines) { - MUJS.counters[engine.name] = 0; - if (!engine.enabled) { - continue; - } - const counter = make('count-frame', '', { + const transfers = { + export: { + cfg: make('mujs-btn', 'mujs-export sub-section hidden', { + textContent: i18n$('export_config'), dataset: { - counter: engine.name - }, - title: engine.url, - textContent: '0' - }); - qs('.counter-container').append(counter); + command: 'export-cfg', + exp: 'export-cfg' + } + }), + theme: make('mujs-btn', 'mujs-export sub-section hidden', { + textContent: i18n$('export_theme'), + dataset: { + command: 'export-theme', + exp: 'export-theme' + } + }) + }, + import: { + cfg: make('mujs-btn', 'mujs-import sub-section hidden', { + textContent: i18n$('import_config'), + dataset: { + command: 'import-cfg', + exp: 'import-cfg' + } + }), + theme: make('mujs-btn', 'mujs-import sub-section hidden', { + textContent: i18n$('import_theme'), + dataset: { + command: 'import-theme', + exp: 'import-theme' + } + }) } - makecfg(); - if (/mujs=/.test(locSearch)) { - if (/settings/.test(locSearch)) { - tab.create('mujs:settings'); - } + }; + for (const value of Object.values(transfers)) { + for (const v of Object.values(value)) { + sections.exp.append(v); } } -}); -function primaryFN(data) { + cfgpage.append(cbtn); +}; +// #endregion + +async function init() { + const [tab] = await webext.tabs.query({ + active: true, + currentWindow: true + }); + const data = []; + if (tab instanceof Object === false) { + return true; + } + Object.assign(currentTab, tab); + let url; try { - if (isEmpty(data)) { - tab.create(); - return; - } - for (const tabData of data) { - const { engine, host } = tabData; - if (MUJS.checkBlacklist(host)) { - continue; - } - if (!qs(`mujs-tab[data-host="${host}"]`)) { - tab.create(host); - if (tabData.link) { - MUJS.setHost(tabData.link); - } + url = new URL(currentTab.url); + tabURL.href = url.href || ''; + } catch (ex) { + err(ex); + } + + if (url !== undefined) { + const hostname = formatURL(normalizedHostname(tabURL.hostname)); + const response = await sendMessage({ + init: true, + type: 'getData', + currentTab, + hostname + }); + if (response instanceof Object) { + Object.assign(cfg, response.cfg ?? DEFAULT_CONFIG); + if (Array.isArray(response.data)) { + data.push(...response.data); } - if (tabData.data) { - for (const ujs of tabData.data) { - createjs(ujs, engine.name); + container.initFn(); + makecfg(); + MUList.cfg = cfg; + MUList.engines = cfg.engines; + if (params.has('mujs', 'settings')) { + Tabs.create('mujs:settings'); + } else if (params.has('host')) { + const host = params.get('host'); + Tabs.create(host); + if (!host.startsWith(Tabs.protocal)) { + MUList.host = host; + MUList.build(data); } - MUJS.updateCounter(tabData.data.length, engine); + } else if (!url.origin.startsWith('https://')) { + Tabs.create(); + } else { + Tabs.create(hostname); + MUList.host = hostname; + MUList.build(data); } } - urlBar.placeholder = i18n$('search_placeholder'); - urlBar.value = ''; - } catch (ex) { - err(ex); } } -if (!/mujs=/.test(locSearch)) { - webext.runtime.sendMessage({}, primaryFN); +async function tryInit() { + try { + await init(); + } catch { + setTimeout(tryInit, 100); + } } + +tryInit(); diff --git a/src/js/punycode.js b/src/js/punycode.js new file mode 100644 index 0000000..a7f990d --- /dev/null +++ b/src/js/punycode.js @@ -0,0 +1,493 @@ +/*! https://mths.be/punycode v1.3.2 by @mathias */ +export default (function() { + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * http://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + return punycode; +})(); diff --git a/src/js/querySelector.js b/src/js/querySelector.js index a2e5376..3a0dc90 100644 --- a/src/js/querySelector.js +++ b/src/js/querySelector.js @@ -57,7 +57,7 @@ const SafeAnimationFrame = class { } }; /** - * @type { import("../typings/types").isElem } + * @type { import("../typings/types.d.ts").isElem } */ const isElem = (obj) => { /** @type { string } */ @@ -65,7 +65,7 @@ const isElem = (obj) => { return s.includes('Element'); }; /** - * @type { import("../typings/types").normalizeTarget } + * @type { import("../typings/types.d.ts").normalizeTarget } */ const normalizeTarget = (target, toQuery = true, root) => { if (Object.is(target, null) || Object.is(target, undefined)) { @@ -320,7 +320,7 @@ dom.cl = class { /******************************************************************************/ /** - * @type { import("../typings/types").qsA } + * @type { import("../typings/types.d.ts").qsA } */ const qsA = (selectors, root) => { try { @@ -331,7 +331,7 @@ const qsA = (selectors, root) => { return []; }; /** - * @type { import("../typings/types").qs } + * @type { import("../typings/types.d.ts").qs } */ const qs = (selector, root) => { try { @@ -343,7 +343,7 @@ const qs = (selector, root) => { }; /** - * @type { import("../typings/WebExt").query } + * @type { import("../typings/WebExt.d.ts").query } */ const query = async (selector, root) => { let el = null; diff --git a/src/js/request-code.js b/src/js/request-code.js index e4fac3e..0dc3a92 100644 --- a/src/js/request-code.js +++ b/src/js/request-code.js @@ -1,11 +1,9 @@ 'use strict'; +import { err } from './logger.js'; import Network from './network.js'; -import { intersect, isNull, isEmpty, normalizeTarget } from './util.js'; -import { language } from './language.js'; +import { isNull, isBlank, isEmpty, union } from './util.js'; -const META_START_COMMENT = '// ==UserScript=='; -const META_END_COMMENT = '// ==/UserScript=='; const TLD_EXPANSION = ['com', 'net', 'org', 'de', 'co.uk']; const APPLIES_TO_ALL_PATTERNS = [ 'http://*', @@ -19,237 +17,303 @@ const APPLIES_TO_ALL_PATTERNS = [ '*://*/*', 'http*' ]; -/** - * @param { string } code - */ -const get_meta_block = (code) => { - if (isEmpty(code)) { - return null; - } - const start_block = code.indexOf(META_START_COMMENT); - if (isNull(start_block)) { - return null; - } - const end_block = code.indexOf(META_END_COMMENT, start_block); - if (isNull(end_block)) { - return null; - } - return code.substring(start_block + META_START_COMMENT.length, end_block); -}; -/** - * @param { string } code - */ -const parse_meta = (code) => { - if (isEmpty(code)) { - return null; - } - const meta = {}; - const meta_block = get_meta_block(code); - const meta_block_map = new Map(); - for (const meta_line of meta_block.split('\n')) { - const meta_match = meta_line.match(/\/\/\s+@([a-zA-Z:-]+)\s+(.*)/); - if (isNull(meta_match)) { - continue; - } - const key = meta_match[1].trim(); - const value = meta_match[2].trim(); - if (!meta_block_map.has(key)) { - meta_block_map.set(key, []); - } - const meta_map = meta_block_map.get(key); - meta_map.push(value); - meta_block_map.set(key, meta_map); +class ParseUserJS { + /** + * @type { string } + */ + code; + /** + * @type { string } + */ + data_meta_block; + /** + * @type { string } + */ + data_code_block; + /** + * @type { { [meta: string]: string | string[] | { [resource: string]: string } } } + */ + data_meta; + /** + * @type { {text: string;domain: boolean;tld_extra: boolean}[] } + */ + data_names; + constructor(code, isUserCSS) { + this.META_START_COMMENT = isUserCSS ? '/* ==UserStyle==' : '// ==UserScript=='; + this.META_END_COMMENT = isUserCSS ? '==/UserStyle== */' : '// ==/UserScript=='; + if (code) { + this.code = code; + this.get_meta_block(); + this.get_code_block(); + this.parse_meta(); + this.calculate_applies_to_names(); + } } - for (const [key, value] of meta_block_map) { - if (value.length > 1) { - meta[key] = value; - } else { - meta[key] = value[0]; + get_meta_block() { + if (isEmpty(this.code)) { + return null; + } + if (this.data_meta_block) { + return this.data_meta_block; + } + const start_block = this.code.indexOf(this.META_START_COMMENT); + if (isNull(start_block)) { + return null; + } + const end_block = this.code.indexOf(this.META_END_COMMENT, start_block); + if (isNull(end_block)) { + return null; } + const meta_block = this.code.substring(start_block + this.META_START_COMMENT.length, end_block); + this.data_meta_block = meta_block; + return this.data_meta_block; } - return meta; -}; -/** - * @template { string } S - * @param { S } code - * @returns { S[] } - */ -const calculate_applies_to_names = (code) => { - if (isEmpty(code)) { - return null; + get_code_block() { + if (isEmpty(this.code)) { + return null; + } + if (this.data_code_block) { + return this.data_code_block; + } + const start_block = this.code.indexOf(this.META_START_COMMENT); + if (isNull(start_block)) { + return null; + } + const end_block = this.code.indexOf(this.META_END_COMMENT, start_block); + if (isNull(end_block)) { + return null; + } + const code_block = this.code.substring( + end_block + this.META_END_COMMENT.length, + this.code.length + ); + this.data_code_block = code_block + .split('\n') + .filter((l) => !isEmpty(l)) + .join('\n'); + return this.data_code_block; } - const meta = parse_meta(code); - let patterns = []; - for (const [k, v] of Object.entries(meta)) { - if (/include|match/.test(k)) { - if (Array.isArray(v)) { - patterns = patterns.concat(v); + parse_meta() { + if (isEmpty(this.code)) { + return null; + } + if (this.data_meta) { + return this.data_meta; + } + const meta = {}; + const meta_block_map = new Map(); + for (const meta_line of this.get_meta_block().split('\n')) { + const meta_match = /\/\/\s+@([a-zA-Z:-]+)\s+(.*)/.exec(meta_line); + if (!meta_match) { + continue; + } + const key = meta_match[1].trim(); + const value = meta_match[2].trim(); + if (!meta_block_map.has(key)) { + meta_block_map.set(key, []); + } + const meta_map = meta_block_map.get(key); + meta_map.push(value); + meta_block_map.set(key, meta_map); + } + for (const [key, value] of meta_block_map) { + if (value.length > 1) { + meta[key] = value; } else { - patterns = patterns.concat([v]); + meta[key] = value[0]; } } + this.data_meta = meta; + return this.data_meta; } - if (isEmpty(patterns)) { - return []; - } - if (intersect(patterns, APPLIES_TO_ALL_PATTERNS)) { - return []; - } - const name_set = new Set(); - const addObj = (obj) => { - if (name_set.has(obj)) { - return; - } - name_set.add(obj); - }; - for (let p of patterns) { - try { - const original_pattern = p; - let pre_wildcards = []; - if (p.match(/^\/(.*)\/$/)) { - pre_wildcards = [p]; - } else { - let m = p.match(/^\*(https?:.*)/i); - if (!isNull(m)) { - p = m[1]; - } - p = p - .replace(/^\*:/i, 'http:') - .replace(/^\*\/\//i, 'http://') - .replace(/^http\*:/i, 'http:') - .replace(/^(https?):([^/])/i, '$1://$2'); - m = p.match(/^([a-z]+:\/\/)\*\.?([a-z0-9-]+(?:.[a-z0-9-]+)+.*)/i); - if (!isNull(m)) { - p = m[1] + m[2]; - } - m = p.match(/^\*\.?([a-z0-9-]+\.[a-z0-9-]+.*)/i); - if (!isNull(m)) { - p = `http://${m[1]}`; + calculate_applies_to_names() { + if (isEmpty(this.code)) { + return null; + } + if (this.data_names) { + return this.data_names; + } + let patterns = []; + for (const [k, v] of Object.entries(this.parse_meta())) { + if (/include|match/i.test(k)) { + if (Array.isArray(v)) { + patterns = patterns.concat(v); + } else { + patterns = patterns.concat([v]); } - m = p.match(/^http\*(?:\/\/)?\.?((?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+.*)/i); - if (!isNull(m)) { - p = `http://${m[1]}`; + } + } + if (isEmpty(patterns)) { + return []; + } + if (this.intersect(patterns, APPLIES_TO_ALL_PATTERNS)) { + this.data_names = [ + { + domain: false, + text: 'All sites', + tld_extra: false } - m = p.match(/^([a-z]+:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)*\.))\*(.*)/); - if (!isNull(m)) { - if (m[2].match(/A([0-9]+\.){2,}z/)) { - p = `${m[1]}tld${m[3]}`; - pre_wildcards = [p.split('*')[0]]; + ]; + return this.data_names; + } + this.data_names = ParseUserJS.getNames(patterns); + return this.data_names; + } + intersect(a, ...arr) { + return !isBlank([...new Set(a)].filter((v) => arr.every((b) => b.includes(v)))); + } + static getNames(patterns = []) { + const name_map = new Map(); + const addObj = (obj) => { + if (name_map.has(obj.text)) { + return; + } + name_map.set(obj.text, obj); + }; + for (let p of patterns) { + try { + const original_pattern = p; + let pre_wildcards = []; + if (p.match(/^\/(.*)\/$/)) { + pre_wildcards = [p]; + } else { + let m = /^\*(https?:.*)/i.exec(p); + if (m) { + p = m[1]; + } + p = p + .replace(/^\*:/i, 'http:') + .replace(/^\*\/\//i, 'http://') + .replace(/^http\*:/i, 'http:') + .replace(/^(https?):([^/])/i, '$1://$2'); + m = /^([a-z]+:\/\/)\*\.?([a-z0-9-]+(?:.[a-z0-9-]+)+.*)/i.exec(p); + if (m) { + p = m[1] + m[2]; + } + m = /^\*\.?([a-z0-9-]+\.[a-z0-9-]+.*)/i.exec(p); + if (m) { + p = `http://${m[1]}`; + } + m = /^http\*(?:\/\/)?\.?((?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+.*)/i.exec(p); + if (m) { + p = `http://${m[1]}`; + } + m = /^([a-z]+:\/\/([a-z0-9-]+(?:\.[a-z0-9-]+)*\.))\*(.*)/.exec(p); + if (m) { + if (m[2].match(/A([0-9]+\.){2,}z/)) { + p = `${m[1]}tld${m[3]}`; + pre_wildcards = [p.split('*')[0]]; + } else { + pre_wildcards = [p]; + } } else { pre_wildcards = [p]; } - } else { - pre_wildcards = [p]; } - } - for (const pre_wildcard of pre_wildcards) { - try { - const uri = new URL(pre_wildcard); - if (isNull(uri.host)) { - addObj({ text: original_pattern, domain: false, tld_extra: false }); - } else if (!uri.host.includes('.') && uri.host.includes('*')) { - addObj({ text: original_pattern, domain: false, tld_extra: false }); - } else if (uri.host.endsWith('.tld')) { - for (let i = 0; i < TLD_EXPANSION.length; i++) { - const tld = TLD_EXPANSION[i]; + for (const pre_wildcard of pre_wildcards) { + try { + const urlObj = new URL(pre_wildcard); + const { host } = urlObj; + if (isNull(host)) { + addObj({ text: original_pattern, domain: false, tld_extra: false }); + } else if (!host.includes('.') && host.includes('*')) { + addObj({ text: original_pattern, domain: false, tld_extra: false }); + } else if (host.endsWith('.tld')) { + for (let i = 0; i < TLD_EXPANSION.length; i++) { + const tld = TLD_EXPANSION[i]; + addObj({ + text: host.replace(/tld$/i, tld), + domain: true, + tld_extra: i != 0 + }); + } + } else if (host.endsWith('.')) { addObj({ - text: uri.host.replace(/tld$/i, tld), + text: host.slice(0, -1), domain: true, - tld_extra: i != 0 + tld_extra: false + }); + } else { + addObj({ + text: host, + domain: true, + tld_extra: false }); } - } else if (uri.host.endsWith('.')) { - addObj({ - text: uri.host.slice(0, -1), - domain: true, - tld_extra: false - }); - } else { - addObj({ - text: uri.host, - domain: true, - tld_extra: false - }); + // eslint-disable-next-line no-unused-vars + } catch (ex) { + addObj({ text: original_pattern, domain: false, tld_extra: false }); } - // eslint-disable-next-line no-unused-vars - } catch (error) { - addObj({ text: original_pattern, domain: false, tld_extra: false }); } + } catch (ex) { + err(ex); } - } catch (ex) { - console.error(ex); } + return [...name_map.values()]; } - return [...name_set]; -}; -const reqCode = async (obj = {}, translate = false) => { - if (obj.code_data) { - return obj.code_data; - } - /** @type { string } */ - const code = await Network.req(obj.code_url, 'GET', 'text'); - if (typeof code !== 'string') { - return; - } - Object.assign(obj, { - code_data: code, - code_meta: {}, - code_size: [Network.format(code.length)], - code_match: [], - code_grant: [], - antifeatures: [] - }); - const grantSet = new Set(); - const afSet = new Set(); - const meta = parse_meta(code); - const applies_to_names = calculate_applies_to_names(code); - - if (translate) { - for (const lng of language.cache) { - if (meta[`name:${lng}`]) { - Object.assign(obj, { - name: meta[`name:${lng}`], - translated: true - }); - } - if (meta[`description:${lng}`]) { - Object.assign(obj, { - description: meta[`description:${lng}`], - translated: true - }); - } + async request(translate = false, code_url, obj) { + if (this.data_code_block) { + return this; } - } + /** @type { string } */ + const code = await Network.req(code_url, 'GET', 'text').catch(err); + if (typeof code !== 'string') { + return this; + } + const isUserCSS = /\.user\.css/.test(code_url); - for (const [key, value] of Object.entries(meta)) { - if (/grant/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (grantSet.has(v)) { - continue; + this.META_START_COMMENT = isUserCSS ? '/* ==UserStyle==' : '// ==UserScript=='; + this.META_END_COMMENT = isUserCSS ? '==/UserStyle== */' : '// ==/UserScript=='; + this.code = code; + this.get_meta_block(); + this.get_code_block(); + this.parse_meta(); + this.calculate_applies_to_names(); + + const { data_meta } = this; + if (translate) { + for (const k of userjs.pool.keys()) { + if (data_meta[`name:${k}`]) { + Object.assign(obj, { + name: data_meta[`name:${k}`] + }); + this.translated = true; + } + if (data_meta[`description:${k}`]) { + Object.assign(obj, { + description: data_meta[`description:${k}`] + }); + this.translated = true; } - grantSet.add(v); } - } else if (/antifeature/.test(key)) { - for (const v of normalizeTarget(value, false)) { - if (afSet.has(v)) { - continue; + } + if (Array.isArray(data_meta.grant)) { + data_meta.grant = union(data_meta.grant); + } + if (data_meta.resource) { + const obj = {}; + if (typeof data_meta.resource === 'string') { + const reg = /(.+)\s+(.+)/.exec(data_meta.resource); + if (reg) { + obj[reg[1].trim()] = reg[2]; + } + } else { + for (const r of data_meta.resource) { + const reg = /(.+)\s+(http.+)/.exec(r); + if (reg) { + obj[reg[1].trim()] = reg[2]; + } } - afSet.add(v); } + data_meta.resource = obj; } + Object.assign(this, { + code_size: [Network.format(code.length)], + meta: data_meta + }); + + return this; } - Object.assign(obj, { - code_meta: meta, - code_match: applies_to_names, - code_grant: [...grantSet], - antifeatures: [...afSet] - }); - return code; -}; +} -export { - calculate_applies_to_names, - get_meta_block, - parse_meta, - reqCode -} \ No newline at end of file +export { ParseUserJS }; diff --git a/src/js/settings.js b/src/js/settings.js deleted file mode 100644 index c4d51cc..0000000 --- a/src/js/settings.js +++ /dev/null @@ -1,294 +0,0 @@ -'use strict'; -import { err } from './logger.js'; -import { XMap } from './XMap.js'; -import { i18n$ } from './i18n.js'; -import { dom, qs } from './querySelector.js'; -import { ael, make, isNull, isEmpty } from './util.js'; - -let cfg = {}; - -const { hermes } = userjs; - -const renderTheme = (theme) => { - theme = theme || cfg.theme; - if (isEmpty(theme)) { - return; - } - // if (theme === defcfg.theme) { - // return; - // } - const sty = qs('mujs-root').style; - for (const [k, v] of Object.entries(theme)) { - const str = `--mujs-${k}`; - const prop = sty.getPropertyValue(str); - if (isEmpty(v)) { - theme[k] = prop; - } - if (prop === v) { - continue; - } - sty.removeProperty(str); - sty.setProperty(str, v); - } -}; - -const cfgMap = new XMap(); - -//#region Make Config -const cfgpage = qs('form'); -const makecfg = () => { - const exBtn = make('mu-js', 'mujs-sty-flex'); - const exportCFG = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_config'), - dataset: { - command: 'export-cfg' - } - }); - const importCFG = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_config'), - dataset: { - command: 'import-cfg' - } - }); - const exportTheme = make('mujs-btn', 'mujs-export', { - textContent: i18n$('export_theme'), - dataset: { - command: 'export-theme' - } - }); - const importTheme = make('mujs-btn', 'mujs-import', { - textContent: i18n$('import_theme'), - dataset: { - command: 'import-theme' - } - }); - exBtn.append(importCFG, importTheme, exportCFG, exportTheme); - cfgpage.append(exBtn); - - const makerow = (desc, type = null, nm, attrs = {}) => { - desc = desc ?? i18n$('no_license'); - nm = nm ?? i18n$('no_license'); - const sec = make('mujs-section', 'mujs-cfg-section', { - style: nm === 'cache' ? 'display: none;' : '' - }); - const lb = make('label'); - const divDesc = make('mu-js', 'mujs-cfg-desc', { - textContent: desc - }); - lb.append(divDesc); - sec.append(lb); - cfgpage.append(sec); - if (isNull(type)) { - return lb; - } - const inp = make('input', 'mujs-cfg-input', { - type, - dataset: { - name: nm - }, - ...attrs - }); - if (!cfgMap.has(nm)) { - cfgMap.set(nm, inp); - } - if (type === 'checkbox') { - const inlab = make('mu-js', 'mujs-inlab'); - const la = make('label', '', { - onclick() { - inp.dispatchEvent(new MouseEvent('click')); - } - }); - inlab.append(inp, la); - lb.append(inlab); - if (nm.includes('-')) { - return inp; - } - if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { - for (const i of cfg.engines) { - if (i.name !== nm) continue; - inp.checked = i.enabled; - inp.dataset.engine = i.name; - ael(inp, 'change', (evt) => { - // MUJS.unsaved = true; - // MUJS.rebuild = true; - i.enabled = evt.target.checked; - hermes.send('Save', { - prop: 'engines', - value: cfg.engines - }); - }); - } - } else { - inp.checked = cfg[nm]; - ael(inp, 'change', (evt) => { - // MUJS.unsaved = true; - // if (/filterlang/i.test(nm)) { - // MUJS.rebuild = true; - // } - cfg[nm] = evt.target.checked; - hermes.send('Save', { - prop: nm, - value: cfg[nm] - }); - }); - } - } else { - lb.append(inp); - } - return inp; - }; - makerow('Sync with GM', 'checkbox', 'cache'); - makerow(i18n$('redirect'), 'checkbox', 'sleazyredirect'); - makerow(i18n$('filter'), 'checkbox', 'filterlang'); - makerow(i18n$('preview_code'), 'checkbox', 'codePreview'); - for (const inp of [ - makerow('Recommend author', 'checkbox', 'recommend-author'), - makerow('Recommend scripts', 'checkbox', 'recommend-others') - ]) { - const nm = inp.dataset.name === 'recommend-author' ? 'author' : 'others'; - inp.checked = cfg.recommend[nm]; - ael(inp, 'change', (evt) => { - // MUJS.unsaved = true; - cfg.recommend[nm] = evt.target.checked; - hermes.send('Save', { - prop: 'recommend', - value: cfg.recommend - }); - }); - } - makerow('Greasy Fork', 'checkbox', 'greasyfork'); - makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); - makerow('Open UserJS', 'checkbox', 'openuserjs'); - makerow('GitHub API', 'checkbox', 'github'); - const ghAPI = cfg.engines.find((c) => c.name === 'github'); - const ghToken = makerow('GitHub API (Token)', 'text', 'github', { - defaultValue: '', - value: ghAPI.token ?? '', - placeholder: 'Paste Access Token' - // onchange(evt) { - // MUJS.unsaved = true; - // MUJS.rebuild = true; - // if (isNull(legacyMsg)) { - // ghAPI.token = evt.target.value; - // } - // } - }); - ghToken.dataset.engine = 'github-token'; - cfgMap.set('github-token', ghToken); - makerow(`${i18n$('dtime')} (ms)`, 'number', 'time', { - defaultValue: 10000, - value: cfg.time, - min: 0, - step: 500, - onbeforeinput(evt) { - if (evt.target.validity.badInput) { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); - } else { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } - }, - oninput(evt) { - // MUJS.unsaved = true; - const t = evt.target; - if (t.validity.badInput || (t.validity.rangeUnderflow && t.value !== '-1')) { - dom.cl.add(t, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); - } else { - dom.cl.remove(t, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - cfg.time = isEmpty(t.value) ? cfg.time : parseFloat(t.value); - } - } - }); - - const cbtn = make('mu-js', 'mujs-sty-flex'); - const savebtn = make('mujs-btn', 'save', { - textContent: i18n$('save'), - dataset: { - command: 'save' - }, - disabled: false - }); - const resetbtn = make('mujs-btn', 'reset', { - textContent: i18n$('reset'), - dataset: { - command: 'reset' - } - }); - const blacklist = make('textarea', '', { - dataset: { - name: 'blacklist' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.blacklist, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.blacklist = JSON.parse(evt.target.value); - isvalid = true; - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); - } - } - } - }); - const theme = make('textarea', '', { - dataset: { - name: 'theme' - }, - rows: '10', - autocomplete: false, - spellcheck: false, - wrap: 'soft', - value: JSON.stringify(cfg.theme, null, ' '), - oninput(evt) { - let isvalid = true; - try { - cfg.theme = JSON.parse(evt.target.value); - isvalid = true; - renderTheme(JSON.parse(evt.target.value)); - } catch (ex) { - err(ex); - isvalid = false; - } finally { - if (isvalid) { - dom.cl.remove(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', false); - } else { - dom.cl.add(evt.target, 'mujs-invalid'); - dom.prop(savebtn, 'disabled', true); - } - } - } - }); - cfgMap.set('blacklist', blacklist); - cfgMap.set('theme', theme); - cbtn.append(resetbtn, savebtn); - cfgpage.append(blacklist, theme, cbtn); -}; -//#endregion - -/** - * @type {chrome.runtime.Port | browser.runtime.Port | null} - */ -const p = hermes.getPort(); -p.onMessage.addListener((root = {}) => { - const m = root.msg; - if (root.channel === 'Config' && isEmpty(cfg)) { - cfg = m.cfg || cfg; - makecfg(); - } -}); diff --git a/src/js/storage.js b/src/js/storage.js index 3b990c6..19b5300 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -1,7 +1,117 @@ 'use strict'; +import { webext } from './ext.js'; + let api = webext.storage.local; +// #region DEFAULT_CONFIG +/** + * @type { import("../typings/types.d.ts").config } + */ +export const DEFAULT_CONFIG = { + autofetch: true, + // autoinject: true, + autoSort: 'daily_installs', + clearTabCache: true, + // cache: true, + // autoexpand: false, + filterlang: false, + sleazyredirect: false, + // time: 10000, + blacklist: ['userjs-local', 'userjs-finance', 'userjs-social', 'userjs-unsupported'], + preview: { + code: false, + metadata: false + }, + engines: [ + { + enabled: true, + name: 'greasyfork', + query: encodeURIComponent('https://greasyfork.org/scripts/by-site/{host}.json?language=all') + }, + { + enabled: false, + name: 'sleazyfork', + query: encodeURIComponent('https://sleazyfork.org/scripts/by-site/{host}.json?language=all') + }, + // { + // enabled: false, + // name: 'openuserjs', + // query: encodeURIComponent('https://openuserjs.org/?q={host}') + // }, + { + enabled: false, + name: 'github', + token: '', + query: encodeURIComponent( + 'https://api.github.com/search/code?q="// ==UserScript=="+{host}+ "// ==/UserScript=="+in:file+language:js&per_page=30' + ) + } + ], + theme: { + 'even-row': '', + 'odd-row': '', + 'even-err': '', + 'odd-err': '', + 'background-color': '', + 'gf-color': '', + 'sf-color': '', + 'border-b-color': '', + 'gf-btn-color': '', + 'sf-btn-color': '', + 'sf-txt-color': '', + 'txt-color': '', + 'chck-color': '', + 'chck-gf': '', + 'chck-git': '', + 'chck-open': '', + placeholder: '', + 'position-top': '', + 'position-bottom': '', + 'position-left': '', + 'position-right': '', + 'font-family': '' + }, + recommend: { + author: true, + others: true + }, + filters: { + ASCII: { + enabled: false, + name: 'Non-ASCII', + regExp: '[^\\x00-\\x7F\\s]+' + }, + Latin: { + enabled: false, + name: 'Non-Latin', + regExp: '[^\\u0000-\\u024F\\u2000-\\u214F\\s]+' + }, + Games: { + enabled: false, + name: 'Games', + flag: 'iu', + regExp: + 'Aimbot|AntiGame|Agar|agar\\.io|alis\\.io|angel\\.io|ExtencionRipXChetoMalo|AposBot|DFxLite|ZTx-Lite|AposFeedingBot|AposLoader|Balz|Blah Blah|Orc Clan Script|Astro\\s*Empires|^\\s*Attack|^\\s*Battle|BiteFight|Blood\\s*Wars|Bloble|Bonk|Bots|Bots4|Brawler|\\bBvS\\b|Business\\s*Tycoon|Castle\\s*Age|City\\s*Ville|chopcoin\\.io|Comunio|Conquer\\s*Club|CosmoPulse|cursors\\.io|Dark\\s*Orbit|Dead\\s*Frontier|Diep\\.io|\\bDOA\\b|doblons\\.io|DotD|Dossergame|Dragons\\s*of\\s*Atlantis|driftin\\.io|Dugout|\\bDS[a-z]+\\n|elites\\.io|Empire\\s*Board|eRep(ublik)?|Epicmafia|Epic.*War|ExoPlanet|Falcon Tools|Feuerwache|Farming|FarmVille|Fightinfo|Frontier\\s*Ville|Ghost\\s*Trapper|Gladiatus|Goalline|Gondal|gota\\.io|Grepolis|Hobopolis|\\bhwm(\\b|_)|Ikariam|\\bIT2\\b|Jellyneo|Kapi\\s*Hospital|Kings\\s*Age|Kingdoms?\\s*of|knastv(o|oe)gel|Knight\\s*Fight|\\b(Power)?KoC(Atta?ck)?\\b|\\bKOL\\b|Kongregate|Krunker|Last\\s*Emperor|Legends?\\s*of|Light\\s*Rising|lite\\.ext\\.io|Lockerz|\\bLoU\\b|Mafia\\s*(Wars|Mofo)|Menelgame|Mob\\s*Wars|Mouse\\s*Hunt|Molehill\\s*Empire|MooMoo|MyFreeFarm|narwhale\\.io|Neopets|NeoQuest|Nemexia|\\bOGame\\b|Ogar(io)?|Pardus|Pennergame|Pigskin\\s*Empire|PlayerScripts|pokeradar\\.io|Popmundo|Po?we?r\\s*(Bot|Tools)|PsicoTSI|Ravenwood|Schulterglatze|Skribbl|slither\\.io|slitherplus\\.io|slitheriogameplay|SpaceWars|splix\\.io|Survivio|\\bSW_[a-z]+\\n|\\bSnP\\b|The\\s*Crims|The\\s*West|torto\\.io|Travian|Treasure\\s*Isl(and|e)|Tribal\\s*Wars|TW.?PRO|Vampire\\s*Wars|vertix\\.io|War\\s*of\\s*Ninja|World\\s*of\\s*Tanks|West\\s*Wars|wings\\.io|\\bWoD\\b|World\\s*of\\s*Dungeons|wtf\\s*battles|Wurzelimperium|Yohoho|Zombs' + }, + SocialNetworks: { + enabled: false, + name: 'Social Networks', + flag: 'iu', + regExp: + 'Face\\s*book|Google(\\+| Plus)|\\bHabbo|Kaskus|\\bLepra|Leprosorium|MySpace|meinVZ|odnoklassniki|Одноклассники|Orkut|sch(ue|ü)ler(VZ|\\.cc)?|studiVZ|Unfriend|Valenth|VK|vkontakte|ВКонтакте|Qzone|Twitter|TweetDeck' + }, + Clutter: { + enabled: false, + name: 'Clutter', + flag: 'iu', + regExp: + "^\\s*(.{1,3})\\1+\\n|^\\s*(.+?)\\n+\\2\\n*$|^\\s*.{1,5}\\n|do\\s*n('|o)?t (install|download)|nicht installieren|(just )?(\\ban? |\\b)test(ing|s|\\d|\\b)|^\\s*.{0,4}test.{0,4}\\n|\\ntest(ing)?\\s*|^\\s*(\\{@|Smolka|Hacks)|\\[\\d{4,5}\\]|free\\s*download|theme|(night|dark) ?(mode)?" + } + } +}; +// #endregion + /** @type {{ [prefix: string]: StorageArea }} */ export const storageByPrefix = {}; @@ -56,9 +166,7 @@ class StorageArea { async getMulti(ids, transform) { const keys = ids?.map(this.toKey, this); const data = await api.get(keys); - return transform || this.prefix - ? mapEntry.call(data, transform, 'toId', this) - : data; + return transform || this.prefix ? mapEntry.call(data, transform, 'toId', this) : data; } /** @@ -92,10 +200,10 @@ const storage = { api = val; }, /** @return {?StorageArea} */ - forKey: key => storageByPrefix[/^\w+:|$/.exec(key)[0]], + forKey: (key) => storageByPrefix[/^\w+:|$/.exec(key)[0]], base: new StorageArea('base', ''), config: new StorageArea('config', 'cfg:'), - cache: new StorageArea('cache', 'cac:'), + cache: new StorageArea('cache', 'cac:') }; export default storage; diff --git a/src/js/util.js b/src/js/util.js index bb22e94..362cbaf 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -1,35 +1,33 @@ 'use strict'; + +import { webext } from './ext.js'; import { err } from './logger.js'; // #region Utilities -let isMob; -// const isMobile = /Mobile|Tablet/.test(navigator.userAgent); +const userjs = {}; const getUAData = () => { - if (typeof isMob !== 'undefined') { - return isMob; + if (userjs.isMobile !== undefined) { + return userjs.isMobile; } try { - const { platform, mobile } = navigator.userAgentData ?? {}; - isMob = - /Mobile|Tablet/.test(navigator.userAgent ?? '') || - mobile || - /Android|Apple/.test(platform ?? ''); + if (navigator) { + const { userAgent, userAgentData } = navigator; + const { platform, mobile } = userAgentData ? Object(userAgentData) : {}; + userjs.isMobile = + /Mobile|Tablet/.test(userAgent ? String(userAgent) : '') || + Boolean(mobile) || + /Android|Apple/.test(platform ? String(platform) : ''); + } else { + userjs.isMobile = false; + } } catch (ex) { - err({ cause: 'getUAData', message: ex.message }); - isMob = false; + userjs.isMobile = false; + ex.cause = 'getUAData'; + err(ex); } - return isMob; + return userjs.isMobile; }; const isMobile = getUAData(); -/** - * @type { import("../typings/types").hasOwn } - */ -const hasOwn = (obj, prop) => { - if (typeof Object.hasOwn !== 'undefined') { - return Object.hasOwn(obj, prop); - } - return Object.prototype.hasOwnProperty.call(obj, prop); -}; const isString = (val) => typeof val === 'string'; /** * @type { import("../typings/types").objToStr } @@ -38,16 +36,21 @@ const objToStr = (obj) => { return Object.prototype.toString.call(obj); }; /** - * @type { import("../typings/types").strToURL } + * @template {string | URL} S + * @param {S} str */ const strToURL = (str) => { + let url; try { - str = str ?? window.location ?? 'about:blank'; - return objToStr(str).includes('URL') ? str : new URL(str); + url = objToStr(str).includes('URL') ? str : new URL(str); } catch (ex) { - err({ cause: 'strToURL', message: ex.message }); - return window.location; + ex.cause = 'strToURL'; + err(ex); } + if (url !== undefined) { + return url + } + return str; }; /** * @type { import("../typings/types").isRegExp } @@ -119,7 +122,7 @@ const normalizeTarget = (target, toQuery = true, root) => { return Array.from(target); }; /** - * @type { import("../typings/types").ael } + * @type { import("../typings/types.d.ts").ael } */ const ael = (el, type, listener, options = {}) => { try { @@ -134,11 +137,12 @@ const ael = (el, type, listener, options = {}) => { elem.addEventListener(type, listener, options); } } catch (ex) { + ex.cause = 'ael'; err(ex); } }; /** - * @type { import("../typings/types").formAttrs } + * @type { import("../typings/types.d.ts").formAttrs } */ const formAttrs = (elem, attr = {}) => { if (!elem) { @@ -162,29 +166,28 @@ const formAttrs = (elem, attr = {}) => { return elem; }; /** - * @type { import("../typings/types").make } + * @type { import("../typings/types.d.ts").make } */ const make = (tagName, cname, attrs) => { let el; try { - // el = - // tagName === 'fragment' ? document.createDocumentFragment() : document.createElement(tagName); el = document.createElement(tagName); if (!isEmpty(cname)) { - if (isString(cname)) { + if (typeof cname === 'string') { el.className = cname; } else if (isObj(cname)) { formAttrs(el, cname); } } if (!isEmpty(attrs)) { - if (isString(attrs)) { + if (typeof attrs === 'string') { el.textContent = attrs; } else if (isObj(attrs)) { formAttrs(el, attrs); } } } catch (ex) { + ex.cause = 'make'; err(ex); } return el; @@ -198,57 +201,101 @@ const openInTab = async (url) => { const newTab = await webext.tabs.create({ url }); return newTab; }; -const intersect = (a = [], b = []) => { - for (const v of a) { - if (b.includes(v)) { +const union = (...arr) => [...new Set(arr.flat())]; +const loadFilters = (cfg) => { + /** @type {Map} */ + const pool = new Map(); + const handles = { + pool, + enabled() { + return [...pool.values()].filter((o) => o.enabled); + }, + refresh() { + if (!Object.is(pool.size, 0)) pool.clear(); + for (const [key, value] of Object.entries(cfg.filters)) { + if (!pool.has(key)) + pool.set(key, { + ...value, + reg: new RegExp(value.regExp, value.flag), + keyReg: new RegExp(key.trim().toLocaleLowerCase(), 'gi'), + valueReg: new RegExp(value.name.trim().toLocaleLowerCase(), 'gi') + }); + } + return this; + }, + get(str) { + return [...pool.values()].find((v) => v.keyReg.test(str) || v.valueReg.test(str)); + }, + /** + * @param { import("../typings/types.d.ts").GSForkQuery } param0 + */ + match({ name, users }) { + const p = handles.enabled(); + if (Object.is(p.length, 0)) return true; + for (const v of p) { + if ([{ name }, ...users].find((o) => o.name.match(v.reg))) return false; + } return true; } + }; + for (const [key, value] of Object.entries(cfg.filters)) { + if (!pool.has(key)) + pool.set(key, { + ...value, + reg: new RegExp(value.regExp, value.flag), + keyReg: new RegExp(key.trim().toLocaleLowerCase(), 'gi'), + valueReg: new RegExp(value.name.trim().toLocaleLowerCase(), 'gi') + }); } - for (const v of b) { - if (a.includes(v)) { - return true; + return handles.refresh(); +}; +/** + * @param {string} txt + */ +const formatURL = (txt) => + txt + .split('.') + .splice(-2) + .join('.') + .replace(/\/|https:/g, ''); +/******************************************************************************/ + +const matchesFromHostnames = (hostnames) => { + const out = []; + for (const hn of hostnames) { + if (hn === '*' || hn === 'all-urls') { + out.length = 0; + out.push(''); + break; } + out.push(`*://*.${hn}/*`); } - return false; + return out; }; -const template = { - data: { - id: 0, - bad_ratings: 0, - good_ratings: 0, - ok_ratings: 0, - daily_installs: 0, - total_installs: 0, - name: 'NOT FOUND', - description: 'NOT FOUND', - version: '0.0.0', - url: 'about:blank', - code_url: 'about:blank', - created_at: Date.now(), - code_updated_at: Date.now(), - users: [ - { - name: '', - url: '' - } - ] - }, - merge(obj = {}) { - for (const key in template.data) { - if (hasOwn(obj, key)) continue; - obj[key] = template.data[key]; + +const hostnamesFromMatches = (origins) => { + const out = []; + for (const origin of origins) { + if (origin === '') { + out.push('all-urls'); + continue; } - return obj; + const match = /^\*:\/\/(?:\*\.)?([^/]+)\/\*/.exec(origin); + if (match === null) { + continue; + } + out.push(match[1]); } + return out; }; + +/******************************************************************************/ // #endregion export { - isMobile, - hasOwn, + formatURL, objToStr, strToURL, - intersect, isRegExp, isElem, isObj, @@ -262,5 +309,8 @@ export { formAttrs, make, openInTab, - template + union, + loadFilters, + matchesFromHostnames, + hostnamesFromMatches }; diff --git a/src/manifest/chrome.json b/src/manifest/chrome.json index 5581779..78eefbe 100644 --- a/src/manifest/chrome.json +++ b/src/manifest/chrome.json @@ -1,38 +1,41 @@ { - "manifest_version": 2, + "manifest_version": 3, "default_locale": "en", "name": "__MSG_extName__", "description": "__MSG_extShortDesc__", "short_name": "userJSPlus", "background": { - "page": "background.html" + "service_worker": "/js/background.js", + "type": "module" }, - "browser_action": { + "action": { "default_icon": { - "16": "img/icon_16.png", + "16": "img/icon_16.png", "32": "img/icon_32.png", - "64": "img/icon_64.png" + "48": "img/icon_48.png", + "64": "img/icon_64.png", + "128": "img/icon_128.png" }, "default_popup": "popup.html", "default_title": "Magic UserJS+" }, - "options_ui": { - "page": "popup.html?mujs=settings", - "open_in_tab": true - }, + "minimum_chrome_version": "122.0", + "options_page": "popup.html?mujs=settings", "permissions": [ - "tabs", - "", "storage", "unlimitedStorage", + "tabs", + "activeTab", "webRequest" ], - "content_security_policy": "script-src 'self'; object-src 'self'", + "host_permissions": [ + "https://*/*" + ], "icons": { "16": "img/icon_16.png", "32": "img/icon_32.png", + "48": "img/icon_48.png", "64": "img/icon_64.png", "128": "img/icon_128.png" - }, - "commands": {} + } } diff --git a/src/manifest/firefox.json b/src/manifest/firefox.json index cbdb471..3a7ac1b 100644 --- a/src/manifest/firefox.json +++ b/src/manifest/firefox.json @@ -1,48 +1,58 @@ { - "$schema": "https://json.schemastore.org/webextension.json", - "manifest_version": 2, + "manifest_version": 3, "default_locale": "en", "name": "__MSG_extName__", "description": "__MSG_extShortDesc__", "short_name": "userJSPlus", "background": { - "page": "background.html" + "scripts": [ + "/js/background.js" + ], + "type": "module" }, - "browser_action": { - "browser_style": false, + "action": { "default_area": "navbar", "default_icon": { - "16": "img/icon_16.png", + "16": "img/icon_16.png", "32": "img/icon_32.png", - "64": "img/icon_64.png" + "48": "img/icon_48.png", + "64": "img/icon_64.png", + "128": "img/icon_128.png" }, "default_popup": "popup.html", "default_title": "Magic UserJS+" }, + "browser_specific_settings": { + "gecko": { + "id": "uscriptplus@mol.com", + "strict_min_version": "128.0" + }, + "gecko_android": { + "strict_min_version": "128.0" + } + }, "options_ui": { - "page": "popup.html?mujs=settings", - "open_in_tab": true + "open_in_tab": true, + "page": "popup.html?mujs=settings" }, "permissions": [ - "tabs", - "", "storage", "unlimitedStorage", + "tabs", + "activeTab", "webRequest" ], - "browser_specific_settings": { - "gecko": { - "id": "uscriptplus@mol.com", - "strict_min_version": "91.1.0" - } + "host_permissions": [ + "https://*/*" + ], + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" }, - "content_security_policy": "script-src 'self'; object-src 'self'", "icons": { - "16": "img/userjs.svg", - "32": "img/userjs.svg", - "48": "img/userjs.svg", - "64": "img/userjs.svg", - "96": "img/userjs.svg" - }, - "commands": {} + "16": "img/icon_16.png", + "32": "img/icon_32.png", + "48": "img/icon_48.png", + "64": "img/icon_64.png", + "128": "img/icon_128.png" + } } diff --git a/src/sass/_main.scss b/src/sass/_main.scss index 257468a..1cbabb5 100644 --- a/src/sass/_main.scss +++ b/src/sass/_main.scss @@ -833,6 +833,7 @@ mujs-body { } @media screen and (max-width: 800px) { + align-self: center; width: 30em !important; } } @@ -844,7 +845,6 @@ mujs-body { width: -webkit-fit-content; width: -moz-fit-content; width: fit-content; - // max-width: 20em; @media screen and (max-width: 800px) { width: 100% !important; diff --git a/src/sass/fontawesome/_animated.scss b/src/sass/fontawesome/_animated.scss new file mode 100644 index 0000000..779125e --- /dev/null +++ b/src/sass/fontawesome/_animated.scss @@ -0,0 +1,152 @@ +// animating icons +// -------------------------- + +.#{$fa-css-prefix}-beat { + animation-name: #{$fa-css-prefix}-beat; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out); +} + +.#{$fa-css-prefix}-bounce { + animation-name: #{$fa-css-prefix}-bounce; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(0.280, 0.840, 0.420, 1)); +} + +.#{$fa-css-prefix}-fade { + animation-name: #{$fa-css-prefix}-fade; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1)); +} + +.#{$fa-css-prefix}-beat-fade { + animation-name: #{$fa-css-prefix}-beat-fade; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1)); +} + +.#{$fa-css-prefix}-flip { + animation-name: #{$fa-css-prefix}-flip; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out); +} + +.#{$fa-css-prefix}-shake { + animation-name: #{$fa-css-prefix}-shake; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear); +} + +.#{$fa-css-prefix}-spin { + animation-name: #{$fa-css-prefix}-spin; + animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s); + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 2s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear); +} + +.#{$fa-css-prefix}-spin-reverse { + --#{$fa-css-prefix}-animation-direction: reverse; +} + +.#{$fa-css-prefix}-pulse, +.#{$fa-css-prefix}-spin-pulse { + animation-name: #{$fa-css-prefix}-spin; + animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal); + animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s); + animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite); + animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, steps(8)); +} + +// if agent or operating system prefers reduced motion, disable animations +// see: https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/ +// see: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion +@media (prefers-reduced-motion: reduce) { + .#{$fa-css-prefix}-beat, + .#{$fa-css-prefix}-bounce, + .#{$fa-css-prefix}-fade, + .#{$fa-css-prefix}-beat-fade, + .#{$fa-css-prefix}-flip, + .#{$fa-css-prefix}-pulse, + .#{$fa-css-prefix}-shake, + .#{$fa-css-prefix}-spin, + .#{$fa-css-prefix}-spin-pulse { + animation-delay: -1ms; + animation-duration: 1ms; + animation-iteration-count: 1; + transition-delay: 0s; + transition-duration: 0s; + } +} + +@keyframes #{$fa-css-prefix}-beat { + 0%, 90% { transform: scale(1); } + 45% { transform: scale(var(--#{$fa-css-prefix}-beat-scale, 1.25)); } +} + +@keyframes #{$fa-css-prefix}-bounce { + 0% { transform: scale(1,1) translateY(0); } + 10% { transform: scale(var(--#{$fa-css-prefix}-bounce-start-scale-x, 1.1),var(--#{$fa-css-prefix}-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { transform: scale(var(--#{$fa-css-prefix}-bounce-jump-scale-x, 0.9),var(--#{$fa-css-prefix}-bounce-jump-scale-y, 1.1)) translateY(var(--#{$fa-css-prefix}-bounce-height, -0.5em)); } + 50% { transform: scale(var(--#{$fa-css-prefix}-bounce-land-scale-x, 1.05),var(--#{$fa-css-prefix}-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { transform: scale(1,1) translateY(var(--#{$fa-css-prefix}-bounce-rebound, -0.125em)); } + 64% { transform: scale(1,1) translateY(0); } + 100% { transform: scale(1,1) translateY(0); } +} + +@keyframes #{$fa-css-prefix}-fade { + 50% { opacity: var(--#{$fa-css-prefix}-fade-opacity, 0.4); } +} + +@keyframes #{$fa-css-prefix}-beat-fade { + 0%, 100% { + opacity: var(--#{$fa-css-prefix}-beat-fade-opacity, 0.4); + transform: scale(1); + } + 50% { + opacity: 1; + transform: scale(var(--#{$fa-css-prefix}-beat-fade-scale, 1.125)); + } +} + +@keyframes #{$fa-css-prefix}-flip { + 50% { + transform: rotate3d(var(--#{$fa-css-prefix}-flip-x, 0), var(--#{$fa-css-prefix}-flip-y, 1), var(--#{$fa-css-prefix}-flip-z, 0), var(--#{$fa-css-prefix}-flip-angle, -180deg)); + } +} + +@keyframes #{$fa-css-prefix}-shake { + 0% { transform: rotate(-15deg); } + 4% { transform: rotate(15deg); } + 8%, 24% { transform: rotate(-18deg); } + 12%, 28% { transform: rotate(18deg); } + 16% { transform: rotate(-22deg); } + 20% { transform: rotate(22deg); } + 32% { transform: rotate(-12deg); } + 36% { transform: rotate(12deg); } + 40%, 100% { transform: rotate(0deg); } +} + +@keyframes #{$fa-css-prefix}-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/src/sass/fontawesome/_bordered-pulled.scss b/src/sass/fontawesome/_bordered-pulled.scss new file mode 100644 index 0000000..06bf72d --- /dev/null +++ b/src/sass/fontawesome/_bordered-pulled.scss @@ -0,0 +1,20 @@ +// bordered + pulled icons +// ------------------------- + +.#{$fa-css-prefix}-border { + border-color: var(--#{$fa-css-prefix}-border-color, #{$fa-border-color}); + border-radius: var(--#{$fa-css-prefix}-border-radius, #{$fa-border-radius}); + border-style: var(--#{$fa-css-prefix}-border-style, #{$fa-border-style}); + border-width: var(--#{$fa-css-prefix}-border-width, #{$fa-border-width}); + padding: var(--#{$fa-css-prefix}-border-padding, #{$fa-border-padding}); +} + +.#{$fa-css-prefix}-pull-left { + float: left; + margin-right: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin}); +} + +.#{$fa-css-prefix}-pull-right { + float: right; + margin-left: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin}); +} diff --git a/src/sass/fontawesome/_core.scss b/src/sass/fontawesome/_core.scss new file mode 100644 index 0000000..a850b0f --- /dev/null +++ b/src/sass/fontawesome/_core.scss @@ -0,0 +1,49 @@ +// base icon class definition +// ------------------------- + +.#{$fa-css-prefix} { + font-family: var(--#{$fa-css-prefix}-style-family, '#{$fa-style-family}'); + font-weight: var(--#{$fa-css-prefix}-style, #{$fa-style}); +} + +.fas, +.far, +.fab, +.#{$fa-css-prefix}-solid, +.#{$fa-css-prefix}-regular, +.#{$fa-css-prefix}-brands, +.#{$fa-css-prefix} { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: var(--#{$fa-css-prefix}-display, #{$fa-display}); + font-style: normal; + font-variant: normal; + line-height: 1; + text-rendering: auto; +} + +.fas::before, +.far::before, +.fab::before, +.#{$fa-css-prefix}-solid::before, +.#{$fa-css-prefix}-regular::before, +.#{$fa-css-prefix}-brands::before, +.#{$fa-css-prefix}::before { + content: var(#{$fa-icon-property}); +} + +.#{$fa-css-prefix}-classic, +.fas, +.#{$fa-css-prefix}-solid, +.far, +.#{$fa-css-prefix}-regular { + font-family: 'Font Awesome 6 Free'; +} +.#{$fa-css-prefix}-brands, +.fab { + font-family: 'Font Awesome 6 Brands'; +} + +%fa-icon { + @include fa-icon; +} diff --git a/src/sass/fontawesome/_fixed-width.scss b/src/sass/fontawesome/_fixed-width.scss new file mode 100644 index 0000000..7234236 --- /dev/null +++ b/src/sass/fontawesome/_fixed-width.scss @@ -0,0 +1,7 @@ +// fixed-width icons +// ------------------------- + +.#{$fa-css-prefix}-fw { + text-align: center; + width: $fa-fw-width; +} diff --git a/src/sass/fontawesome/_functions.scss b/src/sass/fontawesome/_functions.scss new file mode 100644 index 0000000..a17ffe8 --- /dev/null +++ b/src/sass/fontawesome/_functions.scss @@ -0,0 +1,57 @@ +// functions +// -------------------------- + +// fa-content: convenience function used to set content property +@function fa-content($fa-var) { + @return unquote("\"#{ $fa-var }\""); +} + +// fa-divide: Originally obtained from the Bootstrap https://github.com/twbs/bootstrap +// +// Licensed under: The MIT License (MIT) +// +// Copyright (c) 2011-2021 Twitter, Inc. +// Copyright (c) 2011-2021 The Bootstrap Authors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +@function fa-divide($dividend, $divisor, $precision: 10) { + $sign: if($dividend > 0 and $divisor > 0, 1, -1); + $dividend: abs($dividend); + $divisor: abs($divisor); + $quotient: 0; + $remainder: $dividend; + @if $dividend == 0 { + @return 0; + } + @if $divisor == 0 { + @error "Cannot divide by 0"; + } + @if $divisor == 1 { + @return $dividend; + } + @while $remainder >= $divisor { + $quotient: $quotient + 1; + $remainder: $remainder - $divisor; + } + @if $remainder > 0 and $precision > 0 { + $remainder: fa-divide($remainder * 10, $divisor, $precision - 1) * .1; + } + @return ($quotient + $remainder) * $sign; +} diff --git a/src/sass/fontawesome/_icons.scss b/src/sass/fontawesome/_icons.scss new file mode 100644 index 0000000..2f13535 --- /dev/null +++ b/src/sass/fontawesome/_icons.scss @@ -0,0 +1,12 @@ +// specific icon class definition +// ------------------------- + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ + +@each $name, $icon in $fa-icons { + .#{$fa-css-prefix}-#{$name} { + #{$fa-icon-property}: unquote("\"#{ $icon }\""); + } +} + diff --git a/src/sass/fontawesome/_list.scss b/src/sass/fontawesome/_list.scss new file mode 100644 index 0000000..120506a --- /dev/null +++ b/src/sass/fontawesome/_list.scss @@ -0,0 +1,18 @@ +// icons in a list +// ------------------------- + +.#{$fa-css-prefix}-ul { + list-style-type: none; + margin-left: var(--#{$fa-css-prefix}-li-margin, #{$fa-li-margin}); + padding-left: 0; + + > li { position: relative; } +} + +.#{$fa-css-prefix}-li { + left: calc(-1 * var(--#{$fa-css-prefix}-li-width, #{$fa-li-width})); + position: absolute; + text-align: center; + width: var(--#{$fa-css-prefix}-li-width, #{$fa-li-width}); + line-height: inherit; +} diff --git a/src/sass/fontawesome/_mixins.scss b/src/sass/fontawesome/_mixins.scss new file mode 100644 index 0000000..71f99ad --- /dev/null +++ b/src/sass/fontawesome/_mixins.scss @@ -0,0 +1,65 @@ +// mixins +// -------------------------- + +// base rendering for an icon +@mixin fa-icon { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + display: inline-block; + font-style: normal; + font-variant: normal; + font-weight: normal; + line-height: 1; +} + +// sets relative font-sizing and alignment (in _sizing) +@mixin fa-size ($font-size) { + font-size: fa-divide($font-size, $fa-size-scale-base) * 1em; // converts step in sizing scale into an em-based value that's relative to the scale's base + line-height: fa-divide(1, $font-size) * 1em; // sets the line-height of the icon back to that of it's parent + vertical-align: (fa-divide(6, $font-size) - fa-divide(3, 8)) * 1em; // vertically centers the icon taking into account the surrounding text's descender +} + +// only display content to screen readers +// see: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/ +// see: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/ +@mixin fa-sr-only() { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +// use in conjunction with .sr-only to only display content when it's focused +@mixin fa-sr-only-focusable() { + &:not(:focus) { + @include fa-sr-only(); + } +} + +// sets a specific icon family to use alongside style + icon mixins +@mixin fa-family-classic() { + @extend .fa-classic; +} + +// convenience mixins for declaring pseudo-elements by CSS variable, +// including all style-specific font properties +@mixin fa-icon-solid($fa-var) { + @extend .fa-solid; + + & { #{$fa-icon-property}: unquote("\"#{ $fa-var }\""); #{$fa-duotone-icon-property}: unquote("\"#{ $fa-var }#{ $fa-var }\""); } +} +@mixin fa-icon-regular($fa-var) { + @extend .fa-regular; + + & { #{$fa-icon-property}: unquote("\"#{ $fa-var }\""); #{$fa-duotone-icon-property}: unquote("\"#{ $fa-var }#{ $fa-var }\""); } +} +@mixin fa-icon-brands($fa-var) { + @extend .fa-brands; + + & { #{$fa-icon-property}: unquote("\"#{ $fa-var }\""); #{$fa-duotone-icon-property}: unquote("\"#{ $fa-var }#{ $fa-var }\""); } +} diff --git a/src/sass/fontawesome/_rotated-flipped.scss b/src/sass/fontawesome/_rotated-flipped.scss new file mode 100644 index 0000000..0bd4b7c --- /dev/null +++ b/src/sass/fontawesome/_rotated-flipped.scss @@ -0,0 +1,31 @@ +// rotating + flipping icons +// ------------------------- + +.#{$fa-css-prefix}-rotate-90 { + transform: rotate(90deg); +} + +.#{$fa-css-prefix}-rotate-180 { + transform: rotate(180deg); +} + +.#{$fa-css-prefix}-rotate-270 { + transform: rotate(270deg); +} + +.#{$fa-css-prefix}-flip-horizontal { + transform: scale(-1, 1); +} + +.#{$fa-css-prefix}-flip-vertical { + transform: scale(1, -1); +} + +.#{$fa-css-prefix}-flip-both, +.#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { + transform: scale(-1, -1); +} + +.#{$fa-css-prefix}-rotate-by { + transform: rotate(var(--#{$fa-css-prefix}-rotate-angle, 0)); +} diff --git a/src/sass/fontawesome/_screen-reader.scss b/src/sass/fontawesome/_screen-reader.scss new file mode 100644 index 0000000..2beb887 --- /dev/null +++ b/src/sass/fontawesome/_screen-reader.scss @@ -0,0 +1,14 @@ +// screen-reader utilities +// ------------------------- + +// only display content to screen readers +.sr-only, +.#{$fa-css-prefix}-sr-only { + @include fa-sr-only; +} + +// use in conjunction with .sr-only to only display content when it's focused +.sr-only-focusable, +.#{$fa-css-prefix}-sr-only-focusable { + @include fa-sr-only-focusable; +} diff --git a/src/sass/fontawesome/_shims.scss b/src/sass/fontawesome/_shims.scss new file mode 100644 index 0000000..3fb6d41 --- /dev/null +++ b/src/sass/fontawesome/_shims.scss @@ -0,0 +1,1578 @@ +.#{$fa-css-prefix}.#{$fa-css-prefix}-glass { #{$fa-icon-property}: unquote("\"#{ $fa-var-martini-glass-empty }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-envelope-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-envelope-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-envelope }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-star }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-remove { #{$fa-icon-property}: unquote("\"#{ $fa-var-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-close { #{$fa-icon-property}: unquote("\"#{ $fa-var-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-gear { #{$fa-icon-property}: unquote("\"#{ $fa-var-gear }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-trash-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-trash-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-trash-can }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-home { #{$fa-icon-property}: unquote("\"#{ $fa-var-house }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-clock-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-clock-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-clock }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-play-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-play-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-play }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-repeat { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-rotate-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rotate-right { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-rotate-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-refresh { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrows-rotate }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-list-alt { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-list-alt { #{$fa-icon-property}: unquote("\"#{ $fa-var-rectangle-list }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-dedent { #{$fa-icon-property}: unquote("\"#{ $fa-var-outdent }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-video-camera { #{$fa-icon-property}: unquote("\"#{ $fa-var-video }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-picture-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-picture-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-image }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-photo { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-photo { #{$fa-icon-property}: unquote("\"#{ $fa-var-image }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-image { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-image { #{$fa-icon-property}: unquote("\"#{ $fa-var-image }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-map-marker { #{$fa-icon-property}: unquote("\"#{ $fa-var-location-dot }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-pencil-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pencil-square-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-pen-to-square }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-edit { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-edit { #{$fa-icon-property}: unquote("\"#{ $fa-var-pen-to-square }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-share-square-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-share-from-square }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-check-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-check-square-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-check }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrows { #{$fa-icon-property}: unquote("\"#{ $fa-var-up-down-left-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-times-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-times-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-check-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-check-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-check }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-mail-forward { #{$fa-icon-property}: unquote("\"#{ $fa-var-share }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-expand { #{$fa-icon-property}: unquote("\"#{ $fa-var-up-right-and-down-left-from-center }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-compress { #{$fa-icon-property}: unquote("\"#{ $fa-var-down-left-and-up-right-to-center }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-eye { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-eye-slash { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-warning { #{$fa-icon-property}: unquote("\"#{ $fa-var-triangle-exclamation }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar { #{$fa-icon-property}: unquote("\"#{ $fa-var-calendar-days }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrows-v { #{$fa-icon-property}: unquote("\"#{ $fa-var-up-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrows-h { #{$fa-icon-property}: unquote("\"#{ $fa-var-left-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bar-chart { #{$fa-icon-property}: unquote("\"#{ $fa-var-chart-column }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bar-chart-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-chart-column }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-twitter-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-twitter-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-twitter }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-facebook }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-gears { #{$fa-icon-property}: unquote("\"#{ $fa-var-gears }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thumbs-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-thumbs-o-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-thumbs-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thumbs-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-thumbs-o-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-thumbs-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-heart-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-heart-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-heart }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sign-out { #{$fa-icon-property}: unquote("\"#{ $fa-var-right-from-bracket }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-linkedin-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-linkedin-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-linkedin }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thumb-tack { #{$fa-icon-property}: unquote("\"#{ $fa-var-thumbtack }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-external-link { #{$fa-icon-property}: unquote("\"#{ $fa-var-up-right-from-square }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sign-in { #{$fa-icon-property}: unquote("\"#{ $fa-var-right-to-bracket }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-github-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-github-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-github }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-lemon-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-lemon-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-lemon }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-square-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-square }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bookmark-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bookmark-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-bookmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-twitter { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook { #{$fa-icon-property}: unquote("\"#{ $fa-var-facebook-f }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook-f { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook-f { #{$fa-icon-property}: unquote("\"#{ $fa-var-facebook-f }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-github { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-credit-card { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-feed { #{$fa-icon-property}: unquote("\"#{ $fa-var-rss }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hdd-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hdd-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hard-drive }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-right { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-point-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-left { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-point-left }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-point-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-o-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-point-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-globe { #{$fa-icon-property}: unquote("\"#{ $fa-var-earth-americas }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-tasks { #{$fa-icon-property}: unquote("\"#{ $fa-var-bars-progress }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrows-alt { #{$fa-icon-property}: unquote("\"#{ $fa-var-maximize }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-group { #{$fa-icon-property}: unquote("\"#{ $fa-var-users }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-chain { #{$fa-icon-property}: unquote("\"#{ $fa-var-link }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cut { #{$fa-icon-property}: unquote("\"#{ $fa-var-scissors }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-files-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-files-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-copy }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-floppy-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-floppy-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-floppy-disk }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-save { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-save { #{$fa-icon-property}: unquote("\"#{ $fa-var-floppy-disk }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-navicon { #{$fa-icon-property}: unquote("\"#{ $fa-var-bars }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-reorder { #{$fa-icon-property}: unquote("\"#{ $fa-var-bars }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-magic { #{$fa-icon-property}: unquote("\"#{ $fa-var-wand-magic-sparkles }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-pinterest { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pinterest-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pinterest-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-pinterest }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-google-plus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus { #{$fa-icon-property}: unquote("\"#{ $fa-var-google-plus-g }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-money { #{$fa-icon-property}: unquote("\"#{ $fa-var-money-bill-1 }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-unsorted { #{$fa-icon-property}: unquote("\"#{ $fa-var-sort }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-desc { #{$fa-icon-property}: unquote("\"#{ $fa-var-sort-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-asc { #{$fa-icon-property}: unquote("\"#{ $fa-var-sort-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-linkedin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-linkedin { #{$fa-icon-property}: unquote("\"#{ $fa-var-linkedin-in }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rotate-left { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-rotate-left }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-legal { #{$fa-icon-property}: unquote("\"#{ $fa-var-gavel }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-tachometer { #{$fa-icon-property}: unquote("\"#{ $fa-var-gauge-high }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-dashboard { #{$fa-icon-property}: unquote("\"#{ $fa-var-gauge-high }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-comment-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-comment-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-comment }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-comments-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-comments-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-comments }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-flash { #{$fa-icon-property}: unquote("\"#{ $fa-var-bolt }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-clipboard { #{$fa-icon-property}: unquote("\"#{ $fa-var-paste }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-lightbulb-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-lightbulb-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-lightbulb }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-exchange { #{$fa-icon-property}: unquote("\"#{ $fa-var-right-left }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cloud-download { #{$fa-icon-property}: unquote("\"#{ $fa-var-cloud-arrow-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cloud-upload { #{$fa-icon-property}: unquote("\"#{ $fa-var-cloud-arrow-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bell-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bell-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-bell }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cutlery { #{$fa-icon-property}: unquote("\"#{ $fa-var-utensils }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-text-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-text-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-lines }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-building-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-building-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-building }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hospital-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hospital-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hospital }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-tablet { #{$fa-icon-property}: unquote("\"#{ $fa-var-tablet-screen-button }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-mobile { #{$fa-icon-property}: unquote("\"#{ $fa-var-mobile-screen-button }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-mobile-phone { #{$fa-icon-property}: unquote("\"#{ $fa-var-mobile-screen-button }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-mail-reply { #{$fa-icon-property}: unquote("\"#{ $fa-var-reply }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-github-alt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-folder-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-folder-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-folder }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-folder-open-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-folder-open-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-folder-open }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-smile-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-smile-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-face-smile }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-frown-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-frown-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-face-frown }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-meh-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-meh-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-face-meh }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-keyboard-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-keyboard-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-keyboard }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-flag-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-flag-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-flag }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-mail-reply-all { #{$fa-icon-property}: unquote("\"#{ $fa-var-reply-all }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-half-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-half-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-star-half-stroke }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-half-empty { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-half-empty { #{$fa-icon-property}: unquote("\"#{ $fa-var-star-half-stroke }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-half-full { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-star-half-full { #{$fa-icon-property}: unquote("\"#{ $fa-var-star-half-stroke }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-code-fork { #{$fa-icon-property}: unquote("\"#{ $fa-var-code-branch }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-chain-broken { #{$fa-icon-property}: unquote("\"#{ $fa-var-link-slash }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-unlink { #{$fa-icon-property}: unquote("\"#{ $fa-var-link-slash }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-calendar }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-maxcdn { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-html5 { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-css3 { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-unlock-alt { #{$fa-icon-property}: unquote("\"#{ $fa-var-unlock }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-minus-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-minus-square-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-minus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-level-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-turn-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-level-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-turn-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-pencil-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-pen }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-external-link-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-up-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-compass { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-down { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-down }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-up { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-up }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-right { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-right { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-eur { #{$fa-icon-property}: unquote("\"#{ $fa-var-euro-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-euro { #{$fa-icon-property}: unquote("\"#{ $fa-var-euro-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-gbp { #{$fa-icon-property}: unquote("\"#{ $fa-var-sterling-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-usd { #{$fa-icon-property}: unquote("\"#{ $fa-var-dollar-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-dollar { #{$fa-icon-property}: unquote("\"#{ $fa-var-dollar-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-inr { #{$fa-icon-property}: unquote("\"#{ $fa-var-indian-rupee-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rupee { #{$fa-icon-property}: unquote("\"#{ $fa-var-indian-rupee-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-jpy { #{$fa-icon-property}: unquote("\"#{ $fa-var-yen-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cny { #{$fa-icon-property}: unquote("\"#{ $fa-var-yen-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rmb { #{$fa-icon-property}: unquote("\"#{ $fa-var-yen-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-yen { #{$fa-icon-property}: unquote("\"#{ $fa-var-yen-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rub { #{$fa-icon-property}: unquote("\"#{ $fa-var-ruble-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-ruble { #{$fa-icon-property}: unquote("\"#{ $fa-var-ruble-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rouble { #{$fa-icon-property}: unquote("\"#{ $fa-var-ruble-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-krw { #{$fa-icon-property}: unquote("\"#{ $fa-var-won-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-won { #{$fa-icon-property}: unquote("\"#{ $fa-var-won-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-btc { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bitcoin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bitcoin { #{$fa-icon-property}: unquote("\"#{ $fa-var-btc }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-text { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-lines }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-alpha-asc { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-down-a-z }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-alpha-desc { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-down-z-a }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-amount-asc { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-down-short-wide }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-amount-desc { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-down-wide-short }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-numeric-asc { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-down-1-9 }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sort-numeric-desc { #{$fa-icon-property}: unquote("\"#{ $fa-var-arrow-down-9-1 }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-youtube-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-youtube-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-youtube }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-youtube { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-xing { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-xing-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-xing-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-xing }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-youtube-play { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-youtube-play { #{$fa-icon-property}: unquote("\"#{ $fa-var-youtube }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-dropbox { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-stack-overflow { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-instagram { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-flickr { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-adn { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bitbucket { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bitbucket-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bitbucket-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-bitbucket }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-tumblr { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-tumblr-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-tumblr-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-tumblr }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-long-arrow-down { #{$fa-icon-property}: unquote("\"#{ $fa-var-down-long }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-long-arrow-up { #{$fa-icon-property}: unquote("\"#{ $fa-var-up-long }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-long-arrow-left { #{$fa-icon-property}: unquote("\"#{ $fa-var-left-long }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-long-arrow-right { #{$fa-icon-property}: unquote("\"#{ $fa-var-right-long }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-apple { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-windows { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-android { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-linux { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-dribbble { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-skype { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-foursquare { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-trello { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-gratipay { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-gittip { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-gittip { #{$fa-icon-property}: unquote("\"#{ $fa-var-gratipay }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sun-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-sun-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-sun }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-moon-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-moon-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-moon }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-vk { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-weibo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-renren { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pagelines { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-stack-exchange { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-right { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-right { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-right }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-arrow-circle-o-left { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-left }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-caret-square-o-left { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-left }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-left { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-toggle-left { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-caret-left }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-dot-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-dot-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-dot }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-vimeo-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-vimeo-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-vimeo }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-try { #{$fa-icon-property}: unquote("\"#{ $fa-var-turkish-lira-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-turkish-lira { #{$fa-icon-property}: unquote("\"#{ $fa-var-turkish-lira-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-plus-square-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-plus-square-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-plus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-slack { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wordpress { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-openid { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-institution { #{$fa-icon-property}: unquote("\"#{ $fa-var-building-columns }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bank { #{$fa-icon-property}: unquote("\"#{ $fa-var-building-columns }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-mortar-board { #{$fa-icon-property}: unquote("\"#{ $fa-var-graduation-cap }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-yahoo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-reddit { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-reddit-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-reddit-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-reddit }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-stumbleupon-circle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-stumbleupon { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-delicious { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-digg { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pied-piper-pp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pied-piper-alt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-drupal { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-joomla { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-behance { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-behance-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-behance-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-behance }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-steam { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-steam-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-steam-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-steam }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-automobile { #{$fa-icon-property}: unquote("\"#{ $fa-var-car }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cab { #{$fa-icon-property}: unquote("\"#{ $fa-var-taxi }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-spotify { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-deviantart { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-soundcloud { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-pdf-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-pdf-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-pdf }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-word-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-word-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-word }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-excel-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-excel-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-excel }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-powerpoint-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-powerpoint-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-powerpoint }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-image-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-image-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-image }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-photo-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-photo-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-image }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-picture-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-picture-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-image }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-archive-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-archive-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-zipper }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-zip-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-zip-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-zipper }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-audio-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-audio-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-audio }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-sound-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-sound-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-audio }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-video-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-video-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-video }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-movie-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-movie-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-video }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-code-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-file-code-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-file-code }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-vine { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-codepen { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-jsfiddle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-life-bouy { #{$fa-icon-property}: unquote("\"#{ $fa-var-life-ring }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-life-buoy { #{$fa-icon-property}: unquote("\"#{ $fa-var-life-ring }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-life-saver { #{$fa-icon-property}: unquote("\"#{ $fa-var-life-ring }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-support { #{$fa-icon-property}: unquote("\"#{ $fa-var-life-ring }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-circle-o-notch { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-notch }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-rebel { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-ra { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-ra { #{$fa-icon-property}: unquote("\"#{ $fa-var-rebel }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-resistance { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-resistance { #{$fa-icon-property}: unquote("\"#{ $fa-var-rebel }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-empire { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-ge { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-ge { #{$fa-icon-property}: unquote("\"#{ $fa-var-empire }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-git-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-git-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-git }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-git { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hacker-news { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-y-combinator-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-y-combinator-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-hacker-news }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-yc-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-yc-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-hacker-news }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-tencent-weibo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-qq { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-weixin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wechat { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wechat { #{$fa-icon-property}: unquote("\"#{ $fa-var-weixin }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-send { #{$fa-icon-property}: unquote("\"#{ $fa-var-paper-plane }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-paper-plane-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-paper-plane-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-paper-plane }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-send-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-send-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-paper-plane }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-circle-thin { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-circle-thin { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-header { #{$fa-icon-property}: unquote("\"#{ $fa-var-heading }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-futbol-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-futbol-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-futbol }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-soccer-ball-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-soccer-ball-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-futbol }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-slideshare { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-twitch { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-yelp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-newspaper-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-newspaper-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-newspaper }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-paypal { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-wallet { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-visa { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-mastercard { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-discover { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-amex { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-paypal { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-stripe { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bell-slash-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bell-slash-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-bell-slash }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-trash { #{$fa-icon-property}: unquote("\"#{ $fa-var-trash-can }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-copyright { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-eyedropper { #{$fa-icon-property}: unquote("\"#{ $fa-var-eye-dropper }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-area-chart { #{$fa-icon-property}: unquote("\"#{ $fa-var-chart-area }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-pie-chart { #{$fa-icon-property}: unquote("\"#{ $fa-var-chart-pie }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-line-chart { #{$fa-icon-property}: unquote("\"#{ $fa-var-chart-line }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-lastfm { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-lastfm-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-lastfm-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-lastfm }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-ioxhost { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-angellist { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc { #{$fa-icon-property}: unquote("\"#{ $fa-var-closed-captioning }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-ils { #{$fa-icon-property}: unquote("\"#{ $fa-var-shekel-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-shekel { #{$fa-icon-property}: unquote("\"#{ $fa-var-shekel-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-sheqel { #{$fa-icon-property}: unquote("\"#{ $fa-var-shekel-sign }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-buysellads { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-connectdevelop { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-dashcube { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-forumbee { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-leanpub { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-sellsy { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-shirtsinbulk { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-simplybuilt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-skyatlas { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-diamond { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-diamond { #{$fa-icon-property}: unquote("\"#{ $fa-var-gem }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-transgender { #{$fa-icon-property}: unquote("\"#{ $fa-var-mars-and-venus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-intersex { #{$fa-icon-property}: unquote("\"#{ $fa-var-mars-and-venus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-transgender-alt { #{$fa-icon-property}: unquote("\"#{ $fa-var-transgender }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook-official { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-facebook-official { #{$fa-icon-property}: unquote("\"#{ $fa-var-facebook }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-pinterest-p { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-whatsapp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hotel { #{$fa-icon-property}: unquote("\"#{ $fa-var-bed }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-viacoin { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-medium { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-y-combinator { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-yc { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-yc { #{$fa-icon-property}: unquote("\"#{ $fa-var-y-combinator }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-optin-monster { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-opencart { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-expeditedssl { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-battery-4 { #{$fa-icon-property}: unquote("\"#{ $fa-var-battery-full }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-battery { #{$fa-icon-property}: unquote("\"#{ $fa-var-battery-full }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-battery-3 { #{$fa-icon-property}: unquote("\"#{ $fa-var-battery-three-quarters }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-battery-2 { #{$fa-icon-property}: unquote("\"#{ $fa-var-battery-half }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-battery-1 { #{$fa-icon-property}: unquote("\"#{ $fa-var-battery-quarter }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-battery-0 { #{$fa-icon-property}: unquote("\"#{ $fa-var-battery-empty }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-object-group { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-object-ungroup { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-sticky-note-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-sticky-note-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-note-sticky }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-jcb { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-cc-diners-club { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-clone { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hourglass-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hourglass }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hourglass-1 { #{$fa-icon-property}: unquote("\"#{ $fa-var-hourglass-start }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hourglass-2 { #{$fa-icon-property}: unquote("\"#{ $fa-var-hourglass-half }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hourglass-3 { #{$fa-icon-property}: unquote("\"#{ $fa-var-hourglass-end }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-rock-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-rock-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-back-fist }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-grab-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-grab-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-back-fist }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-paper-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-paper-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-stop-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-stop-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-scissors-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-scissors-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-scissors }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-lizard-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-lizard-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-lizard }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-spock-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-spock-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-spock }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-pointer-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-pointer-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-pointer }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-peace-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-hand-peace-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-hand-peace }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-registered { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-creative-commons { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-gg { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-gg-circle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-odnoklassniki { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-odnoklassniki-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-odnoklassniki-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-odnoklassniki }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-get-pocket { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wikipedia-w { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-safari { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-chrome { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-firefox { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-opera { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-internet-explorer { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-television { #{$fa-icon-property}: unquote("\"#{ $fa-var-tv }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-contao { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-500px { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-amazon { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-plus-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-plus-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-calendar-plus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-minus-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-minus-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-calendar-minus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-times-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-times-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-calendar-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-check-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-calendar-check-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-calendar-check }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-map-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-map-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-map }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-commenting { #{$fa-icon-property}: unquote("\"#{ $fa-var-comment-dots }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-commenting-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-commenting-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-comment-dots }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-houzz { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-vimeo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-vimeo { #{$fa-icon-property}: unquote("\"#{ $fa-var-vimeo-v }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-black-tie { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-fonticons { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-reddit-alien { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-edge { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-credit-card-alt { #{$fa-icon-property}: unquote("\"#{ $fa-var-credit-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-codiepie { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-modx { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-fort-awesome { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-usb { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-product-hunt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-mixcloud { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-scribd { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pause-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-pause-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-pause }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-stop-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-stop-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-stop }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bluetooth { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-bluetooth-b { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-gitlab { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wpbeginner { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wpforms { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-envira { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wheelchair-alt { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wheelchair-alt { #{$fa-icon-property}: unquote("\"#{ $fa-var-accessible-icon }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-question-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-question-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-question }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-volume-control-phone { #{$fa-icon-property}: unquote("\"#{ $fa-var-phone-volume }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-asl-interpreting { #{$fa-icon-property}: unquote("\"#{ $fa-var-hands-asl-interpreting }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-deafness { #{$fa-icon-property}: unquote("\"#{ $fa-var-ear-deaf }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-hard-of-hearing { #{$fa-icon-property}: unquote("\"#{ $fa-var-ear-deaf }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-glide { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-glide-g { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-signing { #{$fa-icon-property}: unquote("\"#{ $fa-var-hands }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-viadeo { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-viadeo-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-viadeo-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-viadeo }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-snapchat { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-snapchat-ghost { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-snapchat-ghost { #{$fa-icon-property}: unquote("\"#{ $fa-var-snapchat }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-snapchat-square { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-snapchat-square { #{$fa-icon-property}: unquote("\"#{ $fa-var-square-snapchat }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-pied-piper { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-first-order { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-yoast { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-themeisle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus-official { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus-official { #{$fa-icon-property}: unquote("\"#{ $fa-var-google-plus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus-circle { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-google-plus-circle { #{$fa-icon-property}: unquote("\"#{ $fa-var-google-plus }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-font-awesome { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-fa { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-fa { #{$fa-icon-property}: unquote("\"#{ $fa-var-font-awesome }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-handshake-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-handshake-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-handshake }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-envelope-open-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-envelope-open-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-envelope-open }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-linode { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-address-book-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-address-book-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-address-book }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-vcard { #{$fa-icon-property}: unquote("\"#{ $fa-var-address-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-address-card-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-address-card-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-address-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-vcard-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-vcard-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-address-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-user-circle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-user-circle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-circle-user }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-user-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-user-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-user }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-id-badge { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-drivers-license { #{$fa-icon-property}: unquote("\"#{ $fa-var-id-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-id-card-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-id-card-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-id-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-drivers-license-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-drivers-license-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-id-card }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-quora { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-free-code-camp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-telegram { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-thermometer-4 { #{$fa-icon-property}: unquote("\"#{ $fa-var-temperature-full }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thermometer { #{$fa-icon-property}: unquote("\"#{ $fa-var-temperature-full }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thermometer-3 { #{$fa-icon-property}: unquote("\"#{ $fa-var-temperature-three-quarters }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thermometer-2 { #{$fa-icon-property}: unquote("\"#{ $fa-var-temperature-half }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thermometer-1 { #{$fa-icon-property}: unquote("\"#{ $fa-var-temperature-quarter }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-thermometer-0 { #{$fa-icon-property}: unquote("\"#{ $fa-var-temperature-empty }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bathtub { #{$fa-icon-property}: unquote("\"#{ $fa-var-bath }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-s15 { #{$fa-icon-property}: unquote("\"#{ $fa-var-bath }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-window-maximize { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-window-restore { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-times-rectangle { #{$fa-icon-property}: unquote("\"#{ $fa-var-rectangle-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-window-close-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-window-close-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-rectangle-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-times-rectangle-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-times-rectangle-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-rectangle-xmark }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-bandcamp { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-grav { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-etsy { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-imdb { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-ravelry { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-eercast { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-eercast { #{$fa-icon-property}: unquote("\"#{ $fa-var-sellcast }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-snowflake-o { + font-family: 'Font Awesome 6 Free'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-snowflake-o { #{$fa-icon-property}: unquote("\"#{ $fa-var-snowflake }\""); } +.#{$fa-css-prefix}.#{$fa-css-prefix}-superpowers { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-wpexplorer { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} +.#{$fa-css-prefix}.#{$fa-css-prefix}-meetup { + font-family: 'Font Awesome 6 Brands'; + font-weight: 400; +} diff --git a/src/sass/fontawesome/_sizing.scss b/src/sass/fontawesome/_sizing.scss new file mode 100644 index 0000000..e171e7d --- /dev/null +++ b/src/sass/fontawesome/_sizing.scss @@ -0,0 +1,16 @@ +// sizing icons +// ------------------------- + +// literal magnification scale +@for $i from 1 through 10 { + .#{$fa-css-prefix}-#{$i}x { + font-size: $i * 1em; + } +} + +// step-based scale (with alignment) +@each $size, $value in $fa-sizes { + .#{$fa-css-prefix}-#{$size} { + @include fa-size($value); + } +} diff --git a/src/sass/fontawesome/_stacked.scss b/src/sass/fontawesome/_stacked.scss new file mode 100644 index 0000000..d9a9d4e --- /dev/null +++ b/src/sass/fontawesome/_stacked.scss @@ -0,0 +1,32 @@ +// stacking icons +// ------------------------- + +.#{$fa-css-prefix}-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: $fa-stack-vertical-align; + width: $fa-stack-width; +} + +.#{$fa-css-prefix}-stack-1x, +.#{$fa-css-prefix}-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: var(--#{$fa-css-prefix}-stack-z-index, #{$fa-stack-z-index}); +} + +.#{$fa-css-prefix}-stack-1x { + line-height: inherit; +} + +.#{$fa-css-prefix}-stack-2x { + font-size: 2em; +} + +.#{$fa-css-prefix}-inverse { + color: var(--#{$fa-css-prefix}-inverse, #{$fa-inverse}); +} diff --git a/src/sass/fontawesome/_variables.scss b/src/sass/fontawesome/_variables.scss new file mode 100644 index 0000000..87d19d3 --- /dev/null +++ b/src/sass/fontawesome/_variables.scss @@ -0,0 +1,5044 @@ +// variables +// -------------------------- + +$fa-css-prefix : fa !default; +$fa-style : 900 !default; +$fa-style-family : "Font Awesome 6 Free" !default; + +$fa-icon-property : --fa; +$fa-duotone-icon-property : --fa--fa; + +$fa-display : inline-block !default; + +$fa-fw-width : fa-divide(20em, 16) !default; +$fa-inverse : #fff !default; + +$fa-border-color : #eee !default; +$fa-border-padding : .2em .25em .15em !default; +$fa-border-radius : .1em !default; +$fa-border-style : solid !default; +$fa-border-width : .08em !default; + +$fa-size-scale-2xs : 10 !default; +$fa-size-scale-xs : 12 !default; +$fa-size-scale-sm : 14 !default; +$fa-size-scale-base : 16 !default; +$fa-size-scale-lg : 20 !default; +$fa-size-scale-xl : 24 !default; +$fa-size-scale-2xl : 32 !default; + +$fa-sizes: ( + "2xs" : $fa-size-scale-2xs, + "xs" : $fa-size-scale-xs, + "sm" : $fa-size-scale-sm, + "lg" : $fa-size-scale-lg, + "xl" : $fa-size-scale-xl, + "2xl" : $fa-size-scale-2xl +) !default; + +$fa-li-width : 2em !default; +$fa-li-margin : $fa-li-width * fa-divide(5, 4) !default; + +$fa-pull-margin : .3em !default; + +$fa-primary-opacity : 1 !default; +$fa-secondary-opacity : .4 !default; + +$fa-stack-vertical-align : middle !default; +$fa-stack-width : ($fa-fw-width * 2) !default; +$fa-stack-z-index : auto !default; + +$fa-font-display : block !default; +$fa-font-path : "../../webfonts" !default; + +$fa-var-0: \30; +$fa-var-1: \31; +$fa-var-2: \32; +$fa-var-3: \33; +$fa-var-4: \34; +$fa-var-5: \35; +$fa-var-6: \36; +$fa-var-7: \37; +$fa-var-8: \38; +$fa-var-9: \39; +$fa-var-fill-drip: \f576; +$fa-var-arrows-to-circle: \e4bd; +$fa-var-circle-chevron-right: \f138; +$fa-var-chevron-circle-right: \f138; +$fa-var-at: \40; +$fa-var-trash-can: \f2ed; +$fa-var-trash-alt: \f2ed; +$fa-var-text-height: \f034; +$fa-var-user-xmark: \f235; +$fa-var-user-times: \f235; +$fa-var-stethoscope: \f0f1; +$fa-var-message: \f27a; +$fa-var-comment-alt: \f27a; +$fa-var-info: \f129; +$fa-var-down-left-and-up-right-to-center: \f422; +$fa-var-compress-alt: \f422; +$fa-var-explosion: \e4e9; +$fa-var-file-lines: \f15c; +$fa-var-file-alt: \f15c; +$fa-var-file-text: \f15c; +$fa-var-wave-square: \f83e; +$fa-var-ring: \f70b; +$fa-var-building-un: \e4d9; +$fa-var-dice-three: \f527; +$fa-var-calendar-days: \f073; +$fa-var-calendar-alt: \f073; +$fa-var-anchor-circle-check: \e4aa; +$fa-var-building-circle-arrow-right: \e4d1; +$fa-var-volleyball: \f45f; +$fa-var-volleyball-ball: \f45f; +$fa-var-arrows-up-to-line: \e4c2; +$fa-var-sort-down: \f0dd; +$fa-var-sort-desc: \f0dd; +$fa-var-circle-minus: \f056; +$fa-var-minus-circle: \f056; +$fa-var-door-open: \f52b; +$fa-var-right-from-bracket: \f2f5; +$fa-var-sign-out-alt: \f2f5; +$fa-var-atom: \f5d2; +$fa-var-soap: \e06e; +$fa-var-icons: \f86d; +$fa-var-heart-music-camera-bolt: \f86d; +$fa-var-microphone-lines-slash: \f539; +$fa-var-microphone-alt-slash: \f539; +$fa-var-bridge-circle-check: \e4c9; +$fa-var-pump-medical: \e06a; +$fa-var-fingerprint: \f577; +$fa-var-hand-point-right: \f0a4; +$fa-var-magnifying-glass-location: \f689; +$fa-var-search-location: \f689; +$fa-var-forward-step: \f051; +$fa-var-step-forward: \f051; +$fa-var-face-smile-beam: \f5b8; +$fa-var-smile-beam: \f5b8; +$fa-var-flag-checkered: \f11e; +$fa-var-football: \f44e; +$fa-var-football-ball: \f44e; +$fa-var-school-circle-exclamation: \e56c; +$fa-var-crop: \f125; +$fa-var-angles-down: \f103; +$fa-var-angle-double-down: \f103; +$fa-var-users-rectangle: \e594; +$fa-var-people-roof: \e537; +$fa-var-people-line: \e534; +$fa-var-beer-mug-empty: \f0fc; +$fa-var-beer: \f0fc; +$fa-var-diagram-predecessor: \e477; +$fa-var-arrow-up-long: \f176; +$fa-var-long-arrow-up: \f176; +$fa-var-fire-flame-simple: \f46a; +$fa-var-burn: \f46a; +$fa-var-person: \f183; +$fa-var-male: \f183; +$fa-var-laptop: \f109; +$fa-var-file-csv: \f6dd; +$fa-var-menorah: \f676; +$fa-var-truck-plane: \e58f; +$fa-var-record-vinyl: \f8d9; +$fa-var-face-grin-stars: \f587; +$fa-var-grin-stars: \f587; +$fa-var-bong: \f55c; +$fa-var-spaghetti-monster-flying: \f67b; +$fa-var-pastafarianism: \f67b; +$fa-var-arrow-down-up-across-line: \e4af; +$fa-var-spoon: \f2e5; +$fa-var-utensil-spoon: \f2e5; +$fa-var-jar-wheat: \e517; +$fa-var-envelopes-bulk: \f674; +$fa-var-mail-bulk: \f674; +$fa-var-file-circle-exclamation: \e4eb; +$fa-var-circle-h: \f47e; +$fa-var-hospital-symbol: \f47e; +$fa-var-pager: \f815; +$fa-var-address-book: \f2b9; +$fa-var-contact-book: \f2b9; +$fa-var-strikethrough: \f0cc; +$fa-var-k: \4b; +$fa-var-landmark-flag: \e51c; +$fa-var-pencil: \f303; +$fa-var-pencil-alt: \f303; +$fa-var-backward: \f04a; +$fa-var-caret-right: \f0da; +$fa-var-comments: \f086; +$fa-var-paste: \f0ea; +$fa-var-file-clipboard: \f0ea; +$fa-var-code-pull-request: \e13c; +$fa-var-clipboard-list: \f46d; +$fa-var-truck-ramp-box: \f4de; +$fa-var-truck-loading: \f4de; +$fa-var-user-check: \f4fc; +$fa-var-vial-virus: \e597; +$fa-var-sheet-plastic: \e571; +$fa-var-blog: \f781; +$fa-var-user-ninja: \f504; +$fa-var-person-arrow-up-from-line: \e539; +$fa-var-scroll-torah: \f6a0; +$fa-var-torah: \f6a0; +$fa-var-broom-ball: \f458; +$fa-var-quidditch: \f458; +$fa-var-quidditch-broom-ball: \f458; +$fa-var-toggle-off: \f204; +$fa-var-box-archive: \f187; +$fa-var-archive: \f187; +$fa-var-person-drowning: \e545; +$fa-var-arrow-down-9-1: \f886; +$fa-var-sort-numeric-desc: \f886; +$fa-var-sort-numeric-down-alt: \f886; +$fa-var-face-grin-tongue-squint: \f58a; +$fa-var-grin-tongue-squint: \f58a; +$fa-var-spray-can: \f5bd; +$fa-var-truck-monster: \f63b; +$fa-var-w: \57; +$fa-var-earth-africa: \f57c; +$fa-var-globe-africa: \f57c; +$fa-var-rainbow: \f75b; +$fa-var-circle-notch: \f1ce; +$fa-var-tablet-screen-button: \f3fa; +$fa-var-tablet-alt: \f3fa; +$fa-var-paw: \f1b0; +$fa-var-cloud: \f0c2; +$fa-var-trowel-bricks: \e58a; +$fa-var-face-flushed: \f579; +$fa-var-flushed: \f579; +$fa-var-hospital-user: \f80d; +$fa-var-tent-arrow-left-right: \e57f; +$fa-var-gavel: \f0e3; +$fa-var-legal: \f0e3; +$fa-var-binoculars: \f1e5; +$fa-var-microphone-slash: \f131; +$fa-var-box-tissue: \e05b; +$fa-var-motorcycle: \f21c; +$fa-var-bell-concierge: \f562; +$fa-var-concierge-bell: \f562; +$fa-var-pen-ruler: \f5ae; +$fa-var-pencil-ruler: \f5ae; +$fa-var-people-arrows: \e068; +$fa-var-people-arrows-left-right: \e068; +$fa-var-mars-and-venus-burst: \e523; +$fa-var-square-caret-right: \f152; +$fa-var-caret-square-right: \f152; +$fa-var-scissors: \f0c4; +$fa-var-cut: \f0c4; +$fa-var-sun-plant-wilt: \e57a; +$fa-var-toilets-portable: \e584; +$fa-var-hockey-puck: \f453; +$fa-var-table: \f0ce; +$fa-var-magnifying-glass-arrow-right: \e521; +$fa-var-tachograph-digital: \f566; +$fa-var-digital-tachograph: \f566; +$fa-var-users-slash: \e073; +$fa-var-clover: \e139; +$fa-var-reply: \f3e5; +$fa-var-mail-reply: \f3e5; +$fa-var-star-and-crescent: \f699; +$fa-var-house-fire: \e50c; +$fa-var-square-minus: \f146; +$fa-var-minus-square: \f146; +$fa-var-helicopter: \f533; +$fa-var-compass: \f14e; +$fa-var-square-caret-down: \f150; +$fa-var-caret-square-down: \f150; +$fa-var-file-circle-question: \e4ef; +$fa-var-laptop-code: \f5fc; +$fa-var-swatchbook: \f5c3; +$fa-var-prescription-bottle: \f485; +$fa-var-bars: \f0c9; +$fa-var-navicon: \f0c9; +$fa-var-people-group: \e533; +$fa-var-hourglass-end: \f253; +$fa-var-hourglass-3: \f253; +$fa-var-heart-crack: \f7a9; +$fa-var-heart-broken: \f7a9; +$fa-var-square-up-right: \f360; +$fa-var-external-link-square-alt: \f360; +$fa-var-face-kiss-beam: \f597; +$fa-var-kiss-beam: \f597; +$fa-var-film: \f008; +$fa-var-ruler-horizontal: \f547; +$fa-var-people-robbery: \e536; +$fa-var-lightbulb: \f0eb; +$fa-var-caret-left: \f0d9; +$fa-var-circle-exclamation: \f06a; +$fa-var-exclamation-circle: \f06a; +$fa-var-school-circle-xmark: \e56d; +$fa-var-arrow-right-from-bracket: \f08b; +$fa-var-sign-out: \f08b; +$fa-var-circle-chevron-down: \f13a; +$fa-var-chevron-circle-down: \f13a; +$fa-var-unlock-keyhole: \f13e; +$fa-var-unlock-alt: \f13e; +$fa-var-cloud-showers-heavy: \f740; +$fa-var-headphones-simple: \f58f; +$fa-var-headphones-alt: \f58f; +$fa-var-sitemap: \f0e8; +$fa-var-circle-dollar-to-slot: \f4b9; +$fa-var-donate: \f4b9; +$fa-var-memory: \f538; +$fa-var-road-spikes: \e568; +$fa-var-fire-burner: \e4f1; +$fa-var-flag: \f024; +$fa-var-hanukiah: \f6e6; +$fa-var-feather: \f52d; +$fa-var-volume-low: \f027; +$fa-var-volume-down: \f027; +$fa-var-comment-slash: \f4b3; +$fa-var-cloud-sun-rain: \f743; +$fa-var-compress: \f066; +$fa-var-wheat-awn: \e2cd; +$fa-var-wheat-alt: \e2cd; +$fa-var-ankh: \f644; +$fa-var-hands-holding-child: \e4fa; +$fa-var-asterisk: \2a; +$fa-var-square-check: \f14a; +$fa-var-check-square: \f14a; +$fa-var-peseta-sign: \e221; +$fa-var-heading: \f1dc; +$fa-var-header: \f1dc; +$fa-var-ghost: \f6e2; +$fa-var-list: \f03a; +$fa-var-list-squares: \f03a; +$fa-var-square-phone-flip: \f87b; +$fa-var-phone-square-alt: \f87b; +$fa-var-cart-plus: \f217; +$fa-var-gamepad: \f11b; +$fa-var-circle-dot: \f192; +$fa-var-dot-circle: \f192; +$fa-var-face-dizzy: \f567; +$fa-var-dizzy: \f567; +$fa-var-egg: \f7fb; +$fa-var-house-medical-circle-xmark: \e513; +$fa-var-campground: \f6bb; +$fa-var-folder-plus: \f65e; +$fa-var-futbol: \f1e3; +$fa-var-futbol-ball: \f1e3; +$fa-var-soccer-ball: \f1e3; +$fa-var-paintbrush: \f1fc; +$fa-var-paint-brush: \f1fc; +$fa-var-lock: \f023; +$fa-var-gas-pump: \f52f; +$fa-var-hot-tub-person: \f593; +$fa-var-hot-tub: \f593; +$fa-var-map-location: \f59f; +$fa-var-map-marked: \f59f; +$fa-var-house-flood-water: \e50e; +$fa-var-tree: \f1bb; +$fa-var-bridge-lock: \e4cc; +$fa-var-sack-dollar: \f81d; +$fa-var-pen-to-square: \f044; +$fa-var-edit: \f044; +$fa-var-car-side: \f5e4; +$fa-var-share-nodes: \f1e0; +$fa-var-share-alt: \f1e0; +$fa-var-heart-circle-minus: \e4ff; +$fa-var-hourglass-half: \f252; +$fa-var-hourglass-2: \f252; +$fa-var-microscope: \f610; +$fa-var-sink: \e06d; +$fa-var-bag-shopping: \f290; +$fa-var-shopping-bag: \f290; +$fa-var-arrow-down-z-a: \f881; +$fa-var-sort-alpha-desc: \f881; +$fa-var-sort-alpha-down-alt: \f881; +$fa-var-mitten: \f7b5; +$fa-var-person-rays: \e54d; +$fa-var-users: \f0c0; +$fa-var-eye-slash: \f070; +$fa-var-flask-vial: \e4f3; +$fa-var-hand: \f256; +$fa-var-hand-paper: \f256; +$fa-var-om: \f679; +$fa-var-worm: \e599; +$fa-var-house-circle-xmark: \e50b; +$fa-var-plug: \f1e6; +$fa-var-chevron-up: \f077; +$fa-var-hand-spock: \f259; +$fa-var-stopwatch: \f2f2; +$fa-var-face-kiss: \f596; +$fa-var-kiss: \f596; +$fa-var-bridge-circle-xmark: \e4cb; +$fa-var-face-grin-tongue: \f589; +$fa-var-grin-tongue: \f589; +$fa-var-chess-bishop: \f43a; +$fa-var-face-grin-wink: \f58c; +$fa-var-grin-wink: \f58c; +$fa-var-ear-deaf: \f2a4; +$fa-var-deaf: \f2a4; +$fa-var-deafness: \f2a4; +$fa-var-hard-of-hearing: \f2a4; +$fa-var-road-circle-check: \e564; +$fa-var-dice-five: \f523; +$fa-var-square-rss: \f143; +$fa-var-rss-square: \f143; +$fa-var-land-mine-on: \e51b; +$fa-var-i-cursor: \f246; +$fa-var-stamp: \f5bf; +$fa-var-stairs: \e289; +$fa-var-i: \49; +$fa-var-hryvnia-sign: \f6f2; +$fa-var-hryvnia: \f6f2; +$fa-var-pills: \f484; +$fa-var-face-grin-wide: \f581; +$fa-var-grin-alt: \f581; +$fa-var-tooth: \f5c9; +$fa-var-v: \56; +$fa-var-bangladeshi-taka-sign: \e2e6; +$fa-var-bicycle: \f206; +$fa-var-staff-snake: \e579; +$fa-var-rod-asclepius: \e579; +$fa-var-rod-snake: \e579; +$fa-var-staff-aesculapius: \e579; +$fa-var-head-side-cough-slash: \e062; +$fa-var-truck-medical: \f0f9; +$fa-var-ambulance: \f0f9; +$fa-var-wheat-awn-circle-exclamation: \e598; +$fa-var-snowman: \f7d0; +$fa-var-mortar-pestle: \f5a7; +$fa-var-road-barrier: \e562; +$fa-var-school: \f549; +$fa-var-igloo: \f7ae; +$fa-var-joint: \f595; +$fa-var-angle-right: \f105; +$fa-var-horse: \f6f0; +$fa-var-q: \51; +$fa-var-g: \47; +$fa-var-notes-medical: \f481; +$fa-var-temperature-half: \f2c9; +$fa-var-temperature-2: \f2c9; +$fa-var-thermometer-2: \f2c9; +$fa-var-thermometer-half: \f2c9; +$fa-var-dong-sign: \e169; +$fa-var-capsules: \f46b; +$fa-var-poo-storm: \f75a; +$fa-var-poo-bolt: \f75a; +$fa-var-face-frown-open: \f57a; +$fa-var-frown-open: \f57a; +$fa-var-hand-point-up: \f0a6; +$fa-var-money-bill: \f0d6; +$fa-var-bookmark: \f02e; +$fa-var-align-justify: \f039; +$fa-var-umbrella-beach: \f5ca; +$fa-var-helmet-un: \e503; +$fa-var-bullseye: \f140; +$fa-var-bacon: \f7e5; +$fa-var-hand-point-down: \f0a7; +$fa-var-arrow-up-from-bracket: \e09a; +$fa-var-folder: \f07b; +$fa-var-folder-blank: \f07b; +$fa-var-file-waveform: \f478; +$fa-var-file-medical-alt: \f478; +$fa-var-radiation: \f7b9; +$fa-var-chart-simple: \e473; +$fa-var-mars-stroke: \f229; +$fa-var-vial: \f492; +$fa-var-gauge: \f624; +$fa-var-dashboard: \f624; +$fa-var-gauge-med: \f624; +$fa-var-tachometer-alt-average: \f624; +$fa-var-wand-magic-sparkles: \e2ca; +$fa-var-magic-wand-sparkles: \e2ca; +$fa-var-e: \45; +$fa-var-pen-clip: \f305; +$fa-var-pen-alt: \f305; +$fa-var-bridge-circle-exclamation: \e4ca; +$fa-var-user: \f007; +$fa-var-school-circle-check: \e56b; +$fa-var-dumpster: \f793; +$fa-var-van-shuttle: \f5b6; +$fa-var-shuttle-van: \f5b6; +$fa-var-building-user: \e4da; +$fa-var-square-caret-left: \f191; +$fa-var-caret-square-left: \f191; +$fa-var-highlighter: \f591; +$fa-var-key: \f084; +$fa-var-bullhorn: \f0a1; +$fa-var-globe: \f0ac; +$fa-var-synagogue: \f69b; +$fa-var-person-half-dress: \e548; +$fa-var-road-bridge: \e563; +$fa-var-location-arrow: \f124; +$fa-var-c: \43; +$fa-var-tablet-button: \f10a; +$fa-var-building-lock: \e4d6; +$fa-var-pizza-slice: \f818; +$fa-var-money-bill-wave: \f53a; +$fa-var-chart-area: \f1fe; +$fa-var-area-chart: \f1fe; +$fa-var-house-flag: \e50d; +$fa-var-person-circle-minus: \e540; +$fa-var-ban: \f05e; +$fa-var-cancel: \f05e; +$fa-var-camera-rotate: \e0d8; +$fa-var-spray-can-sparkles: \f5d0; +$fa-var-air-freshener: \f5d0; +$fa-var-star: \f005; +$fa-var-repeat: \f363; +$fa-var-cross: \f654; +$fa-var-box: \f466; +$fa-var-venus-mars: \f228; +$fa-var-arrow-pointer: \f245; +$fa-var-mouse-pointer: \f245; +$fa-var-maximize: \f31e; +$fa-var-expand-arrows-alt: \f31e; +$fa-var-charging-station: \f5e7; +$fa-var-shapes: \f61f; +$fa-var-triangle-circle-square: \f61f; +$fa-var-shuffle: \f074; +$fa-var-random: \f074; +$fa-var-person-running: \f70c; +$fa-var-running: \f70c; +$fa-var-mobile-retro: \e527; +$fa-var-grip-lines-vertical: \f7a5; +$fa-var-spider: \f717; +$fa-var-hands-bound: \e4f9; +$fa-var-file-invoice-dollar: \f571; +$fa-var-plane-circle-exclamation: \e556; +$fa-var-x-ray: \f497; +$fa-var-spell-check: \f891; +$fa-var-slash: \f715; +$fa-var-computer-mouse: \f8cc; +$fa-var-mouse: \f8cc; +$fa-var-arrow-right-to-bracket: \f090; +$fa-var-sign-in: \f090; +$fa-var-shop-slash: \e070; +$fa-var-store-alt-slash: \e070; +$fa-var-server: \f233; +$fa-var-virus-covid-slash: \e4a9; +$fa-var-shop-lock: \e4a5; +$fa-var-hourglass-start: \f251; +$fa-var-hourglass-1: \f251; +$fa-var-blender-phone: \f6b6; +$fa-var-building-wheat: \e4db; +$fa-var-person-breastfeeding: \e53a; +$fa-var-right-to-bracket: \f2f6; +$fa-var-sign-in-alt: \f2f6; +$fa-var-venus: \f221; +$fa-var-passport: \f5ab; +$fa-var-thumbtack-slash: \e68f; +$fa-var-thumb-tack-slash: \e68f; +$fa-var-heart-pulse: \f21e; +$fa-var-heartbeat: \f21e; +$fa-var-people-carry-box: \f4ce; +$fa-var-people-carry: \f4ce; +$fa-var-temperature-high: \f769; +$fa-var-microchip: \f2db; +$fa-var-crown: \f521; +$fa-var-weight-hanging: \f5cd; +$fa-var-xmarks-lines: \e59a; +$fa-var-file-prescription: \f572; +$fa-var-weight-scale: \f496; +$fa-var-weight: \f496; +$fa-var-user-group: \f500; +$fa-var-user-friends: \f500; +$fa-var-arrow-up-a-z: \f15e; +$fa-var-sort-alpha-up: \f15e; +$fa-var-chess-knight: \f441; +$fa-var-face-laugh-squint: \f59b; +$fa-var-laugh-squint: \f59b; +$fa-var-wheelchair: \f193; +$fa-var-circle-arrow-up: \f0aa; +$fa-var-arrow-circle-up: \f0aa; +$fa-var-toggle-on: \f205; +$fa-var-person-walking: \f554; +$fa-var-walking: \f554; +$fa-var-l: \4c; +$fa-var-fire: \f06d; +$fa-var-bed-pulse: \f487; +$fa-var-procedures: \f487; +$fa-var-shuttle-space: \f197; +$fa-var-space-shuttle: \f197; +$fa-var-face-laugh: \f599; +$fa-var-laugh: \f599; +$fa-var-folder-open: \f07c; +$fa-var-heart-circle-plus: \e500; +$fa-var-code-fork: \e13b; +$fa-var-city: \f64f; +$fa-var-microphone-lines: \f3c9; +$fa-var-microphone-alt: \f3c9; +$fa-var-pepper-hot: \f816; +$fa-var-unlock: \f09c; +$fa-var-colon-sign: \e140; +$fa-var-headset: \f590; +$fa-var-store-slash: \e071; +$fa-var-road-circle-xmark: \e566; +$fa-var-user-minus: \f503; +$fa-var-mars-stroke-up: \f22a; +$fa-var-mars-stroke-v: \f22a; +$fa-var-champagne-glasses: \f79f; +$fa-var-glass-cheers: \f79f; +$fa-var-clipboard: \f328; +$fa-var-house-circle-exclamation: \e50a; +$fa-var-file-arrow-up: \f574; +$fa-var-file-upload: \f574; +$fa-var-wifi: \f1eb; +$fa-var-wifi-3: \f1eb; +$fa-var-wifi-strong: \f1eb; +$fa-var-bath: \f2cd; +$fa-var-bathtub: \f2cd; +$fa-var-underline: \f0cd; +$fa-var-user-pen: \f4ff; +$fa-var-user-edit: \f4ff; +$fa-var-signature: \f5b7; +$fa-var-stroopwafel: \f551; +$fa-var-bold: \f032; +$fa-var-anchor-lock: \e4ad; +$fa-var-building-ngo: \e4d7; +$fa-var-manat-sign: \e1d5; +$fa-var-not-equal: \f53e; +$fa-var-border-top-left: \f853; +$fa-var-border-style: \f853; +$fa-var-map-location-dot: \f5a0; +$fa-var-map-marked-alt: \f5a0; +$fa-var-jedi: \f669; +$fa-var-square-poll-vertical: \f681; +$fa-var-poll: \f681; +$fa-var-mug-hot: \f7b6; +$fa-var-car-battery: \f5df; +$fa-var-battery-car: \f5df; +$fa-var-gift: \f06b; +$fa-var-dice-two: \f528; +$fa-var-chess-queen: \f445; +$fa-var-glasses: \f530; +$fa-var-chess-board: \f43c; +$fa-var-building-circle-check: \e4d2; +$fa-var-person-chalkboard: \e53d; +$fa-var-mars-stroke-right: \f22b; +$fa-var-mars-stroke-h: \f22b; +$fa-var-hand-back-fist: \f255; +$fa-var-hand-rock: \f255; +$fa-var-square-caret-up: \f151; +$fa-var-caret-square-up: \f151; +$fa-var-cloud-showers-water: \e4e4; +$fa-var-chart-bar: \f080; +$fa-var-bar-chart: \f080; +$fa-var-hands-bubbles: \e05e; +$fa-var-hands-wash: \e05e; +$fa-var-less-than-equal: \f537; +$fa-var-train: \f238; +$fa-var-eye-low-vision: \f2a8; +$fa-var-low-vision: \f2a8; +$fa-var-crow: \f520; +$fa-var-sailboat: \e445; +$fa-var-window-restore: \f2d2; +$fa-var-square-plus: \f0fe; +$fa-var-plus-square: \f0fe; +$fa-var-torii-gate: \f6a1; +$fa-var-frog: \f52e; +$fa-var-bucket: \e4cf; +$fa-var-image: \f03e; +$fa-var-microphone: \f130; +$fa-var-cow: \f6c8; +$fa-var-caret-up: \f0d8; +$fa-var-screwdriver: \f54a; +$fa-var-folder-closed: \e185; +$fa-var-house-tsunami: \e515; +$fa-var-square-nfi: \e576; +$fa-var-arrow-up-from-ground-water: \e4b5; +$fa-var-martini-glass: \f57b; +$fa-var-glass-martini-alt: \f57b; +$fa-var-square-binary: \e69b; +$fa-var-rotate-left: \f2ea; +$fa-var-rotate-back: \f2ea; +$fa-var-rotate-backward: \f2ea; +$fa-var-undo-alt: \f2ea; +$fa-var-table-columns: \f0db; +$fa-var-columns: \f0db; +$fa-var-lemon: \f094; +$fa-var-head-side-mask: \e063; +$fa-var-handshake: \f2b5; +$fa-var-gem: \f3a5; +$fa-var-dolly: \f472; +$fa-var-dolly-box: \f472; +$fa-var-smoking: \f48d; +$fa-var-minimize: \f78c; +$fa-var-compress-arrows-alt: \f78c; +$fa-var-monument: \f5a6; +$fa-var-snowplow: \f7d2; +$fa-var-angles-right: \f101; +$fa-var-angle-double-right: \f101; +$fa-var-cannabis: \f55f; +$fa-var-circle-play: \f144; +$fa-var-play-circle: \f144; +$fa-var-tablets: \f490; +$fa-var-ethernet: \f796; +$fa-var-euro-sign: \f153; +$fa-var-eur: \f153; +$fa-var-euro: \f153; +$fa-var-chair: \f6c0; +$fa-var-circle-check: \f058; +$fa-var-check-circle: \f058; +$fa-var-circle-stop: \f28d; +$fa-var-stop-circle: \f28d; +$fa-var-compass-drafting: \f568; +$fa-var-drafting-compass: \f568; +$fa-var-plate-wheat: \e55a; +$fa-var-icicles: \f7ad; +$fa-var-person-shelter: \e54f; +$fa-var-neuter: \f22c; +$fa-var-id-badge: \f2c1; +$fa-var-marker: \f5a1; +$fa-var-face-laugh-beam: \f59a; +$fa-var-laugh-beam: \f59a; +$fa-var-helicopter-symbol: \e502; +$fa-var-universal-access: \f29a; +$fa-var-circle-chevron-up: \f139; +$fa-var-chevron-circle-up: \f139; +$fa-var-lari-sign: \e1c8; +$fa-var-volcano: \f770; +$fa-var-person-walking-dashed-line-arrow-right: \e553; +$fa-var-sterling-sign: \f154; +$fa-var-gbp: \f154; +$fa-var-pound-sign: \f154; +$fa-var-viruses: \e076; +$fa-var-square-person-confined: \e577; +$fa-var-user-tie: \f508; +$fa-var-arrow-down-long: \f175; +$fa-var-long-arrow-down: \f175; +$fa-var-tent-arrow-down-to-line: \e57e; +$fa-var-certificate: \f0a3; +$fa-var-reply-all: \f122; +$fa-var-mail-reply-all: \f122; +$fa-var-suitcase: \f0f2; +$fa-var-person-skating: \f7c5; +$fa-var-skating: \f7c5; +$fa-var-filter-circle-dollar: \f662; +$fa-var-funnel-dollar: \f662; +$fa-var-camera-retro: \f083; +$fa-var-circle-arrow-down: \f0ab; +$fa-var-arrow-circle-down: \f0ab; +$fa-var-file-import: \f56f; +$fa-var-arrow-right-to-file: \f56f; +$fa-var-square-arrow-up-right: \f14c; +$fa-var-external-link-square: \f14c; +$fa-var-box-open: \f49e; +$fa-var-scroll: \f70e; +$fa-var-spa: \f5bb; +$fa-var-location-pin-lock: \e51f; +$fa-var-pause: \f04c; +$fa-var-hill-avalanche: \e507; +$fa-var-temperature-empty: \f2cb; +$fa-var-temperature-0: \f2cb; +$fa-var-thermometer-0: \f2cb; +$fa-var-thermometer-empty: \f2cb; +$fa-var-bomb: \f1e2; +$fa-var-registered: \f25d; +$fa-var-address-card: \f2bb; +$fa-var-contact-card: \f2bb; +$fa-var-vcard: \f2bb; +$fa-var-scale-unbalanced-flip: \f516; +$fa-var-balance-scale-right: \f516; +$fa-var-subscript: \f12c; +$fa-var-diamond-turn-right: \f5eb; +$fa-var-directions: \f5eb; +$fa-var-burst: \e4dc; +$fa-var-house-laptop: \e066; +$fa-var-laptop-house: \e066; +$fa-var-face-tired: \f5c8; +$fa-var-tired: \f5c8; +$fa-var-money-bills: \e1f3; +$fa-var-smog: \f75f; +$fa-var-crutch: \f7f7; +$fa-var-cloud-arrow-up: \f0ee; +$fa-var-cloud-upload: \f0ee; +$fa-var-cloud-upload-alt: \f0ee; +$fa-var-palette: \f53f; +$fa-var-arrows-turn-right: \e4c0; +$fa-var-vest: \e085; +$fa-var-ferry: \e4ea; +$fa-var-arrows-down-to-people: \e4b9; +$fa-var-seedling: \f4d8; +$fa-var-sprout: \f4d8; +$fa-var-left-right: \f337; +$fa-var-arrows-alt-h: \f337; +$fa-var-boxes-packing: \e4c7; +$fa-var-circle-arrow-left: \f0a8; +$fa-var-arrow-circle-left: \f0a8; +$fa-var-group-arrows-rotate: \e4f6; +$fa-var-bowl-food: \e4c6; +$fa-var-candy-cane: \f786; +$fa-var-arrow-down-wide-short: \f160; +$fa-var-sort-amount-asc: \f160; +$fa-var-sort-amount-down: \f160; +$fa-var-cloud-bolt: \f76c; +$fa-var-thunderstorm: \f76c; +$fa-var-text-slash: \f87d; +$fa-var-remove-format: \f87d; +$fa-var-face-smile-wink: \f4da; +$fa-var-smile-wink: \f4da; +$fa-var-file-word: \f1c2; +$fa-var-file-powerpoint: \f1c4; +$fa-var-arrows-left-right: \f07e; +$fa-var-arrows-h: \f07e; +$fa-var-house-lock: \e510; +$fa-var-cloud-arrow-down: \f0ed; +$fa-var-cloud-download: \f0ed; +$fa-var-cloud-download-alt: \f0ed; +$fa-var-children: \e4e1; +$fa-var-chalkboard: \f51b; +$fa-var-blackboard: \f51b; +$fa-var-user-large-slash: \f4fa; +$fa-var-user-alt-slash: \f4fa; +$fa-var-envelope-open: \f2b6; +$fa-var-handshake-simple-slash: \e05f; +$fa-var-handshake-alt-slash: \e05f; +$fa-var-mattress-pillow: \e525; +$fa-var-guarani-sign: \e19a; +$fa-var-arrows-rotate: \f021; +$fa-var-refresh: \f021; +$fa-var-sync: \f021; +$fa-var-fire-extinguisher: \f134; +$fa-var-cruzeiro-sign: \e152; +$fa-var-greater-than-equal: \f532; +$fa-var-shield-halved: \f3ed; +$fa-var-shield-alt: \f3ed; +$fa-var-book-atlas: \f558; +$fa-var-atlas: \f558; +$fa-var-virus: \e074; +$fa-var-envelope-circle-check: \e4e8; +$fa-var-layer-group: \f5fd; +$fa-var-arrows-to-dot: \e4be; +$fa-var-archway: \f557; +$fa-var-heart-circle-check: \e4fd; +$fa-var-house-chimney-crack: \f6f1; +$fa-var-house-damage: \f6f1; +$fa-var-file-zipper: \f1c6; +$fa-var-file-archive: \f1c6; +$fa-var-square: \f0c8; +$fa-var-martini-glass-empty: \f000; +$fa-var-glass-martini: \f000; +$fa-var-couch: \f4b8; +$fa-var-cedi-sign: \e0df; +$fa-var-italic: \f033; +$fa-var-table-cells-column-lock: \e678; +$fa-var-church: \f51d; +$fa-var-comments-dollar: \f653; +$fa-var-democrat: \f747; +$fa-var-z: \5a; +$fa-var-person-skiing: \f7c9; +$fa-var-skiing: \f7c9; +$fa-var-road-lock: \e567; +$fa-var-a: \41; +$fa-var-temperature-arrow-down: \e03f; +$fa-var-temperature-down: \e03f; +$fa-var-feather-pointed: \f56b; +$fa-var-feather-alt: \f56b; +$fa-var-p: \50; +$fa-var-snowflake: \f2dc; +$fa-var-newspaper: \f1ea; +$fa-var-rectangle-ad: \f641; +$fa-var-ad: \f641; +$fa-var-circle-arrow-right: \f0a9; +$fa-var-arrow-circle-right: \f0a9; +$fa-var-filter-circle-xmark: \e17b; +$fa-var-locust: \e520; +$fa-var-sort: \f0dc; +$fa-var-unsorted: \f0dc; +$fa-var-list-ol: \f0cb; +$fa-var-list-1-2: \f0cb; +$fa-var-list-numeric: \f0cb; +$fa-var-person-dress-burst: \e544; +$fa-var-money-check-dollar: \f53d; +$fa-var-money-check-alt: \f53d; +$fa-var-vector-square: \f5cb; +$fa-var-bread-slice: \f7ec; +$fa-var-language: \f1ab; +$fa-var-face-kiss-wink-heart: \f598; +$fa-var-kiss-wink-heart: \f598; +$fa-var-filter: \f0b0; +$fa-var-question: \3f; +$fa-var-file-signature: \f573; +$fa-var-up-down-left-right: \f0b2; +$fa-var-arrows-alt: \f0b2; +$fa-var-house-chimney-user: \e065; +$fa-var-hand-holding-heart: \f4be; +$fa-var-puzzle-piece: \f12e; +$fa-var-money-check: \f53c; +$fa-var-star-half-stroke: \f5c0; +$fa-var-star-half-alt: \f5c0; +$fa-var-code: \f121; +$fa-var-whiskey-glass: \f7a0; +$fa-var-glass-whiskey: \f7a0; +$fa-var-building-circle-exclamation: \e4d3; +$fa-var-magnifying-glass-chart: \e522; +$fa-var-arrow-up-right-from-square: \f08e; +$fa-var-external-link: \f08e; +$fa-var-cubes-stacked: \e4e6; +$fa-var-won-sign: \f159; +$fa-var-krw: \f159; +$fa-var-won: \f159; +$fa-var-virus-covid: \e4a8; +$fa-var-austral-sign: \e0a9; +$fa-var-f: \46; +$fa-var-leaf: \f06c; +$fa-var-road: \f018; +$fa-var-taxi: \f1ba; +$fa-var-cab: \f1ba; +$fa-var-person-circle-plus: \e541; +$fa-var-chart-pie: \f200; +$fa-var-pie-chart: \f200; +$fa-var-bolt-lightning: \e0b7; +$fa-var-sack-xmark: \e56a; +$fa-var-file-excel: \f1c3; +$fa-var-file-contract: \f56c; +$fa-var-fish-fins: \e4f2; +$fa-var-building-flag: \e4d5; +$fa-var-face-grin-beam: \f582; +$fa-var-grin-beam: \f582; +$fa-var-object-ungroup: \f248; +$fa-var-poop: \f619; +$fa-var-location-pin: \f041; +$fa-var-map-marker: \f041; +$fa-var-kaaba: \f66b; +$fa-var-toilet-paper: \f71e; +$fa-var-helmet-safety: \f807; +$fa-var-hard-hat: \f807; +$fa-var-hat-hard: \f807; +$fa-var-eject: \f052; +$fa-var-circle-right: \f35a; +$fa-var-arrow-alt-circle-right: \f35a; +$fa-var-plane-circle-check: \e555; +$fa-var-face-rolling-eyes: \f5a5; +$fa-var-meh-rolling-eyes: \f5a5; +$fa-var-object-group: \f247; +$fa-var-chart-line: \f201; +$fa-var-line-chart: \f201; +$fa-var-mask-ventilator: \e524; +$fa-var-arrow-right: \f061; +$fa-var-signs-post: \f277; +$fa-var-map-signs: \f277; +$fa-var-cash-register: \f788; +$fa-var-person-circle-question: \e542; +$fa-var-h: \48; +$fa-var-tarp: \e57b; +$fa-var-screwdriver-wrench: \f7d9; +$fa-var-tools: \f7d9; +$fa-var-arrows-to-eye: \e4bf; +$fa-var-plug-circle-bolt: \e55b; +$fa-var-heart: \f004; +$fa-var-mars-and-venus: \f224; +$fa-var-house-user: \e1b0; +$fa-var-home-user: \e1b0; +$fa-var-dumpster-fire: \f794; +$fa-var-house-crack: \e3b1; +$fa-var-martini-glass-citrus: \f561; +$fa-var-cocktail: \f561; +$fa-var-face-surprise: \f5c2; +$fa-var-surprise: \f5c2; +$fa-var-bottle-water: \e4c5; +$fa-var-circle-pause: \f28b; +$fa-var-pause-circle: \f28b; +$fa-var-toilet-paper-slash: \e072; +$fa-var-apple-whole: \f5d1; +$fa-var-apple-alt: \f5d1; +$fa-var-kitchen-set: \e51a; +$fa-var-r: \52; +$fa-var-temperature-quarter: \f2ca; +$fa-var-temperature-1: \f2ca; +$fa-var-thermometer-1: \f2ca; +$fa-var-thermometer-quarter: \f2ca; +$fa-var-cube: \f1b2; +$fa-var-bitcoin-sign: \e0b4; +$fa-var-shield-dog: \e573; +$fa-var-solar-panel: \f5ba; +$fa-var-lock-open: \f3c1; +$fa-var-elevator: \e16d; +$fa-var-money-bill-transfer: \e528; +$fa-var-money-bill-trend-up: \e529; +$fa-var-house-flood-water-circle-arrow-right: \e50f; +$fa-var-square-poll-horizontal: \f682; +$fa-var-poll-h: \f682; +$fa-var-circle: \f111; +$fa-var-backward-fast: \f049; +$fa-var-fast-backward: \f049; +$fa-var-recycle: \f1b8; +$fa-var-user-astronaut: \f4fb; +$fa-var-plane-slash: \e069; +$fa-var-trademark: \f25c; +$fa-var-basketball: \f434; +$fa-var-basketball-ball: \f434; +$fa-var-satellite-dish: \f7c0; +$fa-var-circle-up: \f35b; +$fa-var-arrow-alt-circle-up: \f35b; +$fa-var-mobile-screen-button: \f3cd; +$fa-var-mobile-alt: \f3cd; +$fa-var-volume-high: \f028; +$fa-var-volume-up: \f028; +$fa-var-users-rays: \e593; +$fa-var-wallet: \f555; +$fa-var-clipboard-check: \f46c; +$fa-var-file-audio: \f1c7; +$fa-var-burger: \f805; +$fa-var-hamburger: \f805; +$fa-var-wrench: \f0ad; +$fa-var-bugs: \e4d0; +$fa-var-rupee-sign: \f156; +$fa-var-rupee: \f156; +$fa-var-file-image: \f1c5; +$fa-var-circle-question: \f059; +$fa-var-question-circle: \f059; +$fa-var-plane-departure: \f5b0; +$fa-var-handshake-slash: \e060; +$fa-var-book-bookmark: \e0bb; +$fa-var-code-branch: \f126; +$fa-var-hat-cowboy: \f8c0; +$fa-var-bridge: \e4c8; +$fa-var-phone-flip: \f879; +$fa-var-phone-alt: \f879; +$fa-var-truck-front: \e2b7; +$fa-var-cat: \f6be; +$fa-var-anchor-circle-exclamation: \e4ab; +$fa-var-truck-field: \e58d; +$fa-var-route: \f4d7; +$fa-var-clipboard-question: \e4e3; +$fa-var-panorama: \e209; +$fa-var-comment-medical: \f7f5; +$fa-var-teeth-open: \f62f; +$fa-var-file-circle-minus: \e4ed; +$fa-var-tags: \f02c; +$fa-var-wine-glass: \f4e3; +$fa-var-forward-fast: \f050; +$fa-var-fast-forward: \f050; +$fa-var-face-meh-blank: \f5a4; +$fa-var-meh-blank: \f5a4; +$fa-var-square-parking: \f540; +$fa-var-parking: \f540; +$fa-var-house-signal: \e012; +$fa-var-bars-progress: \f828; +$fa-var-tasks-alt: \f828; +$fa-var-faucet-drip: \e006; +$fa-var-cart-flatbed: \f474; +$fa-var-dolly-flatbed: \f474; +$fa-var-ban-smoking: \f54d; +$fa-var-smoking-ban: \f54d; +$fa-var-terminal: \f120; +$fa-var-mobile-button: \f10b; +$fa-var-house-medical-flag: \e514; +$fa-var-basket-shopping: \f291; +$fa-var-shopping-basket: \f291; +$fa-var-tape: \f4db; +$fa-var-bus-simple: \f55e; +$fa-var-bus-alt: \f55e; +$fa-var-eye: \f06e; +$fa-var-face-sad-cry: \f5b3; +$fa-var-sad-cry: \f5b3; +$fa-var-audio-description: \f29e; +$fa-var-person-military-to-person: \e54c; +$fa-var-file-shield: \e4f0; +$fa-var-user-slash: \f506; +$fa-var-pen: \f304; +$fa-var-tower-observation: \e586; +$fa-var-file-code: \f1c9; +$fa-var-signal: \f012; +$fa-var-signal-5: \f012; +$fa-var-signal-perfect: \f012; +$fa-var-bus: \f207; +$fa-var-heart-circle-xmark: \e501; +$fa-var-house-chimney: \e3af; +$fa-var-home-lg: \e3af; +$fa-var-window-maximize: \f2d0; +$fa-var-face-frown: \f119; +$fa-var-frown: \f119; +$fa-var-prescription: \f5b1; +$fa-var-shop: \f54f; +$fa-var-store-alt: \f54f; +$fa-var-floppy-disk: \f0c7; +$fa-var-save: \f0c7; +$fa-var-vihara: \f6a7; +$fa-var-scale-unbalanced: \f515; +$fa-var-balance-scale-left: \f515; +$fa-var-sort-up: \f0de; +$fa-var-sort-asc: \f0de; +$fa-var-comment-dots: \f4ad; +$fa-var-commenting: \f4ad; +$fa-var-plant-wilt: \e5aa; +$fa-var-diamond: \f219; +$fa-var-face-grin-squint: \f585; +$fa-var-grin-squint: \f585; +$fa-var-hand-holding-dollar: \f4c0; +$fa-var-hand-holding-usd: \f4c0; +$fa-var-chart-diagram: \e695; +$fa-var-bacterium: \e05a; +$fa-var-hand-pointer: \f25a; +$fa-var-drum-steelpan: \f56a; +$fa-var-hand-scissors: \f257; +$fa-var-hands-praying: \f684; +$fa-var-praying-hands: \f684; +$fa-var-arrow-rotate-right: \f01e; +$fa-var-arrow-right-rotate: \f01e; +$fa-var-arrow-rotate-forward: \f01e; +$fa-var-redo: \f01e; +$fa-var-biohazard: \f780; +$fa-var-location-crosshairs: \f601; +$fa-var-location: \f601; +$fa-var-mars-double: \f227; +$fa-var-child-dress: \e59c; +$fa-var-users-between-lines: \e591; +$fa-var-lungs-virus: \e067; +$fa-var-face-grin-tears: \f588; +$fa-var-grin-tears: \f588; +$fa-var-phone: \f095; +$fa-var-calendar-xmark: \f273; +$fa-var-calendar-times: \f273; +$fa-var-child-reaching: \e59d; +$fa-var-head-side-virus: \e064; +$fa-var-user-gear: \f4fe; +$fa-var-user-cog: \f4fe; +$fa-var-arrow-up-1-9: \f163; +$fa-var-sort-numeric-up: \f163; +$fa-var-door-closed: \f52a; +$fa-var-shield-virus: \e06c; +$fa-var-dice-six: \f526; +$fa-var-mosquito-net: \e52c; +$fa-var-file-fragment: \e697; +$fa-var-bridge-water: \e4ce; +$fa-var-person-booth: \f756; +$fa-var-text-width: \f035; +$fa-var-hat-wizard: \f6e8; +$fa-var-pen-fancy: \f5ac; +$fa-var-person-digging: \f85e; +$fa-var-digging: \f85e; +$fa-var-trash: \f1f8; +$fa-var-gauge-simple: \f629; +$fa-var-gauge-simple-med: \f629; +$fa-var-tachometer-average: \f629; +$fa-var-book-medical: \f7e6; +$fa-var-poo: \f2fe; +$fa-var-quote-right: \f10e; +$fa-var-quote-right-alt: \f10e; +$fa-var-shirt: \f553; +$fa-var-t-shirt: \f553; +$fa-var-tshirt: \f553; +$fa-var-cubes: \f1b3; +$fa-var-divide: \f529; +$fa-var-tenge-sign: \f7d7; +$fa-var-tenge: \f7d7; +$fa-var-headphones: \f025; +$fa-var-hands-holding: \f4c2; +$fa-var-hands-clapping: \e1a8; +$fa-var-republican: \f75e; +$fa-var-arrow-left: \f060; +$fa-var-person-circle-xmark: \e543; +$fa-var-ruler: \f545; +$fa-var-align-left: \f036; +$fa-var-dice-d6: \f6d1; +$fa-var-restroom: \f7bd; +$fa-var-j: \4a; +$fa-var-users-viewfinder: \e595; +$fa-var-file-video: \f1c8; +$fa-var-up-right-from-square: \f35d; +$fa-var-external-link-alt: \f35d; +$fa-var-table-cells: \f00a; +$fa-var-th: \f00a; +$fa-var-file-pdf: \f1c1; +$fa-var-book-bible: \f647; +$fa-var-bible: \f647; +$fa-var-o: \4f; +$fa-var-suitcase-medical: \f0fa; +$fa-var-medkit: \f0fa; +$fa-var-user-secret: \f21b; +$fa-var-otter: \f700; +$fa-var-person-dress: \f182; +$fa-var-female: \f182; +$fa-var-comment-dollar: \f651; +$fa-var-business-time: \f64a; +$fa-var-briefcase-clock: \f64a; +$fa-var-table-cells-large: \f009; +$fa-var-th-large: \f009; +$fa-var-book-tanakh: \f827; +$fa-var-tanakh: \f827; +$fa-var-phone-volume: \f2a0; +$fa-var-volume-control-phone: \f2a0; +$fa-var-hat-cowboy-side: \f8c1; +$fa-var-clipboard-user: \f7f3; +$fa-var-child: \f1ae; +$fa-var-lira-sign: \f195; +$fa-var-satellite: \f7bf; +$fa-var-plane-lock: \e558; +$fa-var-tag: \f02b; +$fa-var-comment: \f075; +$fa-var-cake-candles: \f1fd; +$fa-var-birthday-cake: \f1fd; +$fa-var-cake: \f1fd; +$fa-var-envelope: \f0e0; +$fa-var-angles-up: \f102; +$fa-var-angle-double-up: \f102; +$fa-var-paperclip: \f0c6; +$fa-var-arrow-right-to-city: \e4b3; +$fa-var-ribbon: \f4d6; +$fa-var-lungs: \f604; +$fa-var-arrow-up-9-1: \f887; +$fa-var-sort-numeric-up-alt: \f887; +$fa-var-litecoin-sign: \e1d3; +$fa-var-border-none: \f850; +$fa-var-circle-nodes: \e4e2; +$fa-var-parachute-box: \f4cd; +$fa-var-indent: \f03c; +$fa-var-truck-field-un: \e58e; +$fa-var-hourglass: \f254; +$fa-var-hourglass-empty: \f254; +$fa-var-mountain: \f6fc; +$fa-var-user-doctor: \f0f0; +$fa-var-user-md: \f0f0; +$fa-var-circle-info: \f05a; +$fa-var-info-circle: \f05a; +$fa-var-cloud-meatball: \f73b; +$fa-var-camera: \f030; +$fa-var-camera-alt: \f030; +$fa-var-square-virus: \e578; +$fa-var-meteor: \f753; +$fa-var-car-on: \e4dd; +$fa-var-sleigh: \f7cc; +$fa-var-arrow-down-1-9: \f162; +$fa-var-sort-numeric-asc: \f162; +$fa-var-sort-numeric-down: \f162; +$fa-var-hand-holding-droplet: \f4c1; +$fa-var-hand-holding-water: \f4c1; +$fa-var-water: \f773; +$fa-var-calendar-check: \f274; +$fa-var-braille: \f2a1; +$fa-var-prescription-bottle-medical: \f486; +$fa-var-prescription-bottle-alt: \f486; +$fa-var-landmark: \f66f; +$fa-var-truck: \f0d1; +$fa-var-crosshairs: \f05b; +$fa-var-person-cane: \e53c; +$fa-var-tent: \e57d; +$fa-var-vest-patches: \e086; +$fa-var-check-double: \f560; +$fa-var-arrow-down-a-z: \f15d; +$fa-var-sort-alpha-asc: \f15d; +$fa-var-sort-alpha-down: \f15d; +$fa-var-money-bill-wheat: \e52a; +$fa-var-cookie: \f563; +$fa-var-arrow-rotate-left: \f0e2; +$fa-var-arrow-left-rotate: \f0e2; +$fa-var-arrow-rotate-back: \f0e2; +$fa-var-arrow-rotate-backward: \f0e2; +$fa-var-undo: \f0e2; +$fa-var-hard-drive: \f0a0; +$fa-var-hdd: \f0a0; +$fa-var-face-grin-squint-tears: \f586; +$fa-var-grin-squint-tears: \f586; +$fa-var-dumbbell: \f44b; +$fa-var-rectangle-list: \f022; +$fa-var-list-alt: \f022; +$fa-var-tarp-droplet: \e57c; +$fa-var-house-medical-circle-check: \e511; +$fa-var-person-skiing-nordic: \f7ca; +$fa-var-skiing-nordic: \f7ca; +$fa-var-calendar-plus: \f271; +$fa-var-plane-arrival: \f5af; +$fa-var-circle-left: \f359; +$fa-var-arrow-alt-circle-left: \f359; +$fa-var-train-subway: \f239; +$fa-var-subway: \f239; +$fa-var-chart-gantt: \e0e4; +$fa-var-indian-rupee-sign: \e1bc; +$fa-var-indian-rupee: \e1bc; +$fa-var-inr: \e1bc; +$fa-var-crop-simple: \f565; +$fa-var-crop-alt: \f565; +$fa-var-money-bill-1: \f3d1; +$fa-var-money-bill-alt: \f3d1; +$fa-var-left-long: \f30a; +$fa-var-long-arrow-alt-left: \f30a; +$fa-var-dna: \f471; +$fa-var-virus-slash: \e075; +$fa-var-minus: \f068; +$fa-var-subtract: \f068; +$fa-var-chess: \f439; +$fa-var-arrow-left-long: \f177; +$fa-var-long-arrow-left: \f177; +$fa-var-plug-circle-check: \e55c; +$fa-var-street-view: \f21d; +$fa-var-franc-sign: \e18f; +$fa-var-volume-off: \f026; +$fa-var-hands-asl-interpreting: \f2a3; +$fa-var-american-sign-language-interpreting: \f2a3; +$fa-var-asl-interpreting: \f2a3; +$fa-var-hands-american-sign-language-interpreting: \f2a3; +$fa-var-gear: \f013; +$fa-var-cog: \f013; +$fa-var-droplet-slash: \f5c7; +$fa-var-tint-slash: \f5c7; +$fa-var-mosque: \f678; +$fa-var-mosquito: \e52b; +$fa-var-star-of-david: \f69a; +$fa-var-person-military-rifle: \e54b; +$fa-var-cart-shopping: \f07a; +$fa-var-shopping-cart: \f07a; +$fa-var-vials: \f493; +$fa-var-plug-circle-plus: \e55f; +$fa-var-place-of-worship: \f67f; +$fa-var-grip-vertical: \f58e; +$fa-var-hexagon-nodes: \e699; +$fa-var-arrow-turn-up: \f148; +$fa-var-level-up: \f148; +$fa-var-u: \55; +$fa-var-square-root-variable: \f698; +$fa-var-square-root-alt: \f698; +$fa-var-clock: \f017; +$fa-var-clock-four: \f017; +$fa-var-backward-step: \f048; +$fa-var-step-backward: \f048; +$fa-var-pallet: \f482; +$fa-var-faucet: \e005; +$fa-var-baseball-bat-ball: \f432; +$fa-var-s: \53; +$fa-var-timeline: \e29c; +$fa-var-keyboard: \f11c; +$fa-var-caret-down: \f0d7; +$fa-var-house-chimney-medical: \f7f2; +$fa-var-clinic-medical: \f7f2; +$fa-var-temperature-three-quarters: \f2c8; +$fa-var-temperature-3: \f2c8; +$fa-var-thermometer-3: \f2c8; +$fa-var-thermometer-three-quarters: \f2c8; +$fa-var-mobile-screen: \f3cf; +$fa-var-mobile-android-alt: \f3cf; +$fa-var-plane-up: \e22d; +$fa-var-piggy-bank: \f4d3; +$fa-var-battery-half: \f242; +$fa-var-battery-3: \f242; +$fa-var-mountain-city: \e52e; +$fa-var-coins: \f51e; +$fa-var-khanda: \f66d; +$fa-var-sliders: \f1de; +$fa-var-sliders-h: \f1de; +$fa-var-folder-tree: \f802; +$fa-var-network-wired: \f6ff; +$fa-var-map-pin: \f276; +$fa-var-hamsa: \f665; +$fa-var-cent-sign: \e3f5; +$fa-var-flask: \f0c3; +$fa-var-person-pregnant: \e31e; +$fa-var-wand-sparkles: \f72b; +$fa-var-ellipsis-vertical: \f142; +$fa-var-ellipsis-v: \f142; +$fa-var-ticket: \f145; +$fa-var-power-off: \f011; +$fa-var-right-long: \f30b; +$fa-var-long-arrow-alt-right: \f30b; +$fa-var-flag-usa: \f74d; +$fa-var-laptop-file: \e51d; +$fa-var-tty: \f1e4; +$fa-var-teletype: \f1e4; +$fa-var-diagram-next: \e476; +$fa-var-person-rifle: \e54e; +$fa-var-house-medical-circle-exclamation: \e512; +$fa-var-closed-captioning: \f20a; +$fa-var-person-hiking: \f6ec; +$fa-var-hiking: \f6ec; +$fa-var-venus-double: \f226; +$fa-var-images: \f302; +$fa-var-calculator: \f1ec; +$fa-var-people-pulling: \e535; +$fa-var-n: \4e; +$fa-var-cable-car: \f7da; +$fa-var-tram: \f7da; +$fa-var-cloud-rain: \f73d; +$fa-var-building-circle-xmark: \e4d4; +$fa-var-ship: \f21a; +$fa-var-arrows-down-to-line: \e4b8; +$fa-var-download: \f019; +$fa-var-face-grin: \f580; +$fa-var-grin: \f580; +$fa-var-delete-left: \f55a; +$fa-var-backspace: \f55a; +$fa-var-eye-dropper: \f1fb; +$fa-var-eye-dropper-empty: \f1fb; +$fa-var-eyedropper: \f1fb; +$fa-var-file-circle-check: \e5a0; +$fa-var-forward: \f04e; +$fa-var-mobile: \f3ce; +$fa-var-mobile-android: \f3ce; +$fa-var-mobile-phone: \f3ce; +$fa-var-face-meh: \f11a; +$fa-var-meh: \f11a; +$fa-var-align-center: \f037; +$fa-var-book-skull: \f6b7; +$fa-var-book-dead: \f6b7; +$fa-var-id-card: \f2c2; +$fa-var-drivers-license: \f2c2; +$fa-var-outdent: \f03b; +$fa-var-dedent: \f03b; +$fa-var-heart-circle-exclamation: \e4fe; +$fa-var-house: \f015; +$fa-var-home: \f015; +$fa-var-home-alt: \f015; +$fa-var-home-lg-alt: \f015; +$fa-var-calendar-week: \f784; +$fa-var-laptop-medical: \f812; +$fa-var-b: \42; +$fa-var-file-medical: \f477; +$fa-var-dice-one: \f525; +$fa-var-kiwi-bird: \f535; +$fa-var-arrow-right-arrow-left: \f0ec; +$fa-var-exchange: \f0ec; +$fa-var-rotate-right: \f2f9; +$fa-var-redo-alt: \f2f9; +$fa-var-rotate-forward: \f2f9; +$fa-var-utensils: \f2e7; +$fa-var-cutlery: \f2e7; +$fa-var-arrow-up-wide-short: \f161; +$fa-var-sort-amount-up: \f161; +$fa-var-mill-sign: \e1ed; +$fa-var-bowl-rice: \e2eb; +$fa-var-skull: \f54c; +$fa-var-tower-broadcast: \f519; +$fa-var-broadcast-tower: \f519; +$fa-var-truck-pickup: \f63c; +$fa-var-up-long: \f30c; +$fa-var-long-arrow-alt-up: \f30c; +$fa-var-stop: \f04d; +$fa-var-code-merge: \f387; +$fa-var-upload: \f093; +$fa-var-hurricane: \f751; +$fa-var-mound: \e52d; +$fa-var-toilet-portable: \e583; +$fa-var-compact-disc: \f51f; +$fa-var-file-arrow-down: \f56d; +$fa-var-file-download: \f56d; +$fa-var-caravan: \f8ff; +$fa-var-shield-cat: \e572; +$fa-var-bolt: \f0e7; +$fa-var-zap: \f0e7; +$fa-var-glass-water: \e4f4; +$fa-var-oil-well: \e532; +$fa-var-vault: \e2c5; +$fa-var-mars: \f222; +$fa-var-toilet: \f7d8; +$fa-var-plane-circle-xmark: \e557; +$fa-var-yen-sign: \f157; +$fa-var-cny: \f157; +$fa-var-jpy: \f157; +$fa-var-rmb: \f157; +$fa-var-yen: \f157; +$fa-var-ruble-sign: \f158; +$fa-var-rouble: \f158; +$fa-var-rub: \f158; +$fa-var-ruble: \f158; +$fa-var-sun: \f185; +$fa-var-guitar: \f7a6; +$fa-var-face-laugh-wink: \f59c; +$fa-var-laugh-wink: \f59c; +$fa-var-horse-head: \f7ab; +$fa-var-bore-hole: \e4c3; +$fa-var-industry: \f275; +$fa-var-circle-down: \f358; +$fa-var-arrow-alt-circle-down: \f358; +$fa-var-arrows-turn-to-dots: \e4c1; +$fa-var-florin-sign: \e184; +$fa-var-arrow-down-short-wide: \f884; +$fa-var-sort-amount-desc: \f884; +$fa-var-sort-amount-down-alt: \f884; +$fa-var-less-than: \3c; +$fa-var-angle-down: \f107; +$fa-var-car-tunnel: \e4de; +$fa-var-head-side-cough: \e061; +$fa-var-grip-lines: \f7a4; +$fa-var-thumbs-down: \f165; +$fa-var-user-lock: \f502; +$fa-var-arrow-right-long: \f178; +$fa-var-long-arrow-right: \f178; +$fa-var-anchor-circle-xmark: \e4ac; +$fa-var-ellipsis: \f141; +$fa-var-ellipsis-h: \f141; +$fa-var-chess-pawn: \f443; +$fa-var-kit-medical: \f479; +$fa-var-first-aid: \f479; +$fa-var-person-through-window: \e5a9; +$fa-var-toolbox: \f552; +$fa-var-hands-holding-circle: \e4fb; +$fa-var-bug: \f188; +$fa-var-credit-card: \f09d; +$fa-var-credit-card-alt: \f09d; +$fa-var-car: \f1b9; +$fa-var-automobile: \f1b9; +$fa-var-hand-holding-hand: \e4f7; +$fa-var-book-open-reader: \f5da; +$fa-var-book-reader: \f5da; +$fa-var-mountain-sun: \e52f; +$fa-var-arrows-left-right-to-line: \e4ba; +$fa-var-dice-d20: \f6cf; +$fa-var-truck-droplet: \e58c; +$fa-var-file-circle-xmark: \e5a1; +$fa-var-temperature-arrow-up: \e040; +$fa-var-temperature-up: \e040; +$fa-var-medal: \f5a2; +$fa-var-bed: \f236; +$fa-var-square-h: \f0fd; +$fa-var-h-square: \f0fd; +$fa-var-podcast: \f2ce; +$fa-var-temperature-full: \f2c7; +$fa-var-temperature-4: \f2c7; +$fa-var-thermometer-4: \f2c7; +$fa-var-thermometer-full: \f2c7; +$fa-var-bell: \f0f3; +$fa-var-superscript: \f12b; +$fa-var-plug-circle-xmark: \e560; +$fa-var-star-of-life: \f621; +$fa-var-phone-slash: \f3dd; +$fa-var-paint-roller: \f5aa; +$fa-var-handshake-angle: \f4c4; +$fa-var-hands-helping: \f4c4; +$fa-var-location-dot: \f3c5; +$fa-var-map-marker-alt: \f3c5; +$fa-var-file: \f15b; +$fa-var-greater-than: \3e; +$fa-var-person-swimming: \f5c4; +$fa-var-swimmer: \f5c4; +$fa-var-arrow-down: \f063; +$fa-var-droplet: \f043; +$fa-var-tint: \f043; +$fa-var-eraser: \f12d; +$fa-var-earth-americas: \f57d; +$fa-var-earth: \f57d; +$fa-var-earth-america: \f57d; +$fa-var-globe-americas: \f57d; +$fa-var-person-burst: \e53b; +$fa-var-dove: \f4ba; +$fa-var-battery-empty: \f244; +$fa-var-battery-0: \f244; +$fa-var-socks: \f696; +$fa-var-inbox: \f01c; +$fa-var-section: \e447; +$fa-var-gauge-high: \f625; +$fa-var-tachometer-alt: \f625; +$fa-var-tachometer-alt-fast: \f625; +$fa-var-envelope-open-text: \f658; +$fa-var-hospital: \f0f8; +$fa-var-hospital-alt: \f0f8; +$fa-var-hospital-wide: \f0f8; +$fa-var-wine-bottle: \f72f; +$fa-var-chess-rook: \f447; +$fa-var-bars-staggered: \f550; +$fa-var-reorder: \f550; +$fa-var-stream: \f550; +$fa-var-dharmachakra: \f655; +$fa-var-hotdog: \f80f; +$fa-var-person-walking-with-cane: \f29d; +$fa-var-blind: \f29d; +$fa-var-drum: \f569; +$fa-var-ice-cream: \f810; +$fa-var-heart-circle-bolt: \e4fc; +$fa-var-fax: \f1ac; +$fa-var-paragraph: \f1dd; +$fa-var-check-to-slot: \f772; +$fa-var-vote-yea: \f772; +$fa-var-star-half: \f089; +$fa-var-boxes-stacked: \f468; +$fa-var-boxes: \f468; +$fa-var-boxes-alt: \f468; +$fa-var-link: \f0c1; +$fa-var-chain: \f0c1; +$fa-var-ear-listen: \f2a2; +$fa-var-assistive-listening-systems: \f2a2; +$fa-var-tree-city: \e587; +$fa-var-play: \f04b; +$fa-var-font: \f031; +$fa-var-table-cells-row-lock: \e67a; +$fa-var-rupiah-sign: \e23d; +$fa-var-magnifying-glass: \f002; +$fa-var-search: \f002; +$fa-var-table-tennis-paddle-ball: \f45d; +$fa-var-ping-pong-paddle-ball: \f45d; +$fa-var-table-tennis: \f45d; +$fa-var-person-dots-from-line: \f470; +$fa-var-diagnoses: \f470; +$fa-var-trash-can-arrow-up: \f82a; +$fa-var-trash-restore-alt: \f82a; +$fa-var-naira-sign: \e1f6; +$fa-var-cart-arrow-down: \f218; +$fa-var-walkie-talkie: \f8ef; +$fa-var-file-pen: \f31c; +$fa-var-file-edit: \f31c; +$fa-var-receipt: \f543; +$fa-var-square-pen: \f14b; +$fa-var-pen-square: \f14b; +$fa-var-pencil-square: \f14b; +$fa-var-suitcase-rolling: \f5c1; +$fa-var-person-circle-exclamation: \e53f; +$fa-var-chevron-down: \f078; +$fa-var-battery-full: \f240; +$fa-var-battery: \f240; +$fa-var-battery-5: \f240; +$fa-var-skull-crossbones: \f714; +$fa-var-code-compare: \e13a; +$fa-var-list-ul: \f0ca; +$fa-var-list-dots: \f0ca; +$fa-var-school-lock: \e56f; +$fa-var-tower-cell: \e585; +$fa-var-down-long: \f309; +$fa-var-long-arrow-alt-down: \f309; +$fa-var-ranking-star: \e561; +$fa-var-chess-king: \f43f; +$fa-var-person-harassing: \e549; +$fa-var-brazilian-real-sign: \e46c; +$fa-var-landmark-dome: \f752; +$fa-var-landmark-alt: \f752; +$fa-var-arrow-up: \f062; +$fa-var-tv: \f26c; +$fa-var-television: \f26c; +$fa-var-tv-alt: \f26c; +$fa-var-shrimp: \e448; +$fa-var-list-check: \f0ae; +$fa-var-tasks: \f0ae; +$fa-var-jug-detergent: \e519; +$fa-var-circle-user: \f2bd; +$fa-var-user-circle: \f2bd; +$fa-var-user-shield: \f505; +$fa-var-wind: \f72e; +$fa-var-car-burst: \f5e1; +$fa-var-car-crash: \f5e1; +$fa-var-y: \59; +$fa-var-person-snowboarding: \f7ce; +$fa-var-snowboarding: \f7ce; +$fa-var-truck-fast: \f48b; +$fa-var-shipping-fast: \f48b; +$fa-var-fish: \f578; +$fa-var-user-graduate: \f501; +$fa-var-circle-half-stroke: \f042; +$fa-var-adjust: \f042; +$fa-var-clapperboard: \e131; +$fa-var-circle-radiation: \f7ba; +$fa-var-radiation-alt: \f7ba; +$fa-var-baseball: \f433; +$fa-var-baseball-ball: \f433; +$fa-var-jet-fighter-up: \e518; +$fa-var-diagram-project: \f542; +$fa-var-project-diagram: \f542; +$fa-var-copy: \f0c5; +$fa-var-volume-xmark: \f6a9; +$fa-var-volume-mute: \f6a9; +$fa-var-volume-times: \f6a9; +$fa-var-hand-sparkles: \e05d; +$fa-var-grip: \f58d; +$fa-var-grip-horizontal: \f58d; +$fa-var-share-from-square: \f14d; +$fa-var-share-square: \f14d; +$fa-var-child-combatant: \e4e0; +$fa-var-child-rifle: \e4e0; +$fa-var-gun: \e19b; +$fa-var-square-phone: \f098; +$fa-var-phone-square: \f098; +$fa-var-plus: \2b; +$fa-var-add: \2b; +$fa-var-expand: \f065; +$fa-var-computer: \e4e5; +$fa-var-xmark: \f00d; +$fa-var-close: \f00d; +$fa-var-multiply: \f00d; +$fa-var-remove: \f00d; +$fa-var-times: \f00d; +$fa-var-arrows-up-down-left-right: \f047; +$fa-var-arrows: \f047; +$fa-var-chalkboard-user: \f51c; +$fa-var-chalkboard-teacher: \f51c; +$fa-var-peso-sign: \e222; +$fa-var-building-shield: \e4d8; +$fa-var-baby: \f77c; +$fa-var-users-line: \e592; +$fa-var-quote-left: \f10d; +$fa-var-quote-left-alt: \f10d; +$fa-var-tractor: \f722; +$fa-var-trash-arrow-up: \f829; +$fa-var-trash-restore: \f829; +$fa-var-arrow-down-up-lock: \e4b0; +$fa-var-lines-leaning: \e51e; +$fa-var-ruler-combined: \f546; +$fa-var-copyright: \f1f9; +$fa-var-equals: \3d; +$fa-var-blender: \f517; +$fa-var-teeth: \f62e; +$fa-var-shekel-sign: \f20b; +$fa-var-ils: \f20b; +$fa-var-shekel: \f20b; +$fa-var-sheqel: \f20b; +$fa-var-sheqel-sign: \f20b; +$fa-var-map: \f279; +$fa-var-rocket: \f135; +$fa-var-photo-film: \f87c; +$fa-var-photo-video: \f87c; +$fa-var-folder-minus: \f65d; +$fa-var-hexagon-nodes-bolt: \e69a; +$fa-var-store: \f54e; +$fa-var-arrow-trend-up: \e098; +$fa-var-plug-circle-minus: \e55e; +$fa-var-sign-hanging: \f4d9; +$fa-var-sign: \f4d9; +$fa-var-bezier-curve: \f55b; +$fa-var-bell-slash: \f1f6; +$fa-var-tablet: \f3fb; +$fa-var-tablet-android: \f3fb; +$fa-var-school-flag: \e56e; +$fa-var-fill: \f575; +$fa-var-angle-up: \f106; +$fa-var-drumstick-bite: \f6d7; +$fa-var-holly-berry: \f7aa; +$fa-var-chevron-left: \f053; +$fa-var-bacteria: \e059; +$fa-var-hand-lizard: \f258; +$fa-var-notdef: \e1fe; +$fa-var-disease: \f7fa; +$fa-var-briefcase-medical: \f469; +$fa-var-genderless: \f22d; +$fa-var-chevron-right: \f054; +$fa-var-retweet: \f079; +$fa-var-car-rear: \f5de; +$fa-var-car-alt: \f5de; +$fa-var-pump-soap: \e06b; +$fa-var-video-slash: \f4e2; +$fa-var-battery-quarter: \f243; +$fa-var-battery-2: \f243; +$fa-var-radio: \f8d7; +$fa-var-baby-carriage: \f77d; +$fa-var-carriage-baby: \f77d; +$fa-var-traffic-light: \f637; +$fa-var-thermometer: \f491; +$fa-var-vr-cardboard: \f729; +$fa-var-hand-middle-finger: \f806; +$fa-var-percent: \25; +$fa-var-percentage: \25; +$fa-var-truck-moving: \f4df; +$fa-var-glass-water-droplet: \e4f5; +$fa-var-display: \e163; +$fa-var-face-smile: \f118; +$fa-var-smile: \f118; +$fa-var-thumbtack: \f08d; +$fa-var-thumb-tack: \f08d; +$fa-var-trophy: \f091; +$fa-var-person-praying: \f683; +$fa-var-pray: \f683; +$fa-var-hammer: \f6e3; +$fa-var-hand-peace: \f25b; +$fa-var-rotate: \f2f1; +$fa-var-sync-alt: \f2f1; +$fa-var-spinner: \f110; +$fa-var-robot: \f544; +$fa-var-peace: \f67c; +$fa-var-gears: \f085; +$fa-var-cogs: \f085; +$fa-var-warehouse: \f494; +$fa-var-arrow-up-right-dots: \e4b7; +$fa-var-splotch: \f5bc; +$fa-var-face-grin-hearts: \f584; +$fa-var-grin-hearts: \f584; +$fa-var-dice-four: \f524; +$fa-var-sim-card: \f7c4; +$fa-var-transgender: \f225; +$fa-var-transgender-alt: \f225; +$fa-var-mercury: \f223; +$fa-var-arrow-turn-down: \f149; +$fa-var-level-down: \f149; +$fa-var-person-falling-burst: \e547; +$fa-var-award: \f559; +$fa-var-ticket-simple: \f3ff; +$fa-var-ticket-alt: \f3ff; +$fa-var-building: \f1ad; +$fa-var-angles-left: \f100; +$fa-var-angle-double-left: \f100; +$fa-var-qrcode: \f029; +$fa-var-clock-rotate-left: \f1da; +$fa-var-history: \f1da; +$fa-var-face-grin-beam-sweat: \f583; +$fa-var-grin-beam-sweat: \f583; +$fa-var-file-export: \f56e; +$fa-var-arrow-right-from-file: \f56e; +$fa-var-shield: \f132; +$fa-var-shield-blank: \f132; +$fa-var-arrow-up-short-wide: \f885; +$fa-var-sort-amount-up-alt: \f885; +$fa-var-comment-nodes: \e696; +$fa-var-house-medical: \e3b2; +$fa-var-golf-ball-tee: \f450; +$fa-var-golf-ball: \f450; +$fa-var-circle-chevron-left: \f137; +$fa-var-chevron-circle-left: \f137; +$fa-var-house-chimney-window: \e00d; +$fa-var-pen-nib: \f5ad; +$fa-var-tent-arrow-turn-left: \e580; +$fa-var-tents: \e582; +$fa-var-wand-magic: \f0d0; +$fa-var-magic: \f0d0; +$fa-var-dog: \f6d3; +$fa-var-carrot: \f787; +$fa-var-moon: \f186; +$fa-var-wine-glass-empty: \f5ce; +$fa-var-wine-glass-alt: \f5ce; +$fa-var-cheese: \f7ef; +$fa-var-yin-yang: \f6ad; +$fa-var-music: \f001; +$fa-var-code-commit: \f386; +$fa-var-temperature-low: \f76b; +$fa-var-person-biking: \f84a; +$fa-var-biking: \f84a; +$fa-var-broom: \f51a; +$fa-var-shield-heart: \e574; +$fa-var-gopuram: \f664; +$fa-var-earth-oceania: \e47b; +$fa-var-globe-oceania: \e47b; +$fa-var-square-xmark: \f2d3; +$fa-var-times-square: \f2d3; +$fa-var-xmark-square: \f2d3; +$fa-var-hashtag: \23; +$fa-var-up-right-and-down-left-from-center: \f424; +$fa-var-expand-alt: \f424; +$fa-var-oil-can: \f613; +$fa-var-t: \54; +$fa-var-hippo: \f6ed; +$fa-var-chart-column: \e0e3; +$fa-var-infinity: \f534; +$fa-var-vial-circle-check: \e596; +$fa-var-person-arrow-down-to-line: \e538; +$fa-var-voicemail: \f897; +$fa-var-fan: \f863; +$fa-var-person-walking-luggage: \e554; +$fa-var-up-down: \f338; +$fa-var-arrows-alt-v: \f338; +$fa-var-cloud-moon-rain: \f73c; +$fa-var-calendar: \f133; +$fa-var-trailer: \e041; +$fa-var-bahai: \f666; +$fa-var-haykal: \f666; +$fa-var-sd-card: \f7c2; +$fa-var-dragon: \f6d5; +$fa-var-shoe-prints: \f54b; +$fa-var-circle-plus: \f055; +$fa-var-plus-circle: \f055; +$fa-var-face-grin-tongue-wink: \f58b; +$fa-var-grin-tongue-wink: \f58b; +$fa-var-hand-holding: \f4bd; +$fa-var-plug-circle-exclamation: \e55d; +$fa-var-link-slash: \f127; +$fa-var-chain-broken: \f127; +$fa-var-chain-slash: \f127; +$fa-var-unlink: \f127; +$fa-var-clone: \f24d; +$fa-var-person-walking-arrow-loop-left: \e551; +$fa-var-arrow-up-z-a: \f882; +$fa-var-sort-alpha-up-alt: \f882; +$fa-var-fire-flame-curved: \f7e4; +$fa-var-fire-alt: \f7e4; +$fa-var-tornado: \f76f; +$fa-var-file-circle-plus: \e494; +$fa-var-book-quran: \f687; +$fa-var-quran: \f687; +$fa-var-anchor: \f13d; +$fa-var-border-all: \f84c; +$fa-var-face-angry: \f556; +$fa-var-angry: \f556; +$fa-var-cookie-bite: \f564; +$fa-var-arrow-trend-down: \e097; +$fa-var-rss: \f09e; +$fa-var-feed: \f09e; +$fa-var-draw-polygon: \f5ee; +$fa-var-scale-balanced: \f24e; +$fa-var-balance-scale: \f24e; +$fa-var-gauge-simple-high: \f62a; +$fa-var-tachometer: \f62a; +$fa-var-tachometer-fast: \f62a; +$fa-var-shower: \f2cc; +$fa-var-desktop: \f390; +$fa-var-desktop-alt: \f390; +$fa-var-m: \4d; +$fa-var-table-list: \f00b; +$fa-var-th-list: \f00b; +$fa-var-comment-sms: \f7cd; +$fa-var-sms: \f7cd; +$fa-var-book: \f02d; +$fa-var-user-plus: \f234; +$fa-var-check: \f00c; +$fa-var-battery-three-quarters: \f241; +$fa-var-battery-4: \f241; +$fa-var-house-circle-check: \e509; +$fa-var-angle-left: \f104; +$fa-var-diagram-successor: \e47a; +$fa-var-truck-arrow-right: \e58b; +$fa-var-arrows-split-up-and-left: \e4bc; +$fa-var-hand-fist: \f6de; +$fa-var-fist-raised: \f6de; +$fa-var-cloud-moon: \f6c3; +$fa-var-briefcase: \f0b1; +$fa-var-person-falling: \e546; +$fa-var-image-portrait: \f3e0; +$fa-var-portrait: \f3e0; +$fa-var-user-tag: \f507; +$fa-var-rug: \e569; +$fa-var-earth-europe: \f7a2; +$fa-var-globe-europe: \f7a2; +$fa-var-cart-flatbed-suitcase: \f59d; +$fa-var-luggage-cart: \f59d; +$fa-var-rectangle-xmark: \f410; +$fa-var-rectangle-times: \f410; +$fa-var-times-rectangle: \f410; +$fa-var-window-close: \f410; +$fa-var-baht-sign: \e0ac; +$fa-var-book-open: \f518; +$fa-var-book-journal-whills: \f66a; +$fa-var-journal-whills: \f66a; +$fa-var-handcuffs: \e4f8; +$fa-var-triangle-exclamation: \f071; +$fa-var-exclamation-triangle: \f071; +$fa-var-warning: \f071; +$fa-var-database: \f1c0; +$fa-var-share: \f064; +$fa-var-mail-forward: \f064; +$fa-var-bottle-droplet: \e4c4; +$fa-var-mask-face: \e1d7; +$fa-var-hill-rockslide: \e508; +$fa-var-right-left: \f362; +$fa-var-exchange-alt: \f362; +$fa-var-paper-plane: \f1d8; +$fa-var-road-circle-exclamation: \e565; +$fa-var-dungeon: \f6d9; +$fa-var-align-right: \f038; +$fa-var-money-bill-1-wave: \f53b; +$fa-var-money-bill-wave-alt: \f53b; +$fa-var-life-ring: \f1cd; +$fa-var-hands: \f2a7; +$fa-var-sign-language: \f2a7; +$fa-var-signing: \f2a7; +$fa-var-calendar-day: \f783; +$fa-var-water-ladder: \f5c5; +$fa-var-ladder-water: \f5c5; +$fa-var-swimming-pool: \f5c5; +$fa-var-arrows-up-down: \f07d; +$fa-var-arrows-v: \f07d; +$fa-var-face-grimace: \f57f; +$fa-var-grimace: \f57f; +$fa-var-wheelchair-move: \e2ce; +$fa-var-wheelchair-alt: \e2ce; +$fa-var-turn-down: \f3be; +$fa-var-level-down-alt: \f3be; +$fa-var-person-walking-arrow-right: \e552; +$fa-var-square-envelope: \f199; +$fa-var-envelope-square: \f199; +$fa-var-dice: \f522; +$fa-var-bowling-ball: \f436; +$fa-var-brain: \f5dc; +$fa-var-bandage: \f462; +$fa-var-band-aid: \f462; +$fa-var-calendar-minus: \f272; +$fa-var-circle-xmark: \f057; +$fa-var-times-circle: \f057; +$fa-var-xmark-circle: \f057; +$fa-var-gifts: \f79c; +$fa-var-hotel: \f594; +$fa-var-earth-asia: \f57e; +$fa-var-globe-asia: \f57e; +$fa-var-id-card-clip: \f47f; +$fa-var-id-card-alt: \f47f; +$fa-var-magnifying-glass-plus: \f00e; +$fa-var-search-plus: \f00e; +$fa-var-thumbs-up: \f164; +$fa-var-user-clock: \f4fd; +$fa-var-hand-dots: \f461; +$fa-var-allergies: \f461; +$fa-var-file-invoice: \f570; +$fa-var-window-minimize: \f2d1; +$fa-var-mug-saucer: \f0f4; +$fa-var-coffee: \f0f4; +$fa-var-brush: \f55d; +$fa-var-file-half-dashed: \e698; +$fa-var-mask: \f6fa; +$fa-var-magnifying-glass-minus: \f010; +$fa-var-search-minus: \f010; +$fa-var-ruler-vertical: \f548; +$fa-var-user-large: \f406; +$fa-var-user-alt: \f406; +$fa-var-train-tram: \e5b4; +$fa-var-user-nurse: \f82f; +$fa-var-syringe: \f48e; +$fa-var-cloud-sun: \f6c4; +$fa-var-stopwatch-20: \e06f; +$fa-var-square-full: \f45c; +$fa-var-magnet: \f076; +$fa-var-jar: \e516; +$fa-var-note-sticky: \f249; +$fa-var-sticky-note: \f249; +$fa-var-bug-slash: \e490; +$fa-var-arrow-up-from-water-pump: \e4b6; +$fa-var-bone: \f5d7; +$fa-var-table-cells-row-unlock: \e691; +$fa-var-user-injured: \f728; +$fa-var-face-sad-tear: \f5b4; +$fa-var-sad-tear: \f5b4; +$fa-var-plane: \f072; +$fa-var-tent-arrows-down: \e581; +$fa-var-exclamation: \21; +$fa-var-arrows-spin: \e4bb; +$fa-var-print: \f02f; +$fa-var-turkish-lira-sign: \e2bb; +$fa-var-try: \e2bb; +$fa-var-turkish-lira: \e2bb; +$fa-var-dollar-sign: \24; +$fa-var-dollar: \24; +$fa-var-usd: \24; +$fa-var-x: \58; +$fa-var-magnifying-glass-dollar: \f688; +$fa-var-search-dollar: \f688; +$fa-var-users-gear: \f509; +$fa-var-users-cog: \f509; +$fa-var-person-military-pointing: \e54a; +$fa-var-building-columns: \f19c; +$fa-var-bank: \f19c; +$fa-var-institution: \f19c; +$fa-var-museum: \f19c; +$fa-var-university: \f19c; +$fa-var-umbrella: \f0e9; +$fa-var-trowel: \e589; +$fa-var-d: \44; +$fa-var-stapler: \e5af; +$fa-var-masks-theater: \f630; +$fa-var-theater-masks: \f630; +$fa-var-kip-sign: \e1c4; +$fa-var-hand-point-left: \f0a5; +$fa-var-handshake-simple: \f4c6; +$fa-var-handshake-alt: \f4c6; +$fa-var-jet-fighter: \f0fb; +$fa-var-fighter-jet: \f0fb; +$fa-var-square-share-nodes: \f1e1; +$fa-var-share-alt-square: \f1e1; +$fa-var-barcode: \f02a; +$fa-var-plus-minus: \e43c; +$fa-var-video: \f03d; +$fa-var-video-camera: \f03d; +$fa-var-graduation-cap: \f19d; +$fa-var-mortar-board: \f19d; +$fa-var-hand-holding-medical: \e05c; +$fa-var-person-circle-check: \e53e; +$fa-var-turn-up: \f3bf; +$fa-var-level-up-alt: \f3bf; + +$fa-var-monero: \f3d0; +$fa-var-hooli: \f427; +$fa-var-yelp: \f1e9; +$fa-var-cc-visa: \f1f0; +$fa-var-lastfm: \f202; +$fa-var-shopware: \f5b5; +$fa-var-creative-commons-nc: \f4e8; +$fa-var-aws: \f375; +$fa-var-redhat: \f7bc; +$fa-var-yoast: \f2b1; +$fa-var-cloudflare: \e07d; +$fa-var-ups: \f7e0; +$fa-var-pixiv: \e640; +$fa-var-wpexplorer: \f2de; +$fa-var-dyalog: \f399; +$fa-var-bity: \f37a; +$fa-var-stackpath: \f842; +$fa-var-buysellads: \f20d; +$fa-var-first-order: \f2b0; +$fa-var-modx: \f285; +$fa-var-guilded: \e07e; +$fa-var-vnv: \f40b; +$fa-var-square-js: \f3b9; +$fa-var-js-square: \f3b9; +$fa-var-microsoft: \f3ca; +$fa-var-qq: \f1d6; +$fa-var-orcid: \f8d2; +$fa-var-java: \f4e4; +$fa-var-invision: \f7b0; +$fa-var-creative-commons-pd-alt: \f4ed; +$fa-var-centercode: \f380; +$fa-var-glide-g: \f2a6; +$fa-var-drupal: \f1a9; +$fa-var-jxl: \e67b; +$fa-var-dart-lang: \e693; +$fa-var-hire-a-helper: \f3b0; +$fa-var-creative-commons-by: \f4e7; +$fa-var-unity: \e049; +$fa-var-whmcs: \f40d; +$fa-var-rocketchat: \f3e8; +$fa-var-vk: \f189; +$fa-var-untappd: \f405; +$fa-var-mailchimp: \f59e; +$fa-var-css3-alt: \f38b; +$fa-var-square-reddit: \f1a2; +$fa-var-reddit-square: \f1a2; +$fa-var-vimeo-v: \f27d; +$fa-var-contao: \f26d; +$fa-var-square-font-awesome: \e5ad; +$fa-var-deskpro: \f38f; +$fa-var-brave: \e63c; +$fa-var-sistrix: \f3ee; +$fa-var-square-instagram: \e055; +$fa-var-instagram-square: \e055; +$fa-var-battle-net: \f835; +$fa-var-the-red-yeti: \f69d; +$fa-var-square-hacker-news: \f3af; +$fa-var-hacker-news-square: \f3af; +$fa-var-edge: \f282; +$fa-var-threads: \e618; +$fa-var-napster: \f3d2; +$fa-var-square-snapchat: \f2ad; +$fa-var-snapchat-square: \f2ad; +$fa-var-google-plus-g: \f0d5; +$fa-var-artstation: \f77a; +$fa-var-markdown: \f60f; +$fa-var-sourcetree: \f7d3; +$fa-var-google-plus: \f2b3; +$fa-var-diaspora: \f791; +$fa-var-foursquare: \f180; +$fa-var-stack-overflow: \f16c; +$fa-var-github-alt: \f113; +$fa-var-phoenix-squadron: \f511; +$fa-var-pagelines: \f18c; +$fa-var-algolia: \f36c; +$fa-var-red-river: \f3e3; +$fa-var-creative-commons-sa: \f4ef; +$fa-var-safari: \f267; +$fa-var-google: \f1a0; +$fa-var-square-font-awesome-stroke: \f35c; +$fa-var-font-awesome-alt: \f35c; +$fa-var-atlassian: \f77b; +$fa-var-linkedin-in: \f0e1; +$fa-var-digital-ocean: \f391; +$fa-var-nimblr: \f5a8; +$fa-var-chromecast: \f838; +$fa-var-evernote: \f839; +$fa-var-hacker-news: \f1d4; +$fa-var-creative-commons-sampling: \f4f0; +$fa-var-adversal: \f36a; +$fa-var-creative-commons: \f25e; +$fa-var-watchman-monitoring: \e087; +$fa-var-fonticons: \f280; +$fa-var-weixin: \f1d7; +$fa-var-shirtsinbulk: \f214; +$fa-var-codepen: \f1cb; +$fa-var-git-alt: \f841; +$fa-var-lyft: \f3c3; +$fa-var-rev: \f5b2; +$fa-var-windows: \f17a; +$fa-var-wizards-of-the-coast: \f730; +$fa-var-square-viadeo: \f2aa; +$fa-var-viadeo-square: \f2aa; +$fa-var-meetup: \f2e0; +$fa-var-centos: \f789; +$fa-var-adn: \f170; +$fa-var-cloudsmith: \f384; +$fa-var-opensuse: \e62b; +$fa-var-pied-piper-alt: \f1a8; +$fa-var-square-dribbble: \f397; +$fa-var-dribbble-square: \f397; +$fa-var-codiepie: \f284; +$fa-var-node: \f419; +$fa-var-mix: \f3cb; +$fa-var-steam: \f1b6; +$fa-var-cc-apple-pay: \f416; +$fa-var-scribd: \f28a; +$fa-var-debian: \e60b; +$fa-var-openid: \f19b; +$fa-var-instalod: \e081; +$fa-var-files-pinwheel: \e69f; +$fa-var-expeditedssl: \f23e; +$fa-var-sellcast: \f2da; +$fa-var-square-twitter: \f081; +$fa-var-twitter-square: \f081; +$fa-var-r-project: \f4f7; +$fa-var-delicious: \f1a5; +$fa-var-freebsd: \f3a4; +$fa-var-vuejs: \f41f; +$fa-var-accusoft: \f369; +$fa-var-ioxhost: \f208; +$fa-var-fonticons-fi: \f3a2; +$fa-var-app-store: \f36f; +$fa-var-cc-mastercard: \f1f1; +$fa-var-itunes-note: \f3b5; +$fa-var-golang: \e40f; +$fa-var-kickstarter: \f3bb; +$fa-var-square-kickstarter: \f3bb; +$fa-var-grav: \f2d6; +$fa-var-weibo: \f18a; +$fa-var-uncharted: \e084; +$fa-var-firstdraft: \f3a1; +$fa-var-square-youtube: \f431; +$fa-var-youtube-square: \f431; +$fa-var-wikipedia-w: \f266; +$fa-var-wpressr: \f3e4; +$fa-var-rendact: \f3e4; +$fa-var-angellist: \f209; +$fa-var-galactic-republic: \f50c; +$fa-var-nfc-directional: \e530; +$fa-var-skype: \f17e; +$fa-var-joget: \f3b7; +$fa-var-fedora: \f798; +$fa-var-stripe-s: \f42a; +$fa-var-meta: \e49b; +$fa-var-laravel: \f3bd; +$fa-var-hotjar: \f3b1; +$fa-var-bluetooth-b: \f294; +$fa-var-square-letterboxd: \e62e; +$fa-var-sticker-mule: \f3f7; +$fa-var-creative-commons-zero: \f4f3; +$fa-var-hips: \f452; +$fa-var-css: \e6a2; +$fa-var-behance: \f1b4; +$fa-var-reddit: \f1a1; +$fa-var-discord: \f392; +$fa-var-chrome: \f268; +$fa-var-app-store-ios: \f370; +$fa-var-cc-discover: \f1f2; +$fa-var-wpbeginner: \f297; +$fa-var-confluence: \f78d; +$fa-var-shoelace: \e60c; +$fa-var-mdb: \f8ca; +$fa-var-dochub: \f394; +$fa-var-accessible-icon: \f368; +$fa-var-ebay: \f4f4; +$fa-var-amazon: \f270; +$fa-var-unsplash: \e07c; +$fa-var-yarn: \f7e3; +$fa-var-square-steam: \f1b7; +$fa-var-steam-square: \f1b7; +$fa-var-500px: \f26e; +$fa-var-square-vimeo: \f194; +$fa-var-vimeo-square: \f194; +$fa-var-asymmetrik: \f372; +$fa-var-font-awesome: \f2b4; +$fa-var-font-awesome-flag: \f2b4; +$fa-var-font-awesome-logo-full: \f2b4; +$fa-var-gratipay: \f184; +$fa-var-apple: \f179; +$fa-var-hive: \e07f; +$fa-var-gitkraken: \f3a6; +$fa-var-keybase: \f4f5; +$fa-var-apple-pay: \f415; +$fa-var-padlet: \e4a0; +$fa-var-amazon-pay: \f42c; +$fa-var-square-github: \f092; +$fa-var-github-square: \f092; +$fa-var-stumbleupon: \f1a4; +$fa-var-fedex: \f797; +$fa-var-phoenix-framework: \f3dc; +$fa-var-shopify: \e057; +$fa-var-neos: \f612; +$fa-var-square-threads: \e619; +$fa-var-hackerrank: \f5f7; +$fa-var-researchgate: \f4f8; +$fa-var-swift: \f8e1; +$fa-var-angular: \f420; +$fa-var-speakap: \f3f3; +$fa-var-angrycreative: \f36e; +$fa-var-y-combinator: \f23b; +$fa-var-empire: \f1d1; +$fa-var-envira: \f299; +$fa-var-google-scholar: \e63b; +$fa-var-square-gitlab: \e5ae; +$fa-var-gitlab-square: \e5ae; +$fa-var-studiovinari: \f3f8; +$fa-var-pied-piper: \f2ae; +$fa-var-wordpress: \f19a; +$fa-var-product-hunt: \f288; +$fa-var-firefox: \f269; +$fa-var-linode: \f2b8; +$fa-var-goodreads: \f3a8; +$fa-var-square-odnoklassniki: \f264; +$fa-var-odnoklassniki-square: \f264; +$fa-var-jsfiddle: \f1cc; +$fa-var-sith: \f512; +$fa-var-themeisle: \f2b2; +$fa-var-page4: \f3d7; +$fa-var-hashnode: \e499; +$fa-var-react: \f41b; +$fa-var-cc-paypal: \f1f4; +$fa-var-squarespace: \f5be; +$fa-var-cc-stripe: \f1f5; +$fa-var-creative-commons-share: \f4f2; +$fa-var-bitcoin: \f379; +$fa-var-keycdn: \f3ba; +$fa-var-opera: \f26a; +$fa-var-itch-io: \f83a; +$fa-var-umbraco: \f8e8; +$fa-var-galactic-senate: \f50d; +$fa-var-ubuntu: \f7df; +$fa-var-draft2digital: \f396; +$fa-var-stripe: \f429; +$fa-var-houzz: \f27c; +$fa-var-gg: \f260; +$fa-var-dhl: \f790; +$fa-var-square-pinterest: \f0d3; +$fa-var-pinterest-square: \f0d3; +$fa-var-xing: \f168; +$fa-var-blackberry: \f37b; +$fa-var-creative-commons-pd: \f4ec; +$fa-var-playstation: \f3df; +$fa-var-quinscape: \f459; +$fa-var-less: \f41d; +$fa-var-blogger-b: \f37d; +$fa-var-opencart: \f23d; +$fa-var-vine: \f1ca; +$fa-var-signal-messenger: \e663; +$fa-var-paypal: \f1ed; +$fa-var-gitlab: \f296; +$fa-var-typo3: \f42b; +$fa-var-reddit-alien: \f281; +$fa-var-yahoo: \f19e; +$fa-var-dailymotion: \e052; +$fa-var-affiliatetheme: \f36b; +$fa-var-pied-piper-pp: \f1a7; +$fa-var-bootstrap: \f836; +$fa-var-odnoklassniki: \f263; +$fa-var-nfc-symbol: \e531; +$fa-var-mintbit: \e62f; +$fa-var-ethereum: \f42e; +$fa-var-speaker-deck: \f83c; +$fa-var-creative-commons-nc-eu: \f4e9; +$fa-var-patreon: \f3d9; +$fa-var-avianex: \f374; +$fa-var-ello: \f5f1; +$fa-var-gofore: \f3a7; +$fa-var-bimobject: \f378; +$fa-var-brave-reverse: \e63d; +$fa-var-facebook-f: \f39e; +$fa-var-square-google-plus: \f0d4; +$fa-var-google-plus-square: \f0d4; +$fa-var-web-awesome: \e682; +$fa-var-mandalorian: \f50f; +$fa-var-first-order-alt: \f50a; +$fa-var-osi: \f41a; +$fa-var-google-wallet: \f1ee; +$fa-var-d-and-d-beyond: \f6ca; +$fa-var-periscope: \f3da; +$fa-var-fulcrum: \f50b; +$fa-var-cloudscale: \f383; +$fa-var-forumbee: \f211; +$fa-var-mizuni: \f3cc; +$fa-var-schlix: \f3ea; +$fa-var-square-xing: \f169; +$fa-var-xing-square: \f169; +$fa-var-bandcamp: \f2d5; +$fa-var-wpforms: \f298; +$fa-var-cloudversify: \f385; +$fa-var-usps: \f7e1; +$fa-var-megaport: \f5a3; +$fa-var-magento: \f3c4; +$fa-var-spotify: \f1bc; +$fa-var-optin-monster: \f23c; +$fa-var-fly: \f417; +$fa-var-square-bluesky: \e6a3; +$fa-var-aviato: \f421; +$fa-var-itunes: \f3b4; +$fa-var-cuttlefish: \f38c; +$fa-var-blogger: \f37c; +$fa-var-flickr: \f16e; +$fa-var-viber: \f409; +$fa-var-soundcloud: \f1be; +$fa-var-digg: \f1a6; +$fa-var-tencent-weibo: \f1d5; +$fa-var-letterboxd: \e62d; +$fa-var-symfony: \f83d; +$fa-var-maxcdn: \f136; +$fa-var-etsy: \f2d7; +$fa-var-facebook-messenger: \f39f; +$fa-var-audible: \f373; +$fa-var-think-peaks: \f731; +$fa-var-bilibili: \e3d9; +$fa-var-erlang: \f39d; +$fa-var-x-twitter: \e61b; +$fa-var-cotton-bureau: \f89e; +$fa-var-dashcube: \f210; +$fa-var-42-group: \e080; +$fa-var-innosoft: \e080; +$fa-var-stack-exchange: \f18d; +$fa-var-elementor: \f430; +$fa-var-square-pied-piper: \e01e; +$fa-var-pied-piper-square: \e01e; +$fa-var-creative-commons-nd: \f4eb; +$fa-var-palfed: \f3d8; +$fa-var-superpowers: \f2dd; +$fa-var-resolving: \f3e7; +$fa-var-xbox: \f412; +$fa-var-square-web-awesome-stroke: \e684; +$fa-var-searchengin: \f3eb; +$fa-var-tiktok: \e07b; +$fa-var-square-facebook: \f082; +$fa-var-facebook-square: \f082; +$fa-var-renren: \f18b; +$fa-var-linux: \f17c; +$fa-var-glide: \f2a5; +$fa-var-linkedin: \f08c; +$fa-var-hubspot: \f3b2; +$fa-var-deploydog: \f38e; +$fa-var-twitch: \f1e8; +$fa-var-flutter: \e694; +$fa-var-ravelry: \f2d9; +$fa-var-mixer: \e056; +$fa-var-square-lastfm: \f203; +$fa-var-lastfm-square: \f203; +$fa-var-vimeo: \f40a; +$fa-var-mendeley: \f7b3; +$fa-var-uniregistry: \f404; +$fa-var-figma: \f799; +$fa-var-creative-commons-remix: \f4ee; +$fa-var-cc-amazon-pay: \f42d; +$fa-var-dropbox: \f16b; +$fa-var-instagram: \f16d; +$fa-var-cmplid: \e360; +$fa-var-upwork: \e641; +$fa-var-facebook: \f09a; +$fa-var-gripfire: \f3ac; +$fa-var-jedi-order: \f50e; +$fa-var-uikit: \f403; +$fa-var-fort-awesome-alt: \f3a3; +$fa-var-phabricator: \f3db; +$fa-var-ussunnah: \f407; +$fa-var-earlybirds: \f39a; +$fa-var-trade-federation: \f513; +$fa-var-autoprefixer: \f41c; +$fa-var-whatsapp: \f232; +$fa-var-square-upwork: \e67c; +$fa-var-slideshare: \f1e7; +$fa-var-google-play: \f3ab; +$fa-var-viadeo: \f2a9; +$fa-var-line: \f3c0; +$fa-var-google-drive: \f3aa; +$fa-var-servicestack: \f3ec; +$fa-var-simplybuilt: \f215; +$fa-var-bitbucket: \f171; +$fa-var-imdb: \f2d8; +$fa-var-deezer: \e077; +$fa-var-raspberry-pi: \f7bb; +$fa-var-jira: \f7b1; +$fa-var-docker: \f395; +$fa-var-screenpal: \e570; +$fa-var-bluetooth: \f293; +$fa-var-gitter: \f426; +$fa-var-d-and-d: \f38d; +$fa-var-microblog: \e01a; +$fa-var-cc-diners-club: \f24c; +$fa-var-gg-circle: \f261; +$fa-var-pied-piper-hat: \f4e5; +$fa-var-kickstarter-k: \f3bc; +$fa-var-yandex: \f413; +$fa-var-readme: \f4d5; +$fa-var-html5: \f13b; +$fa-var-sellsy: \f213; +$fa-var-square-web-awesome: \e683; +$fa-var-sass: \f41e; +$fa-var-wirsindhandwerk: \e2d0; +$fa-var-wsh: \e2d0; +$fa-var-buromobelexperte: \f37f; +$fa-var-salesforce: \f83b; +$fa-var-octopus-deploy: \e082; +$fa-var-medapps: \f3c6; +$fa-var-ns8: \f3d5; +$fa-var-pinterest-p: \f231; +$fa-var-apper: \f371; +$fa-var-fort-awesome: \f286; +$fa-var-waze: \f83f; +$fa-var-bluesky: \e671; +$fa-var-cc-jcb: \f24b; +$fa-var-snapchat: \f2ab; +$fa-var-snapchat-ghost: \f2ab; +$fa-var-fantasy-flight-games: \f6dc; +$fa-var-rust: \e07a; +$fa-var-wix: \f5cf; +$fa-var-square-behance: \f1b5; +$fa-var-behance-square: \f1b5; +$fa-var-supple: \f3f9; +$fa-var-webflow: \e65c; +$fa-var-rebel: \f1d0; +$fa-var-css3: \f13c; +$fa-var-staylinked: \f3f5; +$fa-var-kaggle: \f5fa; +$fa-var-space-awesome: \e5ac; +$fa-var-deviantart: \f1bd; +$fa-var-cpanel: \f388; +$fa-var-goodreads-g: \f3a9; +$fa-var-square-git: \f1d2; +$fa-var-git-square: \f1d2; +$fa-var-square-tumblr: \f174; +$fa-var-tumblr-square: \f174; +$fa-var-trello: \f181; +$fa-var-creative-commons-nc-jp: \f4ea; +$fa-var-get-pocket: \f265; +$fa-var-perbyte: \e083; +$fa-var-grunt: \f3ad; +$fa-var-weebly: \f5cc; +$fa-var-connectdevelop: \f20e; +$fa-var-leanpub: \f212; +$fa-var-black-tie: \f27e; +$fa-var-themeco: \f5c6; +$fa-var-python: \f3e2; +$fa-var-android: \f17b; +$fa-var-bots: \e340; +$fa-var-free-code-camp: \f2c5; +$fa-var-hornbill: \f592; +$fa-var-js: \f3b8; +$fa-var-ideal: \e013; +$fa-var-git: \f1d3; +$fa-var-dev: \f6cc; +$fa-var-sketch: \f7c6; +$fa-var-yandex-international: \f414; +$fa-var-cc-amex: \f1f3; +$fa-var-uber: \f402; +$fa-var-github: \f09b; +$fa-var-php: \f457; +$fa-var-alipay: \f642; +$fa-var-youtube: \f167; +$fa-var-skyatlas: \f216; +$fa-var-firefox-browser: \e007; +$fa-var-replyd: \f3e6; +$fa-var-suse: \f7d6; +$fa-var-jenkins: \f3b6; +$fa-var-twitter: \f099; +$fa-var-rockrms: \f3e9; +$fa-var-pinterest: \f0d2; +$fa-var-buffer: \f837; +$fa-var-npm: \f3d4; +$fa-var-yammer: \f840; +$fa-var-btc: \f15a; +$fa-var-dribbble: \f17d; +$fa-var-stumbleupon-circle: \f1a3; +$fa-var-internet-explorer: \f26b; +$fa-var-stubber: \e5c7; +$fa-var-telegram: \f2c6; +$fa-var-telegram-plane: \f2c6; +$fa-var-old-republic: \f510; +$fa-var-odysee: \e5c6; +$fa-var-square-whatsapp: \f40c; +$fa-var-whatsapp-square: \f40c; +$fa-var-node-js: \f3d3; +$fa-var-edge-legacy: \e078; +$fa-var-slack: \f198; +$fa-var-slack-hash: \f198; +$fa-var-medrt: \f3c8; +$fa-var-usb: \f287; +$fa-var-tumblr: \f173; +$fa-var-vaadin: \f408; +$fa-var-quora: \f2c4; +$fa-var-square-x-twitter: \e61a; +$fa-var-reacteurope: \f75d; +$fa-var-medium: \f23a; +$fa-var-medium-m: \f23a; +$fa-var-amilia: \f36d; +$fa-var-mixcloud: \f289; +$fa-var-flipboard: \f44d; +$fa-var-viacoin: \f237; +$fa-var-critical-role: \f6c9; +$fa-var-sitrox: \e44a; +$fa-var-discourse: \f393; +$fa-var-joomla: \f1aa; +$fa-var-mastodon: \f4f6; +$fa-var-airbnb: \f834; +$fa-var-wolf-pack-battalion: \f514; +$fa-var-buy-n-large: \f8a6; +$fa-var-gulp: \f3ae; +$fa-var-creative-commons-sampling-plus: \f4f1; +$fa-var-strava: \f428; +$fa-var-ember: \f423; +$fa-var-canadian-maple-leaf: \f785; +$fa-var-teamspeak: \f4f9; +$fa-var-pushed: \f3e1; +$fa-var-wordpress-simple: \f411; +$fa-var-nutritionix: \f3d6; +$fa-var-wodu: \e088; +$fa-var-google-pay: \e079; +$fa-var-intercom: \f7af; +$fa-var-zhihu: \f63f; +$fa-var-korvue: \f42f; +$fa-var-pix: \e43a; +$fa-var-steam-symbol: \f3f6; + +$fa-icons: ( + "0": $fa-var-0, + "1": $fa-var-1, + "2": $fa-var-2, + "3": $fa-var-3, + "4": $fa-var-4, + "5": $fa-var-5, + "6": $fa-var-6, + "7": $fa-var-7, + "8": $fa-var-8, + "9": $fa-var-9, + "fill-drip": $fa-var-fill-drip, + "arrows-to-circle": $fa-var-arrows-to-circle, + "circle-chevron-right": $fa-var-circle-chevron-right, + "chevron-circle-right": $fa-var-chevron-circle-right, + "at": $fa-var-at, + "trash-can": $fa-var-trash-can, + "trash-alt": $fa-var-trash-alt, + "text-height": $fa-var-text-height, + "user-xmark": $fa-var-user-xmark, + "user-times": $fa-var-user-times, + "stethoscope": $fa-var-stethoscope, + "message": $fa-var-message, + "comment-alt": $fa-var-comment-alt, + "info": $fa-var-info, + "down-left-and-up-right-to-center": $fa-var-down-left-and-up-right-to-center, + "compress-alt": $fa-var-compress-alt, + "explosion": $fa-var-explosion, + "file-lines": $fa-var-file-lines, + "file-alt": $fa-var-file-alt, + "file-text": $fa-var-file-text, + "wave-square": $fa-var-wave-square, + "ring": $fa-var-ring, + "building-un": $fa-var-building-un, + "dice-three": $fa-var-dice-three, + "calendar-days": $fa-var-calendar-days, + "calendar-alt": $fa-var-calendar-alt, + "anchor-circle-check": $fa-var-anchor-circle-check, + "building-circle-arrow-right": $fa-var-building-circle-arrow-right, + "volleyball": $fa-var-volleyball, + "volleyball-ball": $fa-var-volleyball-ball, + "arrows-up-to-line": $fa-var-arrows-up-to-line, + "sort-down": $fa-var-sort-down, + "sort-desc": $fa-var-sort-desc, + "circle-minus": $fa-var-circle-minus, + "minus-circle": $fa-var-minus-circle, + "door-open": $fa-var-door-open, + "right-from-bracket": $fa-var-right-from-bracket, + "sign-out-alt": $fa-var-sign-out-alt, + "atom": $fa-var-atom, + "soap": $fa-var-soap, + "icons": $fa-var-icons, + "heart-music-camera-bolt": $fa-var-heart-music-camera-bolt, + "microphone-lines-slash": $fa-var-microphone-lines-slash, + "microphone-alt-slash": $fa-var-microphone-alt-slash, + "bridge-circle-check": $fa-var-bridge-circle-check, + "pump-medical": $fa-var-pump-medical, + "fingerprint": $fa-var-fingerprint, + "hand-point-right": $fa-var-hand-point-right, + "magnifying-glass-location": $fa-var-magnifying-glass-location, + "search-location": $fa-var-search-location, + "forward-step": $fa-var-forward-step, + "step-forward": $fa-var-step-forward, + "face-smile-beam": $fa-var-face-smile-beam, + "smile-beam": $fa-var-smile-beam, + "flag-checkered": $fa-var-flag-checkered, + "football": $fa-var-football, + "football-ball": $fa-var-football-ball, + "school-circle-exclamation": $fa-var-school-circle-exclamation, + "crop": $fa-var-crop, + "angles-down": $fa-var-angles-down, + "angle-double-down": $fa-var-angle-double-down, + "users-rectangle": $fa-var-users-rectangle, + "people-roof": $fa-var-people-roof, + "people-line": $fa-var-people-line, + "beer-mug-empty": $fa-var-beer-mug-empty, + "beer": $fa-var-beer, + "diagram-predecessor": $fa-var-diagram-predecessor, + "arrow-up-long": $fa-var-arrow-up-long, + "long-arrow-up": $fa-var-long-arrow-up, + "fire-flame-simple": $fa-var-fire-flame-simple, + "burn": $fa-var-burn, + "person": $fa-var-person, + "male": $fa-var-male, + "laptop": $fa-var-laptop, + "file-csv": $fa-var-file-csv, + "menorah": $fa-var-menorah, + "truck-plane": $fa-var-truck-plane, + "record-vinyl": $fa-var-record-vinyl, + "face-grin-stars": $fa-var-face-grin-stars, + "grin-stars": $fa-var-grin-stars, + "bong": $fa-var-bong, + "spaghetti-monster-flying": $fa-var-spaghetti-monster-flying, + "pastafarianism": $fa-var-pastafarianism, + "arrow-down-up-across-line": $fa-var-arrow-down-up-across-line, + "spoon": $fa-var-spoon, + "utensil-spoon": $fa-var-utensil-spoon, + "jar-wheat": $fa-var-jar-wheat, + "envelopes-bulk": $fa-var-envelopes-bulk, + "mail-bulk": $fa-var-mail-bulk, + "file-circle-exclamation": $fa-var-file-circle-exclamation, + "circle-h": $fa-var-circle-h, + "hospital-symbol": $fa-var-hospital-symbol, + "pager": $fa-var-pager, + "address-book": $fa-var-address-book, + "contact-book": $fa-var-contact-book, + "strikethrough": $fa-var-strikethrough, + "k": $fa-var-k, + "landmark-flag": $fa-var-landmark-flag, + "pencil": $fa-var-pencil, + "pencil-alt": $fa-var-pencil-alt, + "backward": $fa-var-backward, + "caret-right": $fa-var-caret-right, + "comments": $fa-var-comments, + "paste": $fa-var-paste, + "file-clipboard": $fa-var-file-clipboard, + "code-pull-request": $fa-var-code-pull-request, + "clipboard-list": $fa-var-clipboard-list, + "truck-ramp-box": $fa-var-truck-ramp-box, + "truck-loading": $fa-var-truck-loading, + "user-check": $fa-var-user-check, + "vial-virus": $fa-var-vial-virus, + "sheet-plastic": $fa-var-sheet-plastic, + "blog": $fa-var-blog, + "user-ninja": $fa-var-user-ninja, + "person-arrow-up-from-line": $fa-var-person-arrow-up-from-line, + "scroll-torah": $fa-var-scroll-torah, + "torah": $fa-var-torah, + "broom-ball": $fa-var-broom-ball, + "quidditch": $fa-var-quidditch, + "quidditch-broom-ball": $fa-var-quidditch-broom-ball, + "toggle-off": $fa-var-toggle-off, + "box-archive": $fa-var-box-archive, + "archive": $fa-var-archive, + "person-drowning": $fa-var-person-drowning, + "arrow-down-9-1": $fa-var-arrow-down-9-1, + "sort-numeric-desc": $fa-var-sort-numeric-desc, + "sort-numeric-down-alt": $fa-var-sort-numeric-down-alt, + "face-grin-tongue-squint": $fa-var-face-grin-tongue-squint, + "grin-tongue-squint": $fa-var-grin-tongue-squint, + "spray-can": $fa-var-spray-can, + "truck-monster": $fa-var-truck-monster, + "w": $fa-var-w, + "earth-africa": $fa-var-earth-africa, + "globe-africa": $fa-var-globe-africa, + "rainbow": $fa-var-rainbow, + "circle-notch": $fa-var-circle-notch, + "tablet-screen-button": $fa-var-tablet-screen-button, + "tablet-alt": $fa-var-tablet-alt, + "paw": $fa-var-paw, + "cloud": $fa-var-cloud, + "trowel-bricks": $fa-var-trowel-bricks, + "face-flushed": $fa-var-face-flushed, + "flushed": $fa-var-flushed, + "hospital-user": $fa-var-hospital-user, + "tent-arrow-left-right": $fa-var-tent-arrow-left-right, + "gavel": $fa-var-gavel, + "legal": $fa-var-legal, + "binoculars": $fa-var-binoculars, + "microphone-slash": $fa-var-microphone-slash, + "box-tissue": $fa-var-box-tissue, + "motorcycle": $fa-var-motorcycle, + "bell-concierge": $fa-var-bell-concierge, + "concierge-bell": $fa-var-concierge-bell, + "pen-ruler": $fa-var-pen-ruler, + "pencil-ruler": $fa-var-pencil-ruler, + "people-arrows": $fa-var-people-arrows, + "people-arrows-left-right": $fa-var-people-arrows-left-right, + "mars-and-venus-burst": $fa-var-mars-and-venus-burst, + "square-caret-right": $fa-var-square-caret-right, + "caret-square-right": $fa-var-caret-square-right, + "scissors": $fa-var-scissors, + "cut": $fa-var-cut, + "sun-plant-wilt": $fa-var-sun-plant-wilt, + "toilets-portable": $fa-var-toilets-portable, + "hockey-puck": $fa-var-hockey-puck, + "table": $fa-var-table, + "magnifying-glass-arrow-right": $fa-var-magnifying-glass-arrow-right, + "tachograph-digital": $fa-var-tachograph-digital, + "digital-tachograph": $fa-var-digital-tachograph, + "users-slash": $fa-var-users-slash, + "clover": $fa-var-clover, + "reply": $fa-var-reply, + "mail-reply": $fa-var-mail-reply, + "star-and-crescent": $fa-var-star-and-crescent, + "house-fire": $fa-var-house-fire, + "square-minus": $fa-var-square-minus, + "minus-square": $fa-var-minus-square, + "helicopter": $fa-var-helicopter, + "compass": $fa-var-compass, + "square-caret-down": $fa-var-square-caret-down, + "caret-square-down": $fa-var-caret-square-down, + "file-circle-question": $fa-var-file-circle-question, + "laptop-code": $fa-var-laptop-code, + "swatchbook": $fa-var-swatchbook, + "prescription-bottle": $fa-var-prescription-bottle, + "bars": $fa-var-bars, + "navicon": $fa-var-navicon, + "people-group": $fa-var-people-group, + "hourglass-end": $fa-var-hourglass-end, + "hourglass-3": $fa-var-hourglass-3, + "heart-crack": $fa-var-heart-crack, + "heart-broken": $fa-var-heart-broken, + "square-up-right": $fa-var-square-up-right, + "external-link-square-alt": $fa-var-external-link-square-alt, + "face-kiss-beam": $fa-var-face-kiss-beam, + "kiss-beam": $fa-var-kiss-beam, + "film": $fa-var-film, + "ruler-horizontal": $fa-var-ruler-horizontal, + "people-robbery": $fa-var-people-robbery, + "lightbulb": $fa-var-lightbulb, + "caret-left": $fa-var-caret-left, + "circle-exclamation": $fa-var-circle-exclamation, + "exclamation-circle": $fa-var-exclamation-circle, + "school-circle-xmark": $fa-var-school-circle-xmark, + "arrow-right-from-bracket": $fa-var-arrow-right-from-bracket, + "sign-out": $fa-var-sign-out, + "circle-chevron-down": $fa-var-circle-chevron-down, + "chevron-circle-down": $fa-var-chevron-circle-down, + "unlock-keyhole": $fa-var-unlock-keyhole, + "unlock-alt": $fa-var-unlock-alt, + "cloud-showers-heavy": $fa-var-cloud-showers-heavy, + "headphones-simple": $fa-var-headphones-simple, + "headphones-alt": $fa-var-headphones-alt, + "sitemap": $fa-var-sitemap, + "circle-dollar-to-slot": $fa-var-circle-dollar-to-slot, + "donate": $fa-var-donate, + "memory": $fa-var-memory, + "road-spikes": $fa-var-road-spikes, + "fire-burner": $fa-var-fire-burner, + "flag": $fa-var-flag, + "hanukiah": $fa-var-hanukiah, + "feather": $fa-var-feather, + "volume-low": $fa-var-volume-low, + "volume-down": $fa-var-volume-down, + "comment-slash": $fa-var-comment-slash, + "cloud-sun-rain": $fa-var-cloud-sun-rain, + "compress": $fa-var-compress, + "wheat-awn": $fa-var-wheat-awn, + "wheat-alt": $fa-var-wheat-alt, + "ankh": $fa-var-ankh, + "hands-holding-child": $fa-var-hands-holding-child, + "asterisk": $fa-var-asterisk, + "square-check": $fa-var-square-check, + "check-square": $fa-var-check-square, + "peseta-sign": $fa-var-peseta-sign, + "heading": $fa-var-heading, + "header": $fa-var-header, + "ghost": $fa-var-ghost, + "list": $fa-var-list, + "list-squares": $fa-var-list-squares, + "square-phone-flip": $fa-var-square-phone-flip, + "phone-square-alt": $fa-var-phone-square-alt, + "cart-plus": $fa-var-cart-plus, + "gamepad": $fa-var-gamepad, + "circle-dot": $fa-var-circle-dot, + "dot-circle": $fa-var-dot-circle, + "face-dizzy": $fa-var-face-dizzy, + "dizzy": $fa-var-dizzy, + "egg": $fa-var-egg, + "house-medical-circle-xmark": $fa-var-house-medical-circle-xmark, + "campground": $fa-var-campground, + "folder-plus": $fa-var-folder-plus, + "futbol": $fa-var-futbol, + "futbol-ball": $fa-var-futbol-ball, + "soccer-ball": $fa-var-soccer-ball, + "paintbrush": $fa-var-paintbrush, + "paint-brush": $fa-var-paint-brush, + "lock": $fa-var-lock, + "gas-pump": $fa-var-gas-pump, + "hot-tub-person": $fa-var-hot-tub-person, + "hot-tub": $fa-var-hot-tub, + "map-location": $fa-var-map-location, + "map-marked": $fa-var-map-marked, + "house-flood-water": $fa-var-house-flood-water, + "tree": $fa-var-tree, + "bridge-lock": $fa-var-bridge-lock, + "sack-dollar": $fa-var-sack-dollar, + "pen-to-square": $fa-var-pen-to-square, + "edit": $fa-var-edit, + "car-side": $fa-var-car-side, + "share-nodes": $fa-var-share-nodes, + "share-alt": $fa-var-share-alt, + "heart-circle-minus": $fa-var-heart-circle-minus, + "hourglass-half": $fa-var-hourglass-half, + "hourglass-2": $fa-var-hourglass-2, + "microscope": $fa-var-microscope, + "sink": $fa-var-sink, + "bag-shopping": $fa-var-bag-shopping, + "shopping-bag": $fa-var-shopping-bag, + "arrow-down-z-a": $fa-var-arrow-down-z-a, + "sort-alpha-desc": $fa-var-sort-alpha-desc, + "sort-alpha-down-alt": $fa-var-sort-alpha-down-alt, + "mitten": $fa-var-mitten, + "person-rays": $fa-var-person-rays, + "users": $fa-var-users, + "eye-slash": $fa-var-eye-slash, + "flask-vial": $fa-var-flask-vial, + "hand": $fa-var-hand, + "hand-paper": $fa-var-hand-paper, + "om": $fa-var-om, + "worm": $fa-var-worm, + "house-circle-xmark": $fa-var-house-circle-xmark, + "plug": $fa-var-plug, + "chevron-up": $fa-var-chevron-up, + "hand-spock": $fa-var-hand-spock, + "stopwatch": $fa-var-stopwatch, + "face-kiss": $fa-var-face-kiss, + "kiss": $fa-var-kiss, + "bridge-circle-xmark": $fa-var-bridge-circle-xmark, + "face-grin-tongue": $fa-var-face-grin-tongue, + "grin-tongue": $fa-var-grin-tongue, + "chess-bishop": $fa-var-chess-bishop, + "face-grin-wink": $fa-var-face-grin-wink, + "grin-wink": $fa-var-grin-wink, + "ear-deaf": $fa-var-ear-deaf, + "deaf": $fa-var-deaf, + "deafness": $fa-var-deafness, + "hard-of-hearing": $fa-var-hard-of-hearing, + "road-circle-check": $fa-var-road-circle-check, + "dice-five": $fa-var-dice-five, + "square-rss": $fa-var-square-rss, + "rss-square": $fa-var-rss-square, + "land-mine-on": $fa-var-land-mine-on, + "i-cursor": $fa-var-i-cursor, + "stamp": $fa-var-stamp, + "stairs": $fa-var-stairs, + "i": $fa-var-i, + "hryvnia-sign": $fa-var-hryvnia-sign, + "hryvnia": $fa-var-hryvnia, + "pills": $fa-var-pills, + "face-grin-wide": $fa-var-face-grin-wide, + "grin-alt": $fa-var-grin-alt, + "tooth": $fa-var-tooth, + "v": $fa-var-v, + "bangladeshi-taka-sign": $fa-var-bangladeshi-taka-sign, + "bicycle": $fa-var-bicycle, + "staff-snake": $fa-var-staff-snake, + "rod-asclepius": $fa-var-rod-asclepius, + "rod-snake": $fa-var-rod-snake, + "staff-aesculapius": $fa-var-staff-aesculapius, + "head-side-cough-slash": $fa-var-head-side-cough-slash, + "truck-medical": $fa-var-truck-medical, + "ambulance": $fa-var-ambulance, + "wheat-awn-circle-exclamation": $fa-var-wheat-awn-circle-exclamation, + "snowman": $fa-var-snowman, + "mortar-pestle": $fa-var-mortar-pestle, + "road-barrier": $fa-var-road-barrier, + "school": $fa-var-school, + "igloo": $fa-var-igloo, + "joint": $fa-var-joint, + "angle-right": $fa-var-angle-right, + "horse": $fa-var-horse, + "q": $fa-var-q, + "g": $fa-var-g, + "notes-medical": $fa-var-notes-medical, + "temperature-half": $fa-var-temperature-half, + "temperature-2": $fa-var-temperature-2, + "thermometer-2": $fa-var-thermometer-2, + "thermometer-half": $fa-var-thermometer-half, + "dong-sign": $fa-var-dong-sign, + "capsules": $fa-var-capsules, + "poo-storm": $fa-var-poo-storm, + "poo-bolt": $fa-var-poo-bolt, + "face-frown-open": $fa-var-face-frown-open, + "frown-open": $fa-var-frown-open, + "hand-point-up": $fa-var-hand-point-up, + "money-bill": $fa-var-money-bill, + "bookmark": $fa-var-bookmark, + "align-justify": $fa-var-align-justify, + "umbrella-beach": $fa-var-umbrella-beach, + "helmet-un": $fa-var-helmet-un, + "bullseye": $fa-var-bullseye, + "bacon": $fa-var-bacon, + "hand-point-down": $fa-var-hand-point-down, + "arrow-up-from-bracket": $fa-var-arrow-up-from-bracket, + "folder": $fa-var-folder, + "folder-blank": $fa-var-folder-blank, + "file-waveform": $fa-var-file-waveform, + "file-medical-alt": $fa-var-file-medical-alt, + "radiation": $fa-var-radiation, + "chart-simple": $fa-var-chart-simple, + "mars-stroke": $fa-var-mars-stroke, + "vial": $fa-var-vial, + "gauge": $fa-var-gauge, + "dashboard": $fa-var-dashboard, + "gauge-med": $fa-var-gauge-med, + "tachometer-alt-average": $fa-var-tachometer-alt-average, + "wand-magic-sparkles": $fa-var-wand-magic-sparkles, + "magic-wand-sparkles": $fa-var-magic-wand-sparkles, + "e": $fa-var-e, + "pen-clip": $fa-var-pen-clip, + "pen-alt": $fa-var-pen-alt, + "bridge-circle-exclamation": $fa-var-bridge-circle-exclamation, + "user": $fa-var-user, + "school-circle-check": $fa-var-school-circle-check, + "dumpster": $fa-var-dumpster, + "van-shuttle": $fa-var-van-shuttle, + "shuttle-van": $fa-var-shuttle-van, + "building-user": $fa-var-building-user, + "square-caret-left": $fa-var-square-caret-left, + "caret-square-left": $fa-var-caret-square-left, + "highlighter": $fa-var-highlighter, + "key": $fa-var-key, + "bullhorn": $fa-var-bullhorn, + "globe": $fa-var-globe, + "synagogue": $fa-var-synagogue, + "person-half-dress": $fa-var-person-half-dress, + "road-bridge": $fa-var-road-bridge, + "location-arrow": $fa-var-location-arrow, + "c": $fa-var-c, + "tablet-button": $fa-var-tablet-button, + "building-lock": $fa-var-building-lock, + "pizza-slice": $fa-var-pizza-slice, + "money-bill-wave": $fa-var-money-bill-wave, + "chart-area": $fa-var-chart-area, + "area-chart": $fa-var-area-chart, + "house-flag": $fa-var-house-flag, + "person-circle-minus": $fa-var-person-circle-minus, + "ban": $fa-var-ban, + "cancel": $fa-var-cancel, + "camera-rotate": $fa-var-camera-rotate, + "spray-can-sparkles": $fa-var-spray-can-sparkles, + "air-freshener": $fa-var-air-freshener, + "star": $fa-var-star, + "repeat": $fa-var-repeat, + "cross": $fa-var-cross, + "box": $fa-var-box, + "venus-mars": $fa-var-venus-mars, + "arrow-pointer": $fa-var-arrow-pointer, + "mouse-pointer": $fa-var-mouse-pointer, + "maximize": $fa-var-maximize, + "expand-arrows-alt": $fa-var-expand-arrows-alt, + "charging-station": $fa-var-charging-station, + "shapes": $fa-var-shapes, + "triangle-circle-square": $fa-var-triangle-circle-square, + "shuffle": $fa-var-shuffle, + "random": $fa-var-random, + "person-running": $fa-var-person-running, + "running": $fa-var-running, + "mobile-retro": $fa-var-mobile-retro, + "grip-lines-vertical": $fa-var-grip-lines-vertical, + "spider": $fa-var-spider, + "hands-bound": $fa-var-hands-bound, + "file-invoice-dollar": $fa-var-file-invoice-dollar, + "plane-circle-exclamation": $fa-var-plane-circle-exclamation, + "x-ray": $fa-var-x-ray, + "spell-check": $fa-var-spell-check, + "slash": $fa-var-slash, + "computer-mouse": $fa-var-computer-mouse, + "mouse": $fa-var-mouse, + "arrow-right-to-bracket": $fa-var-arrow-right-to-bracket, + "sign-in": $fa-var-sign-in, + "shop-slash": $fa-var-shop-slash, + "store-alt-slash": $fa-var-store-alt-slash, + "server": $fa-var-server, + "virus-covid-slash": $fa-var-virus-covid-slash, + "shop-lock": $fa-var-shop-lock, + "hourglass-start": $fa-var-hourglass-start, + "hourglass-1": $fa-var-hourglass-1, + "blender-phone": $fa-var-blender-phone, + "building-wheat": $fa-var-building-wheat, + "person-breastfeeding": $fa-var-person-breastfeeding, + "right-to-bracket": $fa-var-right-to-bracket, + "sign-in-alt": $fa-var-sign-in-alt, + "venus": $fa-var-venus, + "passport": $fa-var-passport, + "thumbtack-slash": $fa-var-thumbtack-slash, + "thumb-tack-slash": $fa-var-thumb-tack-slash, + "heart-pulse": $fa-var-heart-pulse, + "heartbeat": $fa-var-heartbeat, + "people-carry-box": $fa-var-people-carry-box, + "people-carry": $fa-var-people-carry, + "temperature-high": $fa-var-temperature-high, + "microchip": $fa-var-microchip, + "crown": $fa-var-crown, + "weight-hanging": $fa-var-weight-hanging, + "xmarks-lines": $fa-var-xmarks-lines, + "file-prescription": $fa-var-file-prescription, + "weight-scale": $fa-var-weight-scale, + "weight": $fa-var-weight, + "user-group": $fa-var-user-group, + "user-friends": $fa-var-user-friends, + "arrow-up-a-z": $fa-var-arrow-up-a-z, + "sort-alpha-up": $fa-var-sort-alpha-up, + "chess-knight": $fa-var-chess-knight, + "face-laugh-squint": $fa-var-face-laugh-squint, + "laugh-squint": $fa-var-laugh-squint, + "wheelchair": $fa-var-wheelchair, + "circle-arrow-up": $fa-var-circle-arrow-up, + "arrow-circle-up": $fa-var-arrow-circle-up, + "toggle-on": $fa-var-toggle-on, + "person-walking": $fa-var-person-walking, + "walking": $fa-var-walking, + "l": $fa-var-l, + "fire": $fa-var-fire, + "bed-pulse": $fa-var-bed-pulse, + "procedures": $fa-var-procedures, + "shuttle-space": $fa-var-shuttle-space, + "space-shuttle": $fa-var-space-shuttle, + "face-laugh": $fa-var-face-laugh, + "laugh": $fa-var-laugh, + "folder-open": $fa-var-folder-open, + "heart-circle-plus": $fa-var-heart-circle-plus, + "code-fork": $fa-var-code-fork, + "city": $fa-var-city, + "microphone-lines": $fa-var-microphone-lines, + "microphone-alt": $fa-var-microphone-alt, + "pepper-hot": $fa-var-pepper-hot, + "unlock": $fa-var-unlock, + "colon-sign": $fa-var-colon-sign, + "headset": $fa-var-headset, + "store-slash": $fa-var-store-slash, + "road-circle-xmark": $fa-var-road-circle-xmark, + "user-minus": $fa-var-user-minus, + "mars-stroke-up": $fa-var-mars-stroke-up, + "mars-stroke-v": $fa-var-mars-stroke-v, + "champagne-glasses": $fa-var-champagne-glasses, + "glass-cheers": $fa-var-glass-cheers, + "clipboard": $fa-var-clipboard, + "house-circle-exclamation": $fa-var-house-circle-exclamation, + "file-arrow-up": $fa-var-file-arrow-up, + "file-upload": $fa-var-file-upload, + "wifi": $fa-var-wifi, + "wifi-3": $fa-var-wifi-3, + "wifi-strong": $fa-var-wifi-strong, + "bath": $fa-var-bath, + "bathtub": $fa-var-bathtub, + "underline": $fa-var-underline, + "user-pen": $fa-var-user-pen, + "user-edit": $fa-var-user-edit, + "signature": $fa-var-signature, + "stroopwafel": $fa-var-stroopwafel, + "bold": $fa-var-bold, + "anchor-lock": $fa-var-anchor-lock, + "building-ngo": $fa-var-building-ngo, + "manat-sign": $fa-var-manat-sign, + "not-equal": $fa-var-not-equal, + "border-top-left": $fa-var-border-top-left, + "border-style": $fa-var-border-style, + "map-location-dot": $fa-var-map-location-dot, + "map-marked-alt": $fa-var-map-marked-alt, + "jedi": $fa-var-jedi, + "square-poll-vertical": $fa-var-square-poll-vertical, + "poll": $fa-var-poll, + "mug-hot": $fa-var-mug-hot, + "car-battery": $fa-var-car-battery, + "battery-car": $fa-var-battery-car, + "gift": $fa-var-gift, + "dice-two": $fa-var-dice-two, + "chess-queen": $fa-var-chess-queen, + "glasses": $fa-var-glasses, + "chess-board": $fa-var-chess-board, + "building-circle-check": $fa-var-building-circle-check, + "person-chalkboard": $fa-var-person-chalkboard, + "mars-stroke-right": $fa-var-mars-stroke-right, + "mars-stroke-h": $fa-var-mars-stroke-h, + "hand-back-fist": $fa-var-hand-back-fist, + "hand-rock": $fa-var-hand-rock, + "square-caret-up": $fa-var-square-caret-up, + "caret-square-up": $fa-var-caret-square-up, + "cloud-showers-water": $fa-var-cloud-showers-water, + "chart-bar": $fa-var-chart-bar, + "bar-chart": $fa-var-bar-chart, + "hands-bubbles": $fa-var-hands-bubbles, + "hands-wash": $fa-var-hands-wash, + "less-than-equal": $fa-var-less-than-equal, + "train": $fa-var-train, + "eye-low-vision": $fa-var-eye-low-vision, + "low-vision": $fa-var-low-vision, + "crow": $fa-var-crow, + "sailboat": $fa-var-sailboat, + "window-restore": $fa-var-window-restore, + "square-plus": $fa-var-square-plus, + "plus-square": $fa-var-plus-square, + "torii-gate": $fa-var-torii-gate, + "frog": $fa-var-frog, + "bucket": $fa-var-bucket, + "image": $fa-var-image, + "microphone": $fa-var-microphone, + "cow": $fa-var-cow, + "caret-up": $fa-var-caret-up, + "screwdriver": $fa-var-screwdriver, + "folder-closed": $fa-var-folder-closed, + "house-tsunami": $fa-var-house-tsunami, + "square-nfi": $fa-var-square-nfi, + "arrow-up-from-ground-water": $fa-var-arrow-up-from-ground-water, + "martini-glass": $fa-var-martini-glass, + "glass-martini-alt": $fa-var-glass-martini-alt, + "square-binary": $fa-var-square-binary, + "rotate-left": $fa-var-rotate-left, + "rotate-back": $fa-var-rotate-back, + "rotate-backward": $fa-var-rotate-backward, + "undo-alt": $fa-var-undo-alt, + "table-columns": $fa-var-table-columns, + "columns": $fa-var-columns, + "lemon": $fa-var-lemon, + "head-side-mask": $fa-var-head-side-mask, + "handshake": $fa-var-handshake, + "gem": $fa-var-gem, + "dolly": $fa-var-dolly, + "dolly-box": $fa-var-dolly-box, + "smoking": $fa-var-smoking, + "minimize": $fa-var-minimize, + "compress-arrows-alt": $fa-var-compress-arrows-alt, + "monument": $fa-var-monument, + "snowplow": $fa-var-snowplow, + "angles-right": $fa-var-angles-right, + "angle-double-right": $fa-var-angle-double-right, + "cannabis": $fa-var-cannabis, + "circle-play": $fa-var-circle-play, + "play-circle": $fa-var-play-circle, + "tablets": $fa-var-tablets, + "ethernet": $fa-var-ethernet, + "euro-sign": $fa-var-euro-sign, + "eur": $fa-var-eur, + "euro": $fa-var-euro, + "chair": $fa-var-chair, + "circle-check": $fa-var-circle-check, + "check-circle": $fa-var-check-circle, + "circle-stop": $fa-var-circle-stop, + "stop-circle": $fa-var-stop-circle, + "compass-drafting": $fa-var-compass-drafting, + "drafting-compass": $fa-var-drafting-compass, + "plate-wheat": $fa-var-plate-wheat, + "icicles": $fa-var-icicles, + "person-shelter": $fa-var-person-shelter, + "neuter": $fa-var-neuter, + "id-badge": $fa-var-id-badge, + "marker": $fa-var-marker, + "face-laugh-beam": $fa-var-face-laugh-beam, + "laugh-beam": $fa-var-laugh-beam, + "helicopter-symbol": $fa-var-helicopter-symbol, + "universal-access": $fa-var-universal-access, + "circle-chevron-up": $fa-var-circle-chevron-up, + "chevron-circle-up": $fa-var-chevron-circle-up, + "lari-sign": $fa-var-lari-sign, + "volcano": $fa-var-volcano, + "person-walking-dashed-line-arrow-right": $fa-var-person-walking-dashed-line-arrow-right, + "sterling-sign": $fa-var-sterling-sign, + "gbp": $fa-var-gbp, + "pound-sign": $fa-var-pound-sign, + "viruses": $fa-var-viruses, + "square-person-confined": $fa-var-square-person-confined, + "user-tie": $fa-var-user-tie, + "arrow-down-long": $fa-var-arrow-down-long, + "long-arrow-down": $fa-var-long-arrow-down, + "tent-arrow-down-to-line": $fa-var-tent-arrow-down-to-line, + "certificate": $fa-var-certificate, + "reply-all": $fa-var-reply-all, + "mail-reply-all": $fa-var-mail-reply-all, + "suitcase": $fa-var-suitcase, + "person-skating": $fa-var-person-skating, + "skating": $fa-var-skating, + "filter-circle-dollar": $fa-var-filter-circle-dollar, + "funnel-dollar": $fa-var-funnel-dollar, + "camera-retro": $fa-var-camera-retro, + "circle-arrow-down": $fa-var-circle-arrow-down, + "arrow-circle-down": $fa-var-arrow-circle-down, + "file-import": $fa-var-file-import, + "arrow-right-to-file": $fa-var-arrow-right-to-file, + "square-arrow-up-right": $fa-var-square-arrow-up-right, + "external-link-square": $fa-var-external-link-square, + "box-open": $fa-var-box-open, + "scroll": $fa-var-scroll, + "spa": $fa-var-spa, + "location-pin-lock": $fa-var-location-pin-lock, + "pause": $fa-var-pause, + "hill-avalanche": $fa-var-hill-avalanche, + "temperature-empty": $fa-var-temperature-empty, + "temperature-0": $fa-var-temperature-0, + "thermometer-0": $fa-var-thermometer-0, + "thermometer-empty": $fa-var-thermometer-empty, + "bomb": $fa-var-bomb, + "registered": $fa-var-registered, + "address-card": $fa-var-address-card, + "contact-card": $fa-var-contact-card, + "vcard": $fa-var-vcard, + "scale-unbalanced-flip": $fa-var-scale-unbalanced-flip, + "balance-scale-right": $fa-var-balance-scale-right, + "subscript": $fa-var-subscript, + "diamond-turn-right": $fa-var-diamond-turn-right, + "directions": $fa-var-directions, + "burst": $fa-var-burst, + "house-laptop": $fa-var-house-laptop, + "laptop-house": $fa-var-laptop-house, + "face-tired": $fa-var-face-tired, + "tired": $fa-var-tired, + "money-bills": $fa-var-money-bills, + "smog": $fa-var-smog, + "crutch": $fa-var-crutch, + "cloud-arrow-up": $fa-var-cloud-arrow-up, + "cloud-upload": $fa-var-cloud-upload, + "cloud-upload-alt": $fa-var-cloud-upload-alt, + "palette": $fa-var-palette, + "arrows-turn-right": $fa-var-arrows-turn-right, + "vest": $fa-var-vest, + "ferry": $fa-var-ferry, + "arrows-down-to-people": $fa-var-arrows-down-to-people, + "seedling": $fa-var-seedling, + "sprout": $fa-var-sprout, + "left-right": $fa-var-left-right, + "arrows-alt-h": $fa-var-arrows-alt-h, + "boxes-packing": $fa-var-boxes-packing, + "circle-arrow-left": $fa-var-circle-arrow-left, + "arrow-circle-left": $fa-var-arrow-circle-left, + "group-arrows-rotate": $fa-var-group-arrows-rotate, + "bowl-food": $fa-var-bowl-food, + "candy-cane": $fa-var-candy-cane, + "arrow-down-wide-short": $fa-var-arrow-down-wide-short, + "sort-amount-asc": $fa-var-sort-amount-asc, + "sort-amount-down": $fa-var-sort-amount-down, + "cloud-bolt": $fa-var-cloud-bolt, + "thunderstorm": $fa-var-thunderstorm, + "text-slash": $fa-var-text-slash, + "remove-format": $fa-var-remove-format, + "face-smile-wink": $fa-var-face-smile-wink, + "smile-wink": $fa-var-smile-wink, + "file-word": $fa-var-file-word, + "file-powerpoint": $fa-var-file-powerpoint, + "arrows-left-right": $fa-var-arrows-left-right, + "arrows-h": $fa-var-arrows-h, + "house-lock": $fa-var-house-lock, + "cloud-arrow-down": $fa-var-cloud-arrow-down, + "cloud-download": $fa-var-cloud-download, + "cloud-download-alt": $fa-var-cloud-download-alt, + "children": $fa-var-children, + "chalkboard": $fa-var-chalkboard, + "blackboard": $fa-var-blackboard, + "user-large-slash": $fa-var-user-large-slash, + "user-alt-slash": $fa-var-user-alt-slash, + "envelope-open": $fa-var-envelope-open, + "handshake-simple-slash": $fa-var-handshake-simple-slash, + "handshake-alt-slash": $fa-var-handshake-alt-slash, + "mattress-pillow": $fa-var-mattress-pillow, + "guarani-sign": $fa-var-guarani-sign, + "arrows-rotate": $fa-var-arrows-rotate, + "refresh": $fa-var-refresh, + "sync": $fa-var-sync, + "fire-extinguisher": $fa-var-fire-extinguisher, + "cruzeiro-sign": $fa-var-cruzeiro-sign, + "greater-than-equal": $fa-var-greater-than-equal, + "shield-halved": $fa-var-shield-halved, + "shield-alt": $fa-var-shield-alt, + "book-atlas": $fa-var-book-atlas, + "atlas": $fa-var-atlas, + "virus": $fa-var-virus, + "envelope-circle-check": $fa-var-envelope-circle-check, + "layer-group": $fa-var-layer-group, + "arrows-to-dot": $fa-var-arrows-to-dot, + "archway": $fa-var-archway, + "heart-circle-check": $fa-var-heart-circle-check, + "house-chimney-crack": $fa-var-house-chimney-crack, + "house-damage": $fa-var-house-damage, + "file-zipper": $fa-var-file-zipper, + "file-archive": $fa-var-file-archive, + "square": $fa-var-square, + "martini-glass-empty": $fa-var-martini-glass-empty, + "glass-martini": $fa-var-glass-martini, + "couch": $fa-var-couch, + "cedi-sign": $fa-var-cedi-sign, + "italic": $fa-var-italic, + "table-cells-column-lock": $fa-var-table-cells-column-lock, + "church": $fa-var-church, + "comments-dollar": $fa-var-comments-dollar, + "democrat": $fa-var-democrat, + "z": $fa-var-z, + "person-skiing": $fa-var-person-skiing, + "skiing": $fa-var-skiing, + "road-lock": $fa-var-road-lock, + "a": $fa-var-a, + "temperature-arrow-down": $fa-var-temperature-arrow-down, + "temperature-down": $fa-var-temperature-down, + "feather-pointed": $fa-var-feather-pointed, + "feather-alt": $fa-var-feather-alt, + "p": $fa-var-p, + "snowflake": $fa-var-snowflake, + "newspaper": $fa-var-newspaper, + "rectangle-ad": $fa-var-rectangle-ad, + "ad": $fa-var-ad, + "circle-arrow-right": $fa-var-circle-arrow-right, + "arrow-circle-right": $fa-var-arrow-circle-right, + "filter-circle-xmark": $fa-var-filter-circle-xmark, + "locust": $fa-var-locust, + "sort": $fa-var-sort, + "unsorted": $fa-var-unsorted, + "list-ol": $fa-var-list-ol, + "list-1-2": $fa-var-list-1-2, + "list-numeric": $fa-var-list-numeric, + "person-dress-burst": $fa-var-person-dress-burst, + "money-check-dollar": $fa-var-money-check-dollar, + "money-check-alt": $fa-var-money-check-alt, + "vector-square": $fa-var-vector-square, + "bread-slice": $fa-var-bread-slice, + "language": $fa-var-language, + "face-kiss-wink-heart": $fa-var-face-kiss-wink-heart, + "kiss-wink-heart": $fa-var-kiss-wink-heart, + "filter": $fa-var-filter, + "question": $fa-var-question, + "file-signature": $fa-var-file-signature, + "up-down-left-right": $fa-var-up-down-left-right, + "arrows-alt": $fa-var-arrows-alt, + "house-chimney-user": $fa-var-house-chimney-user, + "hand-holding-heart": $fa-var-hand-holding-heart, + "puzzle-piece": $fa-var-puzzle-piece, + "money-check": $fa-var-money-check, + "star-half-stroke": $fa-var-star-half-stroke, + "star-half-alt": $fa-var-star-half-alt, + "code": $fa-var-code, + "whiskey-glass": $fa-var-whiskey-glass, + "glass-whiskey": $fa-var-glass-whiskey, + "building-circle-exclamation": $fa-var-building-circle-exclamation, + "magnifying-glass-chart": $fa-var-magnifying-glass-chart, + "arrow-up-right-from-square": $fa-var-arrow-up-right-from-square, + "external-link": $fa-var-external-link, + "cubes-stacked": $fa-var-cubes-stacked, + "won-sign": $fa-var-won-sign, + "krw": $fa-var-krw, + "won": $fa-var-won, + "virus-covid": $fa-var-virus-covid, + "austral-sign": $fa-var-austral-sign, + "f": $fa-var-f, + "leaf": $fa-var-leaf, + "road": $fa-var-road, + "taxi": $fa-var-taxi, + "cab": $fa-var-cab, + "person-circle-plus": $fa-var-person-circle-plus, + "chart-pie": $fa-var-chart-pie, + "pie-chart": $fa-var-pie-chart, + "bolt-lightning": $fa-var-bolt-lightning, + "sack-xmark": $fa-var-sack-xmark, + "file-excel": $fa-var-file-excel, + "file-contract": $fa-var-file-contract, + "fish-fins": $fa-var-fish-fins, + "building-flag": $fa-var-building-flag, + "face-grin-beam": $fa-var-face-grin-beam, + "grin-beam": $fa-var-grin-beam, + "object-ungroup": $fa-var-object-ungroup, + "poop": $fa-var-poop, + "location-pin": $fa-var-location-pin, + "map-marker": $fa-var-map-marker, + "kaaba": $fa-var-kaaba, + "toilet-paper": $fa-var-toilet-paper, + "helmet-safety": $fa-var-helmet-safety, + "hard-hat": $fa-var-hard-hat, + "hat-hard": $fa-var-hat-hard, + "eject": $fa-var-eject, + "circle-right": $fa-var-circle-right, + "arrow-alt-circle-right": $fa-var-arrow-alt-circle-right, + "plane-circle-check": $fa-var-plane-circle-check, + "face-rolling-eyes": $fa-var-face-rolling-eyes, + "meh-rolling-eyes": $fa-var-meh-rolling-eyes, + "object-group": $fa-var-object-group, + "chart-line": $fa-var-chart-line, + "line-chart": $fa-var-line-chart, + "mask-ventilator": $fa-var-mask-ventilator, + "arrow-right": $fa-var-arrow-right, + "signs-post": $fa-var-signs-post, + "map-signs": $fa-var-map-signs, + "cash-register": $fa-var-cash-register, + "person-circle-question": $fa-var-person-circle-question, + "h": $fa-var-h, + "tarp": $fa-var-tarp, + "screwdriver-wrench": $fa-var-screwdriver-wrench, + "tools": $fa-var-tools, + "arrows-to-eye": $fa-var-arrows-to-eye, + "plug-circle-bolt": $fa-var-plug-circle-bolt, + "heart": $fa-var-heart, + "mars-and-venus": $fa-var-mars-and-venus, + "house-user": $fa-var-house-user, + "home-user": $fa-var-home-user, + "dumpster-fire": $fa-var-dumpster-fire, + "house-crack": $fa-var-house-crack, + "martini-glass-citrus": $fa-var-martini-glass-citrus, + "cocktail": $fa-var-cocktail, + "face-surprise": $fa-var-face-surprise, + "surprise": $fa-var-surprise, + "bottle-water": $fa-var-bottle-water, + "circle-pause": $fa-var-circle-pause, + "pause-circle": $fa-var-pause-circle, + "toilet-paper-slash": $fa-var-toilet-paper-slash, + "apple-whole": $fa-var-apple-whole, + "apple-alt": $fa-var-apple-alt, + "kitchen-set": $fa-var-kitchen-set, + "r": $fa-var-r, + "temperature-quarter": $fa-var-temperature-quarter, + "temperature-1": $fa-var-temperature-1, + "thermometer-1": $fa-var-thermometer-1, + "thermometer-quarter": $fa-var-thermometer-quarter, + "cube": $fa-var-cube, + "bitcoin-sign": $fa-var-bitcoin-sign, + "shield-dog": $fa-var-shield-dog, + "solar-panel": $fa-var-solar-panel, + "lock-open": $fa-var-lock-open, + "elevator": $fa-var-elevator, + "money-bill-transfer": $fa-var-money-bill-transfer, + "money-bill-trend-up": $fa-var-money-bill-trend-up, + "house-flood-water-circle-arrow-right": $fa-var-house-flood-water-circle-arrow-right, + "square-poll-horizontal": $fa-var-square-poll-horizontal, + "poll-h": $fa-var-poll-h, + "circle": $fa-var-circle, + "backward-fast": $fa-var-backward-fast, + "fast-backward": $fa-var-fast-backward, + "recycle": $fa-var-recycle, + "user-astronaut": $fa-var-user-astronaut, + "plane-slash": $fa-var-plane-slash, + "trademark": $fa-var-trademark, + "basketball": $fa-var-basketball, + "basketball-ball": $fa-var-basketball-ball, + "satellite-dish": $fa-var-satellite-dish, + "circle-up": $fa-var-circle-up, + "arrow-alt-circle-up": $fa-var-arrow-alt-circle-up, + "mobile-screen-button": $fa-var-mobile-screen-button, + "mobile-alt": $fa-var-mobile-alt, + "volume-high": $fa-var-volume-high, + "volume-up": $fa-var-volume-up, + "users-rays": $fa-var-users-rays, + "wallet": $fa-var-wallet, + "clipboard-check": $fa-var-clipboard-check, + "file-audio": $fa-var-file-audio, + "burger": $fa-var-burger, + "hamburger": $fa-var-hamburger, + "wrench": $fa-var-wrench, + "bugs": $fa-var-bugs, + "rupee-sign": $fa-var-rupee-sign, + "rupee": $fa-var-rupee, + "file-image": $fa-var-file-image, + "circle-question": $fa-var-circle-question, + "question-circle": $fa-var-question-circle, + "plane-departure": $fa-var-plane-departure, + "handshake-slash": $fa-var-handshake-slash, + "book-bookmark": $fa-var-book-bookmark, + "code-branch": $fa-var-code-branch, + "hat-cowboy": $fa-var-hat-cowboy, + "bridge": $fa-var-bridge, + "phone-flip": $fa-var-phone-flip, + "phone-alt": $fa-var-phone-alt, + "truck-front": $fa-var-truck-front, + "cat": $fa-var-cat, + "anchor-circle-exclamation": $fa-var-anchor-circle-exclamation, + "truck-field": $fa-var-truck-field, + "route": $fa-var-route, + "clipboard-question": $fa-var-clipboard-question, + "panorama": $fa-var-panorama, + "comment-medical": $fa-var-comment-medical, + "teeth-open": $fa-var-teeth-open, + "file-circle-minus": $fa-var-file-circle-minus, + "tags": $fa-var-tags, + "wine-glass": $fa-var-wine-glass, + "forward-fast": $fa-var-forward-fast, + "fast-forward": $fa-var-fast-forward, + "face-meh-blank": $fa-var-face-meh-blank, + "meh-blank": $fa-var-meh-blank, + "square-parking": $fa-var-square-parking, + "parking": $fa-var-parking, + "house-signal": $fa-var-house-signal, + "bars-progress": $fa-var-bars-progress, + "tasks-alt": $fa-var-tasks-alt, + "faucet-drip": $fa-var-faucet-drip, + "cart-flatbed": $fa-var-cart-flatbed, + "dolly-flatbed": $fa-var-dolly-flatbed, + "ban-smoking": $fa-var-ban-smoking, + "smoking-ban": $fa-var-smoking-ban, + "terminal": $fa-var-terminal, + "mobile-button": $fa-var-mobile-button, + "house-medical-flag": $fa-var-house-medical-flag, + "basket-shopping": $fa-var-basket-shopping, + "shopping-basket": $fa-var-shopping-basket, + "tape": $fa-var-tape, + "bus-simple": $fa-var-bus-simple, + "bus-alt": $fa-var-bus-alt, + "eye": $fa-var-eye, + "face-sad-cry": $fa-var-face-sad-cry, + "sad-cry": $fa-var-sad-cry, + "audio-description": $fa-var-audio-description, + "person-military-to-person": $fa-var-person-military-to-person, + "file-shield": $fa-var-file-shield, + "user-slash": $fa-var-user-slash, + "pen": $fa-var-pen, + "tower-observation": $fa-var-tower-observation, + "file-code": $fa-var-file-code, + "signal": $fa-var-signal, + "signal-5": $fa-var-signal-5, + "signal-perfect": $fa-var-signal-perfect, + "bus": $fa-var-bus, + "heart-circle-xmark": $fa-var-heart-circle-xmark, + "house-chimney": $fa-var-house-chimney, + "home-lg": $fa-var-home-lg, + "window-maximize": $fa-var-window-maximize, + "face-frown": $fa-var-face-frown, + "frown": $fa-var-frown, + "prescription": $fa-var-prescription, + "shop": $fa-var-shop, + "store-alt": $fa-var-store-alt, + "floppy-disk": $fa-var-floppy-disk, + "save": $fa-var-save, + "vihara": $fa-var-vihara, + "scale-unbalanced": $fa-var-scale-unbalanced, + "balance-scale-left": $fa-var-balance-scale-left, + "sort-up": $fa-var-sort-up, + "sort-asc": $fa-var-sort-asc, + "comment-dots": $fa-var-comment-dots, + "commenting": $fa-var-commenting, + "plant-wilt": $fa-var-plant-wilt, + "diamond": $fa-var-diamond, + "face-grin-squint": $fa-var-face-grin-squint, + "grin-squint": $fa-var-grin-squint, + "hand-holding-dollar": $fa-var-hand-holding-dollar, + "hand-holding-usd": $fa-var-hand-holding-usd, + "chart-diagram": $fa-var-chart-diagram, + "bacterium": $fa-var-bacterium, + "hand-pointer": $fa-var-hand-pointer, + "drum-steelpan": $fa-var-drum-steelpan, + "hand-scissors": $fa-var-hand-scissors, + "hands-praying": $fa-var-hands-praying, + "praying-hands": $fa-var-praying-hands, + "arrow-rotate-right": $fa-var-arrow-rotate-right, + "arrow-right-rotate": $fa-var-arrow-right-rotate, + "arrow-rotate-forward": $fa-var-arrow-rotate-forward, + "redo": $fa-var-redo, + "biohazard": $fa-var-biohazard, + "location-crosshairs": $fa-var-location-crosshairs, + "location": $fa-var-location, + "mars-double": $fa-var-mars-double, + "child-dress": $fa-var-child-dress, + "users-between-lines": $fa-var-users-between-lines, + "lungs-virus": $fa-var-lungs-virus, + "face-grin-tears": $fa-var-face-grin-tears, + "grin-tears": $fa-var-grin-tears, + "phone": $fa-var-phone, + "calendar-xmark": $fa-var-calendar-xmark, + "calendar-times": $fa-var-calendar-times, + "child-reaching": $fa-var-child-reaching, + "head-side-virus": $fa-var-head-side-virus, + "user-gear": $fa-var-user-gear, + "user-cog": $fa-var-user-cog, + "arrow-up-1-9": $fa-var-arrow-up-1-9, + "sort-numeric-up": $fa-var-sort-numeric-up, + "door-closed": $fa-var-door-closed, + "shield-virus": $fa-var-shield-virus, + "dice-six": $fa-var-dice-six, + "mosquito-net": $fa-var-mosquito-net, + "file-fragment": $fa-var-file-fragment, + "bridge-water": $fa-var-bridge-water, + "person-booth": $fa-var-person-booth, + "text-width": $fa-var-text-width, + "hat-wizard": $fa-var-hat-wizard, + "pen-fancy": $fa-var-pen-fancy, + "person-digging": $fa-var-person-digging, + "digging": $fa-var-digging, + "trash": $fa-var-trash, + "gauge-simple": $fa-var-gauge-simple, + "gauge-simple-med": $fa-var-gauge-simple-med, + "tachometer-average": $fa-var-tachometer-average, + "book-medical": $fa-var-book-medical, + "poo": $fa-var-poo, + "quote-right": $fa-var-quote-right, + "quote-right-alt": $fa-var-quote-right-alt, + "shirt": $fa-var-shirt, + "t-shirt": $fa-var-t-shirt, + "tshirt": $fa-var-tshirt, + "cubes": $fa-var-cubes, + "divide": $fa-var-divide, + "tenge-sign": $fa-var-tenge-sign, + "tenge": $fa-var-tenge, + "headphones": $fa-var-headphones, + "hands-holding": $fa-var-hands-holding, + "hands-clapping": $fa-var-hands-clapping, + "republican": $fa-var-republican, + "arrow-left": $fa-var-arrow-left, + "person-circle-xmark": $fa-var-person-circle-xmark, + "ruler": $fa-var-ruler, + "align-left": $fa-var-align-left, + "dice-d6": $fa-var-dice-d6, + "restroom": $fa-var-restroom, + "j": $fa-var-j, + "users-viewfinder": $fa-var-users-viewfinder, + "file-video": $fa-var-file-video, + "up-right-from-square": $fa-var-up-right-from-square, + "external-link-alt": $fa-var-external-link-alt, + "table-cells": $fa-var-table-cells, + "th": $fa-var-th, + "file-pdf": $fa-var-file-pdf, + "book-bible": $fa-var-book-bible, + "bible": $fa-var-bible, + "o": $fa-var-o, + "suitcase-medical": $fa-var-suitcase-medical, + "medkit": $fa-var-medkit, + "user-secret": $fa-var-user-secret, + "otter": $fa-var-otter, + "person-dress": $fa-var-person-dress, + "female": $fa-var-female, + "comment-dollar": $fa-var-comment-dollar, + "business-time": $fa-var-business-time, + "briefcase-clock": $fa-var-briefcase-clock, + "table-cells-large": $fa-var-table-cells-large, + "th-large": $fa-var-th-large, + "book-tanakh": $fa-var-book-tanakh, + "tanakh": $fa-var-tanakh, + "phone-volume": $fa-var-phone-volume, + "volume-control-phone": $fa-var-volume-control-phone, + "hat-cowboy-side": $fa-var-hat-cowboy-side, + "clipboard-user": $fa-var-clipboard-user, + "child": $fa-var-child, + "lira-sign": $fa-var-lira-sign, + "satellite": $fa-var-satellite, + "plane-lock": $fa-var-plane-lock, + "tag": $fa-var-tag, + "comment": $fa-var-comment, + "cake-candles": $fa-var-cake-candles, + "birthday-cake": $fa-var-birthday-cake, + "cake": $fa-var-cake, + "envelope": $fa-var-envelope, + "angles-up": $fa-var-angles-up, + "angle-double-up": $fa-var-angle-double-up, + "paperclip": $fa-var-paperclip, + "arrow-right-to-city": $fa-var-arrow-right-to-city, + "ribbon": $fa-var-ribbon, + "lungs": $fa-var-lungs, + "arrow-up-9-1": $fa-var-arrow-up-9-1, + "sort-numeric-up-alt": $fa-var-sort-numeric-up-alt, + "litecoin-sign": $fa-var-litecoin-sign, + "border-none": $fa-var-border-none, + "circle-nodes": $fa-var-circle-nodes, + "parachute-box": $fa-var-parachute-box, + "indent": $fa-var-indent, + "truck-field-un": $fa-var-truck-field-un, + "hourglass": $fa-var-hourglass, + "hourglass-empty": $fa-var-hourglass-empty, + "mountain": $fa-var-mountain, + "user-doctor": $fa-var-user-doctor, + "user-md": $fa-var-user-md, + "circle-info": $fa-var-circle-info, + "info-circle": $fa-var-info-circle, + "cloud-meatball": $fa-var-cloud-meatball, + "camera": $fa-var-camera, + "camera-alt": $fa-var-camera-alt, + "square-virus": $fa-var-square-virus, + "meteor": $fa-var-meteor, + "car-on": $fa-var-car-on, + "sleigh": $fa-var-sleigh, + "arrow-down-1-9": $fa-var-arrow-down-1-9, + "sort-numeric-asc": $fa-var-sort-numeric-asc, + "sort-numeric-down": $fa-var-sort-numeric-down, + "hand-holding-droplet": $fa-var-hand-holding-droplet, + "hand-holding-water": $fa-var-hand-holding-water, + "water": $fa-var-water, + "calendar-check": $fa-var-calendar-check, + "braille": $fa-var-braille, + "prescription-bottle-medical": $fa-var-prescription-bottle-medical, + "prescription-bottle-alt": $fa-var-prescription-bottle-alt, + "landmark": $fa-var-landmark, + "truck": $fa-var-truck, + "crosshairs": $fa-var-crosshairs, + "person-cane": $fa-var-person-cane, + "tent": $fa-var-tent, + "vest-patches": $fa-var-vest-patches, + "check-double": $fa-var-check-double, + "arrow-down-a-z": $fa-var-arrow-down-a-z, + "sort-alpha-asc": $fa-var-sort-alpha-asc, + "sort-alpha-down": $fa-var-sort-alpha-down, + "money-bill-wheat": $fa-var-money-bill-wheat, + "cookie": $fa-var-cookie, + "arrow-rotate-left": $fa-var-arrow-rotate-left, + "arrow-left-rotate": $fa-var-arrow-left-rotate, + "arrow-rotate-back": $fa-var-arrow-rotate-back, + "arrow-rotate-backward": $fa-var-arrow-rotate-backward, + "undo": $fa-var-undo, + "hard-drive": $fa-var-hard-drive, + "hdd": $fa-var-hdd, + "face-grin-squint-tears": $fa-var-face-grin-squint-tears, + "grin-squint-tears": $fa-var-grin-squint-tears, + "dumbbell": $fa-var-dumbbell, + "rectangle-list": $fa-var-rectangle-list, + "list-alt": $fa-var-list-alt, + "tarp-droplet": $fa-var-tarp-droplet, + "house-medical-circle-check": $fa-var-house-medical-circle-check, + "person-skiing-nordic": $fa-var-person-skiing-nordic, + "skiing-nordic": $fa-var-skiing-nordic, + "calendar-plus": $fa-var-calendar-plus, + "plane-arrival": $fa-var-plane-arrival, + "circle-left": $fa-var-circle-left, + "arrow-alt-circle-left": $fa-var-arrow-alt-circle-left, + "train-subway": $fa-var-train-subway, + "subway": $fa-var-subway, + "chart-gantt": $fa-var-chart-gantt, + "indian-rupee-sign": $fa-var-indian-rupee-sign, + "indian-rupee": $fa-var-indian-rupee, + "inr": $fa-var-inr, + "crop-simple": $fa-var-crop-simple, + "crop-alt": $fa-var-crop-alt, + "money-bill-1": $fa-var-money-bill-1, + "money-bill-alt": $fa-var-money-bill-alt, + "left-long": $fa-var-left-long, + "long-arrow-alt-left": $fa-var-long-arrow-alt-left, + "dna": $fa-var-dna, + "virus-slash": $fa-var-virus-slash, + "minus": $fa-var-minus, + "subtract": $fa-var-subtract, + "chess": $fa-var-chess, + "arrow-left-long": $fa-var-arrow-left-long, + "long-arrow-left": $fa-var-long-arrow-left, + "plug-circle-check": $fa-var-plug-circle-check, + "street-view": $fa-var-street-view, + "franc-sign": $fa-var-franc-sign, + "volume-off": $fa-var-volume-off, + "hands-asl-interpreting": $fa-var-hands-asl-interpreting, + "american-sign-language-interpreting": $fa-var-american-sign-language-interpreting, + "asl-interpreting": $fa-var-asl-interpreting, + "hands-american-sign-language-interpreting": $fa-var-hands-american-sign-language-interpreting, + "gear": $fa-var-gear, + "cog": $fa-var-cog, + "droplet-slash": $fa-var-droplet-slash, + "tint-slash": $fa-var-tint-slash, + "mosque": $fa-var-mosque, + "mosquito": $fa-var-mosquito, + "star-of-david": $fa-var-star-of-david, + "person-military-rifle": $fa-var-person-military-rifle, + "cart-shopping": $fa-var-cart-shopping, + "shopping-cart": $fa-var-shopping-cart, + "vials": $fa-var-vials, + "plug-circle-plus": $fa-var-plug-circle-plus, + "place-of-worship": $fa-var-place-of-worship, + "grip-vertical": $fa-var-grip-vertical, + "hexagon-nodes": $fa-var-hexagon-nodes, + "arrow-turn-up": $fa-var-arrow-turn-up, + "level-up": $fa-var-level-up, + "u": $fa-var-u, + "square-root-variable": $fa-var-square-root-variable, + "square-root-alt": $fa-var-square-root-alt, + "clock": $fa-var-clock, + "clock-four": $fa-var-clock-four, + "backward-step": $fa-var-backward-step, + "step-backward": $fa-var-step-backward, + "pallet": $fa-var-pallet, + "faucet": $fa-var-faucet, + "baseball-bat-ball": $fa-var-baseball-bat-ball, + "s": $fa-var-s, + "timeline": $fa-var-timeline, + "keyboard": $fa-var-keyboard, + "caret-down": $fa-var-caret-down, + "house-chimney-medical": $fa-var-house-chimney-medical, + "clinic-medical": $fa-var-clinic-medical, + "temperature-three-quarters": $fa-var-temperature-three-quarters, + "temperature-3": $fa-var-temperature-3, + "thermometer-3": $fa-var-thermometer-3, + "thermometer-three-quarters": $fa-var-thermometer-three-quarters, + "mobile-screen": $fa-var-mobile-screen, + "mobile-android-alt": $fa-var-mobile-android-alt, + "plane-up": $fa-var-plane-up, + "piggy-bank": $fa-var-piggy-bank, + "battery-half": $fa-var-battery-half, + "battery-3": $fa-var-battery-3, + "mountain-city": $fa-var-mountain-city, + "coins": $fa-var-coins, + "khanda": $fa-var-khanda, + "sliders": $fa-var-sliders, + "sliders-h": $fa-var-sliders-h, + "folder-tree": $fa-var-folder-tree, + "network-wired": $fa-var-network-wired, + "map-pin": $fa-var-map-pin, + "hamsa": $fa-var-hamsa, + "cent-sign": $fa-var-cent-sign, + "flask": $fa-var-flask, + "person-pregnant": $fa-var-person-pregnant, + "wand-sparkles": $fa-var-wand-sparkles, + "ellipsis-vertical": $fa-var-ellipsis-vertical, + "ellipsis-v": $fa-var-ellipsis-v, + "ticket": $fa-var-ticket, + "power-off": $fa-var-power-off, + "right-long": $fa-var-right-long, + "long-arrow-alt-right": $fa-var-long-arrow-alt-right, + "flag-usa": $fa-var-flag-usa, + "laptop-file": $fa-var-laptop-file, + "tty": $fa-var-tty, + "teletype": $fa-var-teletype, + "diagram-next": $fa-var-diagram-next, + "person-rifle": $fa-var-person-rifle, + "house-medical-circle-exclamation": $fa-var-house-medical-circle-exclamation, + "closed-captioning": $fa-var-closed-captioning, + "person-hiking": $fa-var-person-hiking, + "hiking": $fa-var-hiking, + "venus-double": $fa-var-venus-double, + "images": $fa-var-images, + "calculator": $fa-var-calculator, + "people-pulling": $fa-var-people-pulling, + "n": $fa-var-n, + "cable-car": $fa-var-cable-car, + "tram": $fa-var-tram, + "cloud-rain": $fa-var-cloud-rain, + "building-circle-xmark": $fa-var-building-circle-xmark, + "ship": $fa-var-ship, + "arrows-down-to-line": $fa-var-arrows-down-to-line, + "download": $fa-var-download, + "face-grin": $fa-var-face-grin, + "grin": $fa-var-grin, + "delete-left": $fa-var-delete-left, + "backspace": $fa-var-backspace, + "eye-dropper": $fa-var-eye-dropper, + "eye-dropper-empty": $fa-var-eye-dropper-empty, + "eyedropper": $fa-var-eyedropper, + "file-circle-check": $fa-var-file-circle-check, + "forward": $fa-var-forward, + "mobile": $fa-var-mobile, + "mobile-android": $fa-var-mobile-android, + "mobile-phone": $fa-var-mobile-phone, + "face-meh": $fa-var-face-meh, + "meh": $fa-var-meh, + "align-center": $fa-var-align-center, + "book-skull": $fa-var-book-skull, + "book-dead": $fa-var-book-dead, + "id-card": $fa-var-id-card, + "drivers-license": $fa-var-drivers-license, + "outdent": $fa-var-outdent, + "dedent": $fa-var-dedent, + "heart-circle-exclamation": $fa-var-heart-circle-exclamation, + "house": $fa-var-house, + "home": $fa-var-home, + "home-alt": $fa-var-home-alt, + "home-lg-alt": $fa-var-home-lg-alt, + "calendar-week": $fa-var-calendar-week, + "laptop-medical": $fa-var-laptop-medical, + "b": $fa-var-b, + "file-medical": $fa-var-file-medical, + "dice-one": $fa-var-dice-one, + "kiwi-bird": $fa-var-kiwi-bird, + "arrow-right-arrow-left": $fa-var-arrow-right-arrow-left, + "exchange": $fa-var-exchange, + "rotate-right": $fa-var-rotate-right, + "redo-alt": $fa-var-redo-alt, + "rotate-forward": $fa-var-rotate-forward, + "utensils": $fa-var-utensils, + "cutlery": $fa-var-cutlery, + "arrow-up-wide-short": $fa-var-arrow-up-wide-short, + "sort-amount-up": $fa-var-sort-amount-up, + "mill-sign": $fa-var-mill-sign, + "bowl-rice": $fa-var-bowl-rice, + "skull": $fa-var-skull, + "tower-broadcast": $fa-var-tower-broadcast, + "broadcast-tower": $fa-var-broadcast-tower, + "truck-pickup": $fa-var-truck-pickup, + "up-long": $fa-var-up-long, + "long-arrow-alt-up": $fa-var-long-arrow-alt-up, + "stop": $fa-var-stop, + "code-merge": $fa-var-code-merge, + "upload": $fa-var-upload, + "hurricane": $fa-var-hurricane, + "mound": $fa-var-mound, + "toilet-portable": $fa-var-toilet-portable, + "compact-disc": $fa-var-compact-disc, + "file-arrow-down": $fa-var-file-arrow-down, + "file-download": $fa-var-file-download, + "caravan": $fa-var-caravan, + "shield-cat": $fa-var-shield-cat, + "bolt": $fa-var-bolt, + "zap": $fa-var-zap, + "glass-water": $fa-var-glass-water, + "oil-well": $fa-var-oil-well, + "vault": $fa-var-vault, + "mars": $fa-var-mars, + "toilet": $fa-var-toilet, + "plane-circle-xmark": $fa-var-plane-circle-xmark, + "yen-sign": $fa-var-yen-sign, + "cny": $fa-var-cny, + "jpy": $fa-var-jpy, + "rmb": $fa-var-rmb, + "yen": $fa-var-yen, + "ruble-sign": $fa-var-ruble-sign, + "rouble": $fa-var-rouble, + "rub": $fa-var-rub, + "ruble": $fa-var-ruble, + "sun": $fa-var-sun, + "guitar": $fa-var-guitar, + "face-laugh-wink": $fa-var-face-laugh-wink, + "laugh-wink": $fa-var-laugh-wink, + "horse-head": $fa-var-horse-head, + "bore-hole": $fa-var-bore-hole, + "industry": $fa-var-industry, + "circle-down": $fa-var-circle-down, + "arrow-alt-circle-down": $fa-var-arrow-alt-circle-down, + "arrows-turn-to-dots": $fa-var-arrows-turn-to-dots, + "florin-sign": $fa-var-florin-sign, + "arrow-down-short-wide": $fa-var-arrow-down-short-wide, + "sort-amount-desc": $fa-var-sort-amount-desc, + "sort-amount-down-alt": $fa-var-sort-amount-down-alt, + "less-than": $fa-var-less-than, + "angle-down": $fa-var-angle-down, + "car-tunnel": $fa-var-car-tunnel, + "head-side-cough": $fa-var-head-side-cough, + "grip-lines": $fa-var-grip-lines, + "thumbs-down": $fa-var-thumbs-down, + "user-lock": $fa-var-user-lock, + "arrow-right-long": $fa-var-arrow-right-long, + "long-arrow-right": $fa-var-long-arrow-right, + "anchor-circle-xmark": $fa-var-anchor-circle-xmark, + "ellipsis": $fa-var-ellipsis, + "ellipsis-h": $fa-var-ellipsis-h, + "chess-pawn": $fa-var-chess-pawn, + "kit-medical": $fa-var-kit-medical, + "first-aid": $fa-var-first-aid, + "person-through-window": $fa-var-person-through-window, + "toolbox": $fa-var-toolbox, + "hands-holding-circle": $fa-var-hands-holding-circle, + "bug": $fa-var-bug, + "credit-card": $fa-var-credit-card, + "credit-card-alt": $fa-var-credit-card-alt, + "car": $fa-var-car, + "automobile": $fa-var-automobile, + "hand-holding-hand": $fa-var-hand-holding-hand, + "book-open-reader": $fa-var-book-open-reader, + "book-reader": $fa-var-book-reader, + "mountain-sun": $fa-var-mountain-sun, + "arrows-left-right-to-line": $fa-var-arrows-left-right-to-line, + "dice-d20": $fa-var-dice-d20, + "truck-droplet": $fa-var-truck-droplet, + "file-circle-xmark": $fa-var-file-circle-xmark, + "temperature-arrow-up": $fa-var-temperature-arrow-up, + "temperature-up": $fa-var-temperature-up, + "medal": $fa-var-medal, + "bed": $fa-var-bed, + "square-h": $fa-var-square-h, + "h-square": $fa-var-h-square, + "podcast": $fa-var-podcast, + "temperature-full": $fa-var-temperature-full, + "temperature-4": $fa-var-temperature-4, + "thermometer-4": $fa-var-thermometer-4, + "thermometer-full": $fa-var-thermometer-full, + "bell": $fa-var-bell, + "superscript": $fa-var-superscript, + "plug-circle-xmark": $fa-var-plug-circle-xmark, + "star-of-life": $fa-var-star-of-life, + "phone-slash": $fa-var-phone-slash, + "paint-roller": $fa-var-paint-roller, + "handshake-angle": $fa-var-handshake-angle, + "hands-helping": $fa-var-hands-helping, + "location-dot": $fa-var-location-dot, + "map-marker-alt": $fa-var-map-marker-alt, + "file": $fa-var-file, + "greater-than": $fa-var-greater-than, + "person-swimming": $fa-var-person-swimming, + "swimmer": $fa-var-swimmer, + "arrow-down": $fa-var-arrow-down, + "droplet": $fa-var-droplet, + "tint": $fa-var-tint, + "eraser": $fa-var-eraser, + "earth-americas": $fa-var-earth-americas, + "earth": $fa-var-earth, + "earth-america": $fa-var-earth-america, + "globe-americas": $fa-var-globe-americas, + "person-burst": $fa-var-person-burst, + "dove": $fa-var-dove, + "battery-empty": $fa-var-battery-empty, + "battery-0": $fa-var-battery-0, + "socks": $fa-var-socks, + "inbox": $fa-var-inbox, + "section": $fa-var-section, + "gauge-high": $fa-var-gauge-high, + "tachometer-alt": $fa-var-tachometer-alt, + "tachometer-alt-fast": $fa-var-tachometer-alt-fast, + "envelope-open-text": $fa-var-envelope-open-text, + "hospital": $fa-var-hospital, + "hospital-alt": $fa-var-hospital-alt, + "hospital-wide": $fa-var-hospital-wide, + "wine-bottle": $fa-var-wine-bottle, + "chess-rook": $fa-var-chess-rook, + "bars-staggered": $fa-var-bars-staggered, + "reorder": $fa-var-reorder, + "stream": $fa-var-stream, + "dharmachakra": $fa-var-dharmachakra, + "hotdog": $fa-var-hotdog, + "person-walking-with-cane": $fa-var-person-walking-with-cane, + "blind": $fa-var-blind, + "drum": $fa-var-drum, + "ice-cream": $fa-var-ice-cream, + "heart-circle-bolt": $fa-var-heart-circle-bolt, + "fax": $fa-var-fax, + "paragraph": $fa-var-paragraph, + "check-to-slot": $fa-var-check-to-slot, + "vote-yea": $fa-var-vote-yea, + "star-half": $fa-var-star-half, + "boxes-stacked": $fa-var-boxes-stacked, + "boxes": $fa-var-boxes, + "boxes-alt": $fa-var-boxes-alt, + "link": $fa-var-link, + "chain": $fa-var-chain, + "ear-listen": $fa-var-ear-listen, + "assistive-listening-systems": $fa-var-assistive-listening-systems, + "tree-city": $fa-var-tree-city, + "play": $fa-var-play, + "font": $fa-var-font, + "table-cells-row-lock": $fa-var-table-cells-row-lock, + "rupiah-sign": $fa-var-rupiah-sign, + "magnifying-glass": $fa-var-magnifying-glass, + "search": $fa-var-search, + "table-tennis-paddle-ball": $fa-var-table-tennis-paddle-ball, + "ping-pong-paddle-ball": $fa-var-ping-pong-paddle-ball, + "table-tennis": $fa-var-table-tennis, + "person-dots-from-line": $fa-var-person-dots-from-line, + "diagnoses": $fa-var-diagnoses, + "trash-can-arrow-up": $fa-var-trash-can-arrow-up, + "trash-restore-alt": $fa-var-trash-restore-alt, + "naira-sign": $fa-var-naira-sign, + "cart-arrow-down": $fa-var-cart-arrow-down, + "walkie-talkie": $fa-var-walkie-talkie, + "file-pen": $fa-var-file-pen, + "file-edit": $fa-var-file-edit, + "receipt": $fa-var-receipt, + "square-pen": $fa-var-square-pen, + "pen-square": $fa-var-pen-square, + "pencil-square": $fa-var-pencil-square, + "suitcase-rolling": $fa-var-suitcase-rolling, + "person-circle-exclamation": $fa-var-person-circle-exclamation, + "chevron-down": $fa-var-chevron-down, + "battery-full": $fa-var-battery-full, + "battery": $fa-var-battery, + "battery-5": $fa-var-battery-5, + "skull-crossbones": $fa-var-skull-crossbones, + "code-compare": $fa-var-code-compare, + "list-ul": $fa-var-list-ul, + "list-dots": $fa-var-list-dots, + "school-lock": $fa-var-school-lock, + "tower-cell": $fa-var-tower-cell, + "down-long": $fa-var-down-long, + "long-arrow-alt-down": $fa-var-long-arrow-alt-down, + "ranking-star": $fa-var-ranking-star, + "chess-king": $fa-var-chess-king, + "person-harassing": $fa-var-person-harassing, + "brazilian-real-sign": $fa-var-brazilian-real-sign, + "landmark-dome": $fa-var-landmark-dome, + "landmark-alt": $fa-var-landmark-alt, + "arrow-up": $fa-var-arrow-up, + "tv": $fa-var-tv, + "television": $fa-var-television, + "tv-alt": $fa-var-tv-alt, + "shrimp": $fa-var-shrimp, + "list-check": $fa-var-list-check, + "tasks": $fa-var-tasks, + "jug-detergent": $fa-var-jug-detergent, + "circle-user": $fa-var-circle-user, + "user-circle": $fa-var-user-circle, + "user-shield": $fa-var-user-shield, + "wind": $fa-var-wind, + "car-burst": $fa-var-car-burst, + "car-crash": $fa-var-car-crash, + "y": $fa-var-y, + "person-snowboarding": $fa-var-person-snowboarding, + "snowboarding": $fa-var-snowboarding, + "truck-fast": $fa-var-truck-fast, + "shipping-fast": $fa-var-shipping-fast, + "fish": $fa-var-fish, + "user-graduate": $fa-var-user-graduate, + "circle-half-stroke": $fa-var-circle-half-stroke, + "adjust": $fa-var-adjust, + "clapperboard": $fa-var-clapperboard, + "circle-radiation": $fa-var-circle-radiation, + "radiation-alt": $fa-var-radiation-alt, + "baseball": $fa-var-baseball, + "baseball-ball": $fa-var-baseball-ball, + "jet-fighter-up": $fa-var-jet-fighter-up, + "diagram-project": $fa-var-diagram-project, + "project-diagram": $fa-var-project-diagram, + "copy": $fa-var-copy, + "volume-xmark": $fa-var-volume-xmark, + "volume-mute": $fa-var-volume-mute, + "volume-times": $fa-var-volume-times, + "hand-sparkles": $fa-var-hand-sparkles, + "grip": $fa-var-grip, + "grip-horizontal": $fa-var-grip-horizontal, + "share-from-square": $fa-var-share-from-square, + "share-square": $fa-var-share-square, + "child-combatant": $fa-var-child-combatant, + "child-rifle": $fa-var-child-rifle, + "gun": $fa-var-gun, + "square-phone": $fa-var-square-phone, + "phone-square": $fa-var-phone-square, + "plus": $fa-var-plus, + "add": $fa-var-add, + "expand": $fa-var-expand, + "computer": $fa-var-computer, + "xmark": $fa-var-xmark, + "close": $fa-var-close, + "multiply": $fa-var-multiply, + "remove": $fa-var-remove, + "times": $fa-var-times, + "arrows-up-down-left-right": $fa-var-arrows-up-down-left-right, + "arrows": $fa-var-arrows, + "chalkboard-user": $fa-var-chalkboard-user, + "chalkboard-teacher": $fa-var-chalkboard-teacher, + "peso-sign": $fa-var-peso-sign, + "building-shield": $fa-var-building-shield, + "baby": $fa-var-baby, + "users-line": $fa-var-users-line, + "quote-left": $fa-var-quote-left, + "quote-left-alt": $fa-var-quote-left-alt, + "tractor": $fa-var-tractor, + "trash-arrow-up": $fa-var-trash-arrow-up, + "trash-restore": $fa-var-trash-restore, + "arrow-down-up-lock": $fa-var-arrow-down-up-lock, + "lines-leaning": $fa-var-lines-leaning, + "ruler-combined": $fa-var-ruler-combined, + "copyright": $fa-var-copyright, + "equals": $fa-var-equals, + "blender": $fa-var-blender, + "teeth": $fa-var-teeth, + "shekel-sign": $fa-var-shekel-sign, + "ils": $fa-var-ils, + "shekel": $fa-var-shekel, + "sheqel": $fa-var-sheqel, + "sheqel-sign": $fa-var-sheqel-sign, + "map": $fa-var-map, + "rocket": $fa-var-rocket, + "photo-film": $fa-var-photo-film, + "photo-video": $fa-var-photo-video, + "folder-minus": $fa-var-folder-minus, + "hexagon-nodes-bolt": $fa-var-hexagon-nodes-bolt, + "store": $fa-var-store, + "arrow-trend-up": $fa-var-arrow-trend-up, + "plug-circle-minus": $fa-var-plug-circle-minus, + "sign-hanging": $fa-var-sign-hanging, + "sign": $fa-var-sign, + "bezier-curve": $fa-var-bezier-curve, + "bell-slash": $fa-var-bell-slash, + "tablet": $fa-var-tablet, + "tablet-android": $fa-var-tablet-android, + "school-flag": $fa-var-school-flag, + "fill": $fa-var-fill, + "angle-up": $fa-var-angle-up, + "drumstick-bite": $fa-var-drumstick-bite, + "holly-berry": $fa-var-holly-berry, + "chevron-left": $fa-var-chevron-left, + "bacteria": $fa-var-bacteria, + "hand-lizard": $fa-var-hand-lizard, + "notdef": $fa-var-notdef, + "disease": $fa-var-disease, + "briefcase-medical": $fa-var-briefcase-medical, + "genderless": $fa-var-genderless, + "chevron-right": $fa-var-chevron-right, + "retweet": $fa-var-retweet, + "car-rear": $fa-var-car-rear, + "car-alt": $fa-var-car-alt, + "pump-soap": $fa-var-pump-soap, + "video-slash": $fa-var-video-slash, + "battery-quarter": $fa-var-battery-quarter, + "battery-2": $fa-var-battery-2, + "radio": $fa-var-radio, + "baby-carriage": $fa-var-baby-carriage, + "carriage-baby": $fa-var-carriage-baby, + "traffic-light": $fa-var-traffic-light, + "thermometer": $fa-var-thermometer, + "vr-cardboard": $fa-var-vr-cardboard, + "hand-middle-finger": $fa-var-hand-middle-finger, + "percent": $fa-var-percent, + "percentage": $fa-var-percentage, + "truck-moving": $fa-var-truck-moving, + "glass-water-droplet": $fa-var-glass-water-droplet, + "display": $fa-var-display, + "face-smile": $fa-var-face-smile, + "smile": $fa-var-smile, + "thumbtack": $fa-var-thumbtack, + "thumb-tack": $fa-var-thumb-tack, + "trophy": $fa-var-trophy, + "person-praying": $fa-var-person-praying, + "pray": $fa-var-pray, + "hammer": $fa-var-hammer, + "hand-peace": $fa-var-hand-peace, + "rotate": $fa-var-rotate, + "sync-alt": $fa-var-sync-alt, + "spinner": $fa-var-spinner, + "robot": $fa-var-robot, + "peace": $fa-var-peace, + "gears": $fa-var-gears, + "cogs": $fa-var-cogs, + "warehouse": $fa-var-warehouse, + "arrow-up-right-dots": $fa-var-arrow-up-right-dots, + "splotch": $fa-var-splotch, + "face-grin-hearts": $fa-var-face-grin-hearts, + "grin-hearts": $fa-var-grin-hearts, + "dice-four": $fa-var-dice-four, + "sim-card": $fa-var-sim-card, + "transgender": $fa-var-transgender, + "transgender-alt": $fa-var-transgender-alt, + "mercury": $fa-var-mercury, + "arrow-turn-down": $fa-var-arrow-turn-down, + "level-down": $fa-var-level-down, + "person-falling-burst": $fa-var-person-falling-burst, + "award": $fa-var-award, + "ticket-simple": $fa-var-ticket-simple, + "ticket-alt": $fa-var-ticket-alt, + "building": $fa-var-building, + "angles-left": $fa-var-angles-left, + "angle-double-left": $fa-var-angle-double-left, + "qrcode": $fa-var-qrcode, + "clock-rotate-left": $fa-var-clock-rotate-left, + "history": $fa-var-history, + "face-grin-beam-sweat": $fa-var-face-grin-beam-sweat, + "grin-beam-sweat": $fa-var-grin-beam-sweat, + "file-export": $fa-var-file-export, + "arrow-right-from-file": $fa-var-arrow-right-from-file, + "shield": $fa-var-shield, + "shield-blank": $fa-var-shield-blank, + "arrow-up-short-wide": $fa-var-arrow-up-short-wide, + "sort-amount-up-alt": $fa-var-sort-amount-up-alt, + "comment-nodes": $fa-var-comment-nodes, + "house-medical": $fa-var-house-medical, + "golf-ball-tee": $fa-var-golf-ball-tee, + "golf-ball": $fa-var-golf-ball, + "circle-chevron-left": $fa-var-circle-chevron-left, + "chevron-circle-left": $fa-var-chevron-circle-left, + "house-chimney-window": $fa-var-house-chimney-window, + "pen-nib": $fa-var-pen-nib, + "tent-arrow-turn-left": $fa-var-tent-arrow-turn-left, + "tents": $fa-var-tents, + "wand-magic": $fa-var-wand-magic, + "magic": $fa-var-magic, + "dog": $fa-var-dog, + "carrot": $fa-var-carrot, + "moon": $fa-var-moon, + "wine-glass-empty": $fa-var-wine-glass-empty, + "wine-glass-alt": $fa-var-wine-glass-alt, + "cheese": $fa-var-cheese, + "yin-yang": $fa-var-yin-yang, + "music": $fa-var-music, + "code-commit": $fa-var-code-commit, + "temperature-low": $fa-var-temperature-low, + "person-biking": $fa-var-person-biking, + "biking": $fa-var-biking, + "broom": $fa-var-broom, + "shield-heart": $fa-var-shield-heart, + "gopuram": $fa-var-gopuram, + "earth-oceania": $fa-var-earth-oceania, + "globe-oceania": $fa-var-globe-oceania, + "square-xmark": $fa-var-square-xmark, + "times-square": $fa-var-times-square, + "xmark-square": $fa-var-xmark-square, + "hashtag": $fa-var-hashtag, + "up-right-and-down-left-from-center": $fa-var-up-right-and-down-left-from-center, + "expand-alt": $fa-var-expand-alt, + "oil-can": $fa-var-oil-can, + "t": $fa-var-t, + "hippo": $fa-var-hippo, + "chart-column": $fa-var-chart-column, + "infinity": $fa-var-infinity, + "vial-circle-check": $fa-var-vial-circle-check, + "person-arrow-down-to-line": $fa-var-person-arrow-down-to-line, + "voicemail": $fa-var-voicemail, + "fan": $fa-var-fan, + "person-walking-luggage": $fa-var-person-walking-luggage, + "up-down": $fa-var-up-down, + "arrows-alt-v": $fa-var-arrows-alt-v, + "cloud-moon-rain": $fa-var-cloud-moon-rain, + "calendar": $fa-var-calendar, + "trailer": $fa-var-trailer, + "bahai": $fa-var-bahai, + "haykal": $fa-var-haykal, + "sd-card": $fa-var-sd-card, + "dragon": $fa-var-dragon, + "shoe-prints": $fa-var-shoe-prints, + "circle-plus": $fa-var-circle-plus, + "plus-circle": $fa-var-plus-circle, + "face-grin-tongue-wink": $fa-var-face-grin-tongue-wink, + "grin-tongue-wink": $fa-var-grin-tongue-wink, + "hand-holding": $fa-var-hand-holding, + "plug-circle-exclamation": $fa-var-plug-circle-exclamation, + "link-slash": $fa-var-link-slash, + "chain-broken": $fa-var-chain-broken, + "chain-slash": $fa-var-chain-slash, + "unlink": $fa-var-unlink, + "clone": $fa-var-clone, + "person-walking-arrow-loop-left": $fa-var-person-walking-arrow-loop-left, + "arrow-up-z-a": $fa-var-arrow-up-z-a, + "sort-alpha-up-alt": $fa-var-sort-alpha-up-alt, + "fire-flame-curved": $fa-var-fire-flame-curved, + "fire-alt": $fa-var-fire-alt, + "tornado": $fa-var-tornado, + "file-circle-plus": $fa-var-file-circle-plus, + "book-quran": $fa-var-book-quran, + "quran": $fa-var-quran, + "anchor": $fa-var-anchor, + "border-all": $fa-var-border-all, + "face-angry": $fa-var-face-angry, + "angry": $fa-var-angry, + "cookie-bite": $fa-var-cookie-bite, + "arrow-trend-down": $fa-var-arrow-trend-down, + "rss": $fa-var-rss, + "feed": $fa-var-feed, + "draw-polygon": $fa-var-draw-polygon, + "scale-balanced": $fa-var-scale-balanced, + "balance-scale": $fa-var-balance-scale, + "gauge-simple-high": $fa-var-gauge-simple-high, + "tachometer": $fa-var-tachometer, + "tachometer-fast": $fa-var-tachometer-fast, + "shower": $fa-var-shower, + "desktop": $fa-var-desktop, + "desktop-alt": $fa-var-desktop-alt, + "m": $fa-var-m, + "table-list": $fa-var-table-list, + "th-list": $fa-var-th-list, + "comment-sms": $fa-var-comment-sms, + "sms": $fa-var-sms, + "book": $fa-var-book, + "user-plus": $fa-var-user-plus, + "check": $fa-var-check, + "battery-three-quarters": $fa-var-battery-three-quarters, + "battery-4": $fa-var-battery-4, + "house-circle-check": $fa-var-house-circle-check, + "angle-left": $fa-var-angle-left, + "diagram-successor": $fa-var-diagram-successor, + "truck-arrow-right": $fa-var-truck-arrow-right, + "arrows-split-up-and-left": $fa-var-arrows-split-up-and-left, + "hand-fist": $fa-var-hand-fist, + "fist-raised": $fa-var-fist-raised, + "cloud-moon": $fa-var-cloud-moon, + "briefcase": $fa-var-briefcase, + "person-falling": $fa-var-person-falling, + "image-portrait": $fa-var-image-portrait, + "portrait": $fa-var-portrait, + "user-tag": $fa-var-user-tag, + "rug": $fa-var-rug, + "earth-europe": $fa-var-earth-europe, + "globe-europe": $fa-var-globe-europe, + "cart-flatbed-suitcase": $fa-var-cart-flatbed-suitcase, + "luggage-cart": $fa-var-luggage-cart, + "rectangle-xmark": $fa-var-rectangle-xmark, + "rectangle-times": $fa-var-rectangle-times, + "times-rectangle": $fa-var-times-rectangle, + "window-close": $fa-var-window-close, + "baht-sign": $fa-var-baht-sign, + "book-open": $fa-var-book-open, + "book-journal-whills": $fa-var-book-journal-whills, + "journal-whills": $fa-var-journal-whills, + "handcuffs": $fa-var-handcuffs, + "triangle-exclamation": $fa-var-triangle-exclamation, + "exclamation-triangle": $fa-var-exclamation-triangle, + "warning": $fa-var-warning, + "database": $fa-var-database, + "share": $fa-var-share, + "mail-forward": $fa-var-mail-forward, + "bottle-droplet": $fa-var-bottle-droplet, + "mask-face": $fa-var-mask-face, + "hill-rockslide": $fa-var-hill-rockslide, + "right-left": $fa-var-right-left, + "exchange-alt": $fa-var-exchange-alt, + "paper-plane": $fa-var-paper-plane, + "road-circle-exclamation": $fa-var-road-circle-exclamation, + "dungeon": $fa-var-dungeon, + "align-right": $fa-var-align-right, + "money-bill-1-wave": $fa-var-money-bill-1-wave, + "money-bill-wave-alt": $fa-var-money-bill-wave-alt, + "life-ring": $fa-var-life-ring, + "hands": $fa-var-hands, + "sign-language": $fa-var-sign-language, + "signing": $fa-var-signing, + "calendar-day": $fa-var-calendar-day, + "water-ladder": $fa-var-water-ladder, + "ladder-water": $fa-var-ladder-water, + "swimming-pool": $fa-var-swimming-pool, + "arrows-up-down": $fa-var-arrows-up-down, + "arrows-v": $fa-var-arrows-v, + "face-grimace": $fa-var-face-grimace, + "grimace": $fa-var-grimace, + "wheelchair-move": $fa-var-wheelchair-move, + "wheelchair-alt": $fa-var-wheelchair-alt, + "turn-down": $fa-var-turn-down, + "level-down-alt": $fa-var-level-down-alt, + "person-walking-arrow-right": $fa-var-person-walking-arrow-right, + "square-envelope": $fa-var-square-envelope, + "envelope-square": $fa-var-envelope-square, + "dice": $fa-var-dice, + "bowling-ball": $fa-var-bowling-ball, + "brain": $fa-var-brain, + "bandage": $fa-var-bandage, + "band-aid": $fa-var-band-aid, + "calendar-minus": $fa-var-calendar-minus, + "circle-xmark": $fa-var-circle-xmark, + "times-circle": $fa-var-times-circle, + "xmark-circle": $fa-var-xmark-circle, + "gifts": $fa-var-gifts, + "hotel": $fa-var-hotel, + "earth-asia": $fa-var-earth-asia, + "globe-asia": $fa-var-globe-asia, + "id-card-clip": $fa-var-id-card-clip, + "id-card-alt": $fa-var-id-card-alt, + "magnifying-glass-plus": $fa-var-magnifying-glass-plus, + "search-plus": $fa-var-search-plus, + "thumbs-up": $fa-var-thumbs-up, + "user-clock": $fa-var-user-clock, + "hand-dots": $fa-var-hand-dots, + "allergies": $fa-var-allergies, + "file-invoice": $fa-var-file-invoice, + "window-minimize": $fa-var-window-minimize, + "mug-saucer": $fa-var-mug-saucer, + "coffee": $fa-var-coffee, + "brush": $fa-var-brush, + "file-half-dashed": $fa-var-file-half-dashed, + "mask": $fa-var-mask, + "magnifying-glass-minus": $fa-var-magnifying-glass-minus, + "search-minus": $fa-var-search-minus, + "ruler-vertical": $fa-var-ruler-vertical, + "user-large": $fa-var-user-large, + "user-alt": $fa-var-user-alt, + "train-tram": $fa-var-train-tram, + "user-nurse": $fa-var-user-nurse, + "syringe": $fa-var-syringe, + "cloud-sun": $fa-var-cloud-sun, + "stopwatch-20": $fa-var-stopwatch-20, + "square-full": $fa-var-square-full, + "magnet": $fa-var-magnet, + "jar": $fa-var-jar, + "note-sticky": $fa-var-note-sticky, + "sticky-note": $fa-var-sticky-note, + "bug-slash": $fa-var-bug-slash, + "arrow-up-from-water-pump": $fa-var-arrow-up-from-water-pump, + "bone": $fa-var-bone, + "table-cells-row-unlock": $fa-var-table-cells-row-unlock, + "user-injured": $fa-var-user-injured, + "face-sad-tear": $fa-var-face-sad-tear, + "sad-tear": $fa-var-sad-tear, + "plane": $fa-var-plane, + "tent-arrows-down": $fa-var-tent-arrows-down, + "exclamation": $fa-var-exclamation, + "arrows-spin": $fa-var-arrows-spin, + "print": $fa-var-print, + "turkish-lira-sign": $fa-var-turkish-lira-sign, + "try": $fa-var-try, + "turkish-lira": $fa-var-turkish-lira, + "dollar-sign": $fa-var-dollar-sign, + "dollar": $fa-var-dollar, + "usd": $fa-var-usd, + "x": $fa-var-x, + "magnifying-glass-dollar": $fa-var-magnifying-glass-dollar, + "search-dollar": $fa-var-search-dollar, + "users-gear": $fa-var-users-gear, + "users-cog": $fa-var-users-cog, + "person-military-pointing": $fa-var-person-military-pointing, + "building-columns": $fa-var-building-columns, + "bank": $fa-var-bank, + "institution": $fa-var-institution, + "museum": $fa-var-museum, + "university": $fa-var-university, + "umbrella": $fa-var-umbrella, + "trowel": $fa-var-trowel, + "d": $fa-var-d, + "stapler": $fa-var-stapler, + "masks-theater": $fa-var-masks-theater, + "theater-masks": $fa-var-theater-masks, + "kip-sign": $fa-var-kip-sign, + "hand-point-left": $fa-var-hand-point-left, + "handshake-simple": $fa-var-handshake-simple, + "handshake-alt": $fa-var-handshake-alt, + "jet-fighter": $fa-var-jet-fighter, + "fighter-jet": $fa-var-fighter-jet, + "square-share-nodes": $fa-var-square-share-nodes, + "share-alt-square": $fa-var-share-alt-square, + "barcode": $fa-var-barcode, + "plus-minus": $fa-var-plus-minus, + "video": $fa-var-video, + "video-camera": $fa-var-video-camera, + "graduation-cap": $fa-var-graduation-cap, + "mortar-board": $fa-var-mortar-board, + "hand-holding-medical": $fa-var-hand-holding-medical, + "person-circle-check": $fa-var-person-circle-check, + "turn-up": $fa-var-turn-up, + "level-up-alt": $fa-var-level-up-alt, +); + +$fa-brand-icons: ( + "monero": $fa-var-monero, + "hooli": $fa-var-hooli, + "yelp": $fa-var-yelp, + "cc-visa": $fa-var-cc-visa, + "lastfm": $fa-var-lastfm, + "shopware": $fa-var-shopware, + "creative-commons-nc": $fa-var-creative-commons-nc, + "aws": $fa-var-aws, + "redhat": $fa-var-redhat, + "yoast": $fa-var-yoast, + "cloudflare": $fa-var-cloudflare, + "ups": $fa-var-ups, + "pixiv": $fa-var-pixiv, + "wpexplorer": $fa-var-wpexplorer, + "dyalog": $fa-var-dyalog, + "bity": $fa-var-bity, + "stackpath": $fa-var-stackpath, + "buysellads": $fa-var-buysellads, + "first-order": $fa-var-first-order, + "modx": $fa-var-modx, + "guilded": $fa-var-guilded, + "vnv": $fa-var-vnv, + "square-js": $fa-var-square-js, + "js-square": $fa-var-js-square, + "microsoft": $fa-var-microsoft, + "qq": $fa-var-qq, + "orcid": $fa-var-orcid, + "java": $fa-var-java, + "invision": $fa-var-invision, + "creative-commons-pd-alt": $fa-var-creative-commons-pd-alt, + "centercode": $fa-var-centercode, + "glide-g": $fa-var-glide-g, + "drupal": $fa-var-drupal, + "jxl": $fa-var-jxl, + "dart-lang": $fa-var-dart-lang, + "hire-a-helper": $fa-var-hire-a-helper, + "creative-commons-by": $fa-var-creative-commons-by, + "unity": $fa-var-unity, + "whmcs": $fa-var-whmcs, + "rocketchat": $fa-var-rocketchat, + "vk": $fa-var-vk, + "untappd": $fa-var-untappd, + "mailchimp": $fa-var-mailchimp, + "css3-alt": $fa-var-css3-alt, + "square-reddit": $fa-var-square-reddit, + "reddit-square": $fa-var-reddit-square, + "vimeo-v": $fa-var-vimeo-v, + "contao": $fa-var-contao, + "square-font-awesome": $fa-var-square-font-awesome, + "deskpro": $fa-var-deskpro, + "brave": $fa-var-brave, + "sistrix": $fa-var-sistrix, + "square-instagram": $fa-var-square-instagram, + "instagram-square": $fa-var-instagram-square, + "battle-net": $fa-var-battle-net, + "the-red-yeti": $fa-var-the-red-yeti, + "square-hacker-news": $fa-var-square-hacker-news, + "hacker-news-square": $fa-var-hacker-news-square, + "edge": $fa-var-edge, + "threads": $fa-var-threads, + "napster": $fa-var-napster, + "square-snapchat": $fa-var-square-snapchat, + "snapchat-square": $fa-var-snapchat-square, + "google-plus-g": $fa-var-google-plus-g, + "artstation": $fa-var-artstation, + "markdown": $fa-var-markdown, + "sourcetree": $fa-var-sourcetree, + "google-plus": $fa-var-google-plus, + "diaspora": $fa-var-diaspora, + "foursquare": $fa-var-foursquare, + "stack-overflow": $fa-var-stack-overflow, + "github-alt": $fa-var-github-alt, + "phoenix-squadron": $fa-var-phoenix-squadron, + "pagelines": $fa-var-pagelines, + "algolia": $fa-var-algolia, + "red-river": $fa-var-red-river, + "creative-commons-sa": $fa-var-creative-commons-sa, + "safari": $fa-var-safari, + "google": $fa-var-google, + "square-font-awesome-stroke": $fa-var-square-font-awesome-stroke, + "font-awesome-alt": $fa-var-font-awesome-alt, + "atlassian": $fa-var-atlassian, + "linkedin-in": $fa-var-linkedin-in, + "digital-ocean": $fa-var-digital-ocean, + "nimblr": $fa-var-nimblr, + "chromecast": $fa-var-chromecast, + "evernote": $fa-var-evernote, + "hacker-news": $fa-var-hacker-news, + "creative-commons-sampling": $fa-var-creative-commons-sampling, + "adversal": $fa-var-adversal, + "creative-commons": $fa-var-creative-commons, + "watchman-monitoring": $fa-var-watchman-monitoring, + "fonticons": $fa-var-fonticons, + "weixin": $fa-var-weixin, + "shirtsinbulk": $fa-var-shirtsinbulk, + "codepen": $fa-var-codepen, + "git-alt": $fa-var-git-alt, + "lyft": $fa-var-lyft, + "rev": $fa-var-rev, + "windows": $fa-var-windows, + "wizards-of-the-coast": $fa-var-wizards-of-the-coast, + "square-viadeo": $fa-var-square-viadeo, + "viadeo-square": $fa-var-viadeo-square, + "meetup": $fa-var-meetup, + "centos": $fa-var-centos, + "adn": $fa-var-adn, + "cloudsmith": $fa-var-cloudsmith, + "opensuse": $fa-var-opensuse, + "pied-piper-alt": $fa-var-pied-piper-alt, + "square-dribbble": $fa-var-square-dribbble, + "dribbble-square": $fa-var-dribbble-square, + "codiepie": $fa-var-codiepie, + "node": $fa-var-node, + "mix": $fa-var-mix, + "steam": $fa-var-steam, + "cc-apple-pay": $fa-var-cc-apple-pay, + "scribd": $fa-var-scribd, + "debian": $fa-var-debian, + "openid": $fa-var-openid, + "instalod": $fa-var-instalod, + "files-pinwheel": $fa-var-files-pinwheel, + "expeditedssl": $fa-var-expeditedssl, + "sellcast": $fa-var-sellcast, + "square-twitter": $fa-var-square-twitter, + "twitter-square": $fa-var-twitter-square, + "r-project": $fa-var-r-project, + "delicious": $fa-var-delicious, + "freebsd": $fa-var-freebsd, + "vuejs": $fa-var-vuejs, + "accusoft": $fa-var-accusoft, + "ioxhost": $fa-var-ioxhost, + "fonticons-fi": $fa-var-fonticons-fi, + "app-store": $fa-var-app-store, + "cc-mastercard": $fa-var-cc-mastercard, + "itunes-note": $fa-var-itunes-note, + "golang": $fa-var-golang, + "kickstarter": $fa-var-kickstarter, + "square-kickstarter": $fa-var-square-kickstarter, + "grav": $fa-var-grav, + "weibo": $fa-var-weibo, + "uncharted": $fa-var-uncharted, + "firstdraft": $fa-var-firstdraft, + "square-youtube": $fa-var-square-youtube, + "youtube-square": $fa-var-youtube-square, + "wikipedia-w": $fa-var-wikipedia-w, + "wpressr": $fa-var-wpressr, + "rendact": $fa-var-rendact, + "angellist": $fa-var-angellist, + "galactic-republic": $fa-var-galactic-republic, + "nfc-directional": $fa-var-nfc-directional, + "skype": $fa-var-skype, + "joget": $fa-var-joget, + "fedora": $fa-var-fedora, + "stripe-s": $fa-var-stripe-s, + "meta": $fa-var-meta, + "laravel": $fa-var-laravel, + "hotjar": $fa-var-hotjar, + "bluetooth-b": $fa-var-bluetooth-b, + "square-letterboxd": $fa-var-square-letterboxd, + "sticker-mule": $fa-var-sticker-mule, + "creative-commons-zero": $fa-var-creative-commons-zero, + "hips": $fa-var-hips, + "css": $fa-var-css, + "behance": $fa-var-behance, + "reddit": $fa-var-reddit, + "discord": $fa-var-discord, + "chrome": $fa-var-chrome, + "app-store-ios": $fa-var-app-store-ios, + "cc-discover": $fa-var-cc-discover, + "wpbeginner": $fa-var-wpbeginner, + "confluence": $fa-var-confluence, + "shoelace": $fa-var-shoelace, + "mdb": $fa-var-mdb, + "dochub": $fa-var-dochub, + "accessible-icon": $fa-var-accessible-icon, + "ebay": $fa-var-ebay, + "amazon": $fa-var-amazon, + "unsplash": $fa-var-unsplash, + "yarn": $fa-var-yarn, + "square-steam": $fa-var-square-steam, + "steam-square": $fa-var-steam-square, + "500px": $fa-var-500px, + "square-vimeo": $fa-var-square-vimeo, + "vimeo-square": $fa-var-vimeo-square, + "asymmetrik": $fa-var-asymmetrik, + "font-awesome": $fa-var-font-awesome, + "font-awesome-flag": $fa-var-font-awesome-flag, + "font-awesome-logo-full": $fa-var-font-awesome-logo-full, + "gratipay": $fa-var-gratipay, + "apple": $fa-var-apple, + "hive": $fa-var-hive, + "gitkraken": $fa-var-gitkraken, + "keybase": $fa-var-keybase, + "apple-pay": $fa-var-apple-pay, + "padlet": $fa-var-padlet, + "amazon-pay": $fa-var-amazon-pay, + "square-github": $fa-var-square-github, + "github-square": $fa-var-github-square, + "stumbleupon": $fa-var-stumbleupon, + "fedex": $fa-var-fedex, + "phoenix-framework": $fa-var-phoenix-framework, + "shopify": $fa-var-shopify, + "neos": $fa-var-neos, + "square-threads": $fa-var-square-threads, + "hackerrank": $fa-var-hackerrank, + "researchgate": $fa-var-researchgate, + "swift": $fa-var-swift, + "angular": $fa-var-angular, + "speakap": $fa-var-speakap, + "angrycreative": $fa-var-angrycreative, + "y-combinator": $fa-var-y-combinator, + "empire": $fa-var-empire, + "envira": $fa-var-envira, + "google-scholar": $fa-var-google-scholar, + "square-gitlab": $fa-var-square-gitlab, + "gitlab-square": $fa-var-gitlab-square, + "studiovinari": $fa-var-studiovinari, + "pied-piper": $fa-var-pied-piper, + "wordpress": $fa-var-wordpress, + "product-hunt": $fa-var-product-hunt, + "firefox": $fa-var-firefox, + "linode": $fa-var-linode, + "goodreads": $fa-var-goodreads, + "square-odnoklassniki": $fa-var-square-odnoklassniki, + "odnoklassniki-square": $fa-var-odnoklassniki-square, + "jsfiddle": $fa-var-jsfiddle, + "sith": $fa-var-sith, + "themeisle": $fa-var-themeisle, + "page4": $fa-var-page4, + "hashnode": $fa-var-hashnode, + "react": $fa-var-react, + "cc-paypal": $fa-var-cc-paypal, + "squarespace": $fa-var-squarespace, + "cc-stripe": $fa-var-cc-stripe, + "creative-commons-share": $fa-var-creative-commons-share, + "bitcoin": $fa-var-bitcoin, + "keycdn": $fa-var-keycdn, + "opera": $fa-var-opera, + "itch-io": $fa-var-itch-io, + "umbraco": $fa-var-umbraco, + "galactic-senate": $fa-var-galactic-senate, + "ubuntu": $fa-var-ubuntu, + "draft2digital": $fa-var-draft2digital, + "stripe": $fa-var-stripe, + "houzz": $fa-var-houzz, + "gg": $fa-var-gg, + "dhl": $fa-var-dhl, + "square-pinterest": $fa-var-square-pinterest, + "pinterest-square": $fa-var-pinterest-square, + "xing": $fa-var-xing, + "blackberry": $fa-var-blackberry, + "creative-commons-pd": $fa-var-creative-commons-pd, + "playstation": $fa-var-playstation, + "quinscape": $fa-var-quinscape, + "less": $fa-var-less, + "blogger-b": $fa-var-blogger-b, + "opencart": $fa-var-opencart, + "vine": $fa-var-vine, + "signal-messenger": $fa-var-signal-messenger, + "paypal": $fa-var-paypal, + "gitlab": $fa-var-gitlab, + "typo3": $fa-var-typo3, + "reddit-alien": $fa-var-reddit-alien, + "yahoo": $fa-var-yahoo, + "dailymotion": $fa-var-dailymotion, + "affiliatetheme": $fa-var-affiliatetheme, + "pied-piper-pp": $fa-var-pied-piper-pp, + "bootstrap": $fa-var-bootstrap, + "odnoklassniki": $fa-var-odnoklassniki, + "nfc-symbol": $fa-var-nfc-symbol, + "mintbit": $fa-var-mintbit, + "ethereum": $fa-var-ethereum, + "speaker-deck": $fa-var-speaker-deck, + "creative-commons-nc-eu": $fa-var-creative-commons-nc-eu, + "patreon": $fa-var-patreon, + "avianex": $fa-var-avianex, + "ello": $fa-var-ello, + "gofore": $fa-var-gofore, + "bimobject": $fa-var-bimobject, + "brave-reverse": $fa-var-brave-reverse, + "facebook-f": $fa-var-facebook-f, + "square-google-plus": $fa-var-square-google-plus, + "google-plus-square": $fa-var-google-plus-square, + "web-awesome": $fa-var-web-awesome, + "mandalorian": $fa-var-mandalorian, + "first-order-alt": $fa-var-first-order-alt, + "osi": $fa-var-osi, + "google-wallet": $fa-var-google-wallet, + "d-and-d-beyond": $fa-var-d-and-d-beyond, + "periscope": $fa-var-periscope, + "fulcrum": $fa-var-fulcrum, + "cloudscale": $fa-var-cloudscale, + "forumbee": $fa-var-forumbee, + "mizuni": $fa-var-mizuni, + "schlix": $fa-var-schlix, + "square-xing": $fa-var-square-xing, + "xing-square": $fa-var-xing-square, + "bandcamp": $fa-var-bandcamp, + "wpforms": $fa-var-wpforms, + "cloudversify": $fa-var-cloudversify, + "usps": $fa-var-usps, + "megaport": $fa-var-megaport, + "magento": $fa-var-magento, + "spotify": $fa-var-spotify, + "optin-monster": $fa-var-optin-monster, + "fly": $fa-var-fly, + "square-bluesky": $fa-var-square-bluesky, + "aviato": $fa-var-aviato, + "itunes": $fa-var-itunes, + "cuttlefish": $fa-var-cuttlefish, + "blogger": $fa-var-blogger, + "flickr": $fa-var-flickr, + "viber": $fa-var-viber, + "soundcloud": $fa-var-soundcloud, + "digg": $fa-var-digg, + "tencent-weibo": $fa-var-tencent-weibo, + "letterboxd": $fa-var-letterboxd, + "symfony": $fa-var-symfony, + "maxcdn": $fa-var-maxcdn, + "etsy": $fa-var-etsy, + "facebook-messenger": $fa-var-facebook-messenger, + "audible": $fa-var-audible, + "think-peaks": $fa-var-think-peaks, + "bilibili": $fa-var-bilibili, + "erlang": $fa-var-erlang, + "x-twitter": $fa-var-x-twitter, + "cotton-bureau": $fa-var-cotton-bureau, + "dashcube": $fa-var-dashcube, + "42-group": $fa-var-42-group, + "innosoft": $fa-var-innosoft, + "stack-exchange": $fa-var-stack-exchange, + "elementor": $fa-var-elementor, + "square-pied-piper": $fa-var-square-pied-piper, + "pied-piper-square": $fa-var-pied-piper-square, + "creative-commons-nd": $fa-var-creative-commons-nd, + "palfed": $fa-var-palfed, + "superpowers": $fa-var-superpowers, + "resolving": $fa-var-resolving, + "xbox": $fa-var-xbox, + "square-web-awesome-stroke": $fa-var-square-web-awesome-stroke, + "searchengin": $fa-var-searchengin, + "tiktok": $fa-var-tiktok, + "square-facebook": $fa-var-square-facebook, + "facebook-square": $fa-var-facebook-square, + "renren": $fa-var-renren, + "linux": $fa-var-linux, + "glide": $fa-var-glide, + "linkedin": $fa-var-linkedin, + "hubspot": $fa-var-hubspot, + "deploydog": $fa-var-deploydog, + "twitch": $fa-var-twitch, + "flutter": $fa-var-flutter, + "ravelry": $fa-var-ravelry, + "mixer": $fa-var-mixer, + "square-lastfm": $fa-var-square-lastfm, + "lastfm-square": $fa-var-lastfm-square, + "vimeo": $fa-var-vimeo, + "mendeley": $fa-var-mendeley, + "uniregistry": $fa-var-uniregistry, + "figma": $fa-var-figma, + "creative-commons-remix": $fa-var-creative-commons-remix, + "cc-amazon-pay": $fa-var-cc-amazon-pay, + "dropbox": $fa-var-dropbox, + "instagram": $fa-var-instagram, + "cmplid": $fa-var-cmplid, + "upwork": $fa-var-upwork, + "facebook": $fa-var-facebook, + "gripfire": $fa-var-gripfire, + "jedi-order": $fa-var-jedi-order, + "uikit": $fa-var-uikit, + "fort-awesome-alt": $fa-var-fort-awesome-alt, + "phabricator": $fa-var-phabricator, + "ussunnah": $fa-var-ussunnah, + "earlybirds": $fa-var-earlybirds, + "trade-federation": $fa-var-trade-federation, + "autoprefixer": $fa-var-autoprefixer, + "whatsapp": $fa-var-whatsapp, + "square-upwork": $fa-var-square-upwork, + "slideshare": $fa-var-slideshare, + "google-play": $fa-var-google-play, + "viadeo": $fa-var-viadeo, + "line": $fa-var-line, + "google-drive": $fa-var-google-drive, + "servicestack": $fa-var-servicestack, + "simplybuilt": $fa-var-simplybuilt, + "bitbucket": $fa-var-bitbucket, + "imdb": $fa-var-imdb, + "deezer": $fa-var-deezer, + "raspberry-pi": $fa-var-raspberry-pi, + "jira": $fa-var-jira, + "docker": $fa-var-docker, + "screenpal": $fa-var-screenpal, + "bluetooth": $fa-var-bluetooth, + "gitter": $fa-var-gitter, + "d-and-d": $fa-var-d-and-d, + "microblog": $fa-var-microblog, + "cc-diners-club": $fa-var-cc-diners-club, + "gg-circle": $fa-var-gg-circle, + "pied-piper-hat": $fa-var-pied-piper-hat, + "kickstarter-k": $fa-var-kickstarter-k, + "yandex": $fa-var-yandex, + "readme": $fa-var-readme, + "html5": $fa-var-html5, + "sellsy": $fa-var-sellsy, + "square-web-awesome": $fa-var-square-web-awesome, + "sass": $fa-var-sass, + "wirsindhandwerk": $fa-var-wirsindhandwerk, + "wsh": $fa-var-wsh, + "buromobelexperte": $fa-var-buromobelexperte, + "salesforce": $fa-var-salesforce, + "octopus-deploy": $fa-var-octopus-deploy, + "medapps": $fa-var-medapps, + "ns8": $fa-var-ns8, + "pinterest-p": $fa-var-pinterest-p, + "apper": $fa-var-apper, + "fort-awesome": $fa-var-fort-awesome, + "waze": $fa-var-waze, + "bluesky": $fa-var-bluesky, + "cc-jcb": $fa-var-cc-jcb, + "snapchat": $fa-var-snapchat, + "snapchat-ghost": $fa-var-snapchat-ghost, + "fantasy-flight-games": $fa-var-fantasy-flight-games, + "rust": $fa-var-rust, + "wix": $fa-var-wix, + "square-behance": $fa-var-square-behance, + "behance-square": $fa-var-behance-square, + "supple": $fa-var-supple, + "webflow": $fa-var-webflow, + "rebel": $fa-var-rebel, + "css3": $fa-var-css3, + "staylinked": $fa-var-staylinked, + "kaggle": $fa-var-kaggle, + "space-awesome": $fa-var-space-awesome, + "deviantart": $fa-var-deviantart, + "cpanel": $fa-var-cpanel, + "goodreads-g": $fa-var-goodreads-g, + "square-git": $fa-var-square-git, + "git-square": $fa-var-git-square, + "square-tumblr": $fa-var-square-tumblr, + "tumblr-square": $fa-var-tumblr-square, + "trello": $fa-var-trello, + "creative-commons-nc-jp": $fa-var-creative-commons-nc-jp, + "get-pocket": $fa-var-get-pocket, + "perbyte": $fa-var-perbyte, + "grunt": $fa-var-grunt, + "weebly": $fa-var-weebly, + "connectdevelop": $fa-var-connectdevelop, + "leanpub": $fa-var-leanpub, + "black-tie": $fa-var-black-tie, + "themeco": $fa-var-themeco, + "python": $fa-var-python, + "android": $fa-var-android, + "bots": $fa-var-bots, + "free-code-camp": $fa-var-free-code-camp, + "hornbill": $fa-var-hornbill, + "js": $fa-var-js, + "ideal": $fa-var-ideal, + "git": $fa-var-git, + "dev": $fa-var-dev, + "sketch": $fa-var-sketch, + "yandex-international": $fa-var-yandex-international, + "cc-amex": $fa-var-cc-amex, + "uber": $fa-var-uber, + "github": $fa-var-github, + "php": $fa-var-php, + "alipay": $fa-var-alipay, + "youtube": $fa-var-youtube, + "skyatlas": $fa-var-skyatlas, + "firefox-browser": $fa-var-firefox-browser, + "replyd": $fa-var-replyd, + "suse": $fa-var-suse, + "jenkins": $fa-var-jenkins, + "twitter": $fa-var-twitter, + "rockrms": $fa-var-rockrms, + "pinterest": $fa-var-pinterest, + "buffer": $fa-var-buffer, + "npm": $fa-var-npm, + "yammer": $fa-var-yammer, + "btc": $fa-var-btc, + "dribbble": $fa-var-dribbble, + "stumbleupon-circle": $fa-var-stumbleupon-circle, + "internet-explorer": $fa-var-internet-explorer, + "stubber": $fa-var-stubber, + "telegram": $fa-var-telegram, + "telegram-plane": $fa-var-telegram-plane, + "old-republic": $fa-var-old-republic, + "odysee": $fa-var-odysee, + "square-whatsapp": $fa-var-square-whatsapp, + "whatsapp-square": $fa-var-whatsapp-square, + "node-js": $fa-var-node-js, + "edge-legacy": $fa-var-edge-legacy, + "slack": $fa-var-slack, + "slack-hash": $fa-var-slack-hash, + "medrt": $fa-var-medrt, + "usb": $fa-var-usb, + "tumblr": $fa-var-tumblr, + "vaadin": $fa-var-vaadin, + "quora": $fa-var-quora, + "square-x-twitter": $fa-var-square-x-twitter, + "reacteurope": $fa-var-reacteurope, + "medium": $fa-var-medium, + "medium-m": $fa-var-medium-m, + "amilia": $fa-var-amilia, + "mixcloud": $fa-var-mixcloud, + "flipboard": $fa-var-flipboard, + "viacoin": $fa-var-viacoin, + "critical-role": $fa-var-critical-role, + "sitrox": $fa-var-sitrox, + "discourse": $fa-var-discourse, + "joomla": $fa-var-joomla, + "mastodon": $fa-var-mastodon, + "airbnb": $fa-var-airbnb, + "wolf-pack-battalion": $fa-var-wolf-pack-battalion, + "buy-n-large": $fa-var-buy-n-large, + "gulp": $fa-var-gulp, + "creative-commons-sampling-plus": $fa-var-creative-commons-sampling-plus, + "strava": $fa-var-strava, + "ember": $fa-var-ember, + "canadian-maple-leaf": $fa-var-canadian-maple-leaf, + "teamspeak": $fa-var-teamspeak, + "pushed": $fa-var-pushed, + "wordpress-simple": $fa-var-wordpress-simple, + "nutritionix": $fa-var-nutritionix, + "wodu": $fa-var-wodu, + "google-pay": $fa-var-google-pay, + "intercom": $fa-var-intercom, + "zhihu": $fa-var-zhihu, + "korvue": $fa-var-korvue, + "pix": $fa-var-pix, + "steam-symbol": $fa-var-steam-symbol, +); diff --git a/src/sass/fontawesome/brands.scss b/src/sass/fontawesome/brands.scss new file mode 100644 index 0000000..f05b3fc --- /dev/null +++ b/src/sass/fontawesome/brands.scss @@ -0,0 +1,30 @@ +/*! + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +@import 'functions'; +@import 'variables'; + +:root, :host { + --#{$fa-css-prefix}-style-family-brands: 'Font Awesome 6 Brands'; + --#{$fa-css-prefix}-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; +} + +@font-face { + font-family: 'Font Awesome 6 Brands'; + font-style: normal; + font-weight: 400; + font-display: $fa-font-display; + src: url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'), + url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype'); +} + +.fab, +.#{$fa-css-prefix}-brands { + font-weight: 400; +} + +@each $name, $icon in $fa-brand-icons { + .#{$fa-css-prefix}-#{$name} { #{$fa-icon-property}: unquote("\"#{ $icon }\""); } +} diff --git a/src/sass/fontawesome/fontawesome.scss b/src/sass/fontawesome/fontawesome.scss new file mode 100644 index 0000000..2a5b40a --- /dev/null +++ b/src/sass/fontawesome/fontawesome.scss @@ -0,0 +1,21 @@ +/*! + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +// Font Awesome core compile (Web Fonts-based) +// ------------------------- + +@import 'functions'; +@import 'variables'; +@import 'mixins'; +@import 'core'; +@import 'sizing'; +@import 'fixed-width'; +@import 'list'; +@import 'bordered-pulled'; +@import 'animated'; +@import 'rotated-flipped'; +@import 'stacked'; +@import 'icons'; +@import 'screen-reader'; diff --git a/src/sass/fontawesome/regular.scss b/src/sass/fontawesome/regular.scss new file mode 100644 index 0000000..4a15596 --- /dev/null +++ b/src/sass/fontawesome/regular.scss @@ -0,0 +1,27 @@ +/*! + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +@import 'functions'; +@import 'variables'; + +:root, :host { + --#{$fa-css-prefix}-style-family-classic: '#{ $fa-style-family }'; + --#{$fa-css-prefix}-font-regular: normal 400 1em/1 '#{ $fa-style-family }'; +} + + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 400; + font-display: $fa-font-display; + src: url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'), + url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'); +} + +.far, +.#{$fa-css-prefix}-regular { + font-weight: 400; +} diff --git a/src/sass/fontawesome/solid.scss b/src/sass/fontawesome/solid.scss new file mode 100644 index 0000000..f673892 --- /dev/null +++ b/src/sass/fontawesome/solid.scss @@ -0,0 +1,27 @@ +/*! + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +@import 'functions'; +@import 'variables'; + +:root, :host { + --#{$fa-css-prefix}-style-family-classic: '#{ $fa-style-family }'; + --#{$fa-css-prefix}-font-solid: normal 900 1em/1 '#{ $fa-style-family }'; +} + + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 900; + font-display: $fa-font-display; + src: url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'), + url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'); +} + +.fas, +.#{$fa-css-prefix}-solid { + font-weight: 900; +} diff --git a/src/sass/fontawesome/v4-shims.scss b/src/sass/fontawesome/v4-shims.scss new file mode 100644 index 0000000..448e25a --- /dev/null +++ b/src/sass/fontawesome/v4-shims.scss @@ -0,0 +1,11 @@ +/*! + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. + */ +// V4 shims compile (Web Fonts-based) +// ------------------------- + +@import 'functions'; +@import 'variables'; +@import 'shims'; diff --git a/src/sass/fonts/Inter-Regular.woff2 b/src/sass/fonts/Inter-Regular.woff2 deleted file mode 100644 index 6c2b6893d593201d7c94e52687f78b2ef28b357e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98868 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%0D(-D;tD2U3Vy$! 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 diff --git a/src/sass/fonts/Inter-SemiBold.woff2 b/src/sass/fonts/Inter-SemiBold.woff2 deleted file mode 100644 index 611e90c958f1b784ada6be1c603b923d57ca88b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105804 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 `>0IwGJyHK~ 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 z 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ⅇ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 diff --git a/src/svg/checkmark-seal-svgrepo-com.svg b/src/svg/checkmark-seal-svgrepo-com.svg deleted file mode 100644 index 8a5b4a3..0000000 --- a/src/svg/checkmark-seal-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/close-svgrepo-com.svg b/src/svg/close-svgrepo-com.svg deleted file mode 100644 index a4a1e54..0000000 --- a/src/svg/close-svgrepo-com.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/src/svg/download-svgrepo-com.svg b/src/svg/download-svgrepo-com.svg deleted file mode 100644 index 9b8cf09..0000000 --- a/src/svg/download-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/expand-full-fullscreen-svgrepo-com.svg b/src/svg/expand-full-fullscreen-svgrepo-com.svg deleted file mode 100644 index 53218ff..0000000 --- a/src/svg/expand-full-fullscreen-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/filter-svgrepo-com.svg b/src/svg/filter-svgrepo-com.svg deleted file mode 100644 index 6bedf72..0000000 --- a/src/svg/filter-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/fork-svgrepo-com.svg b/src/svg/fork-svgrepo-com.svg deleted file mode 100644 index 8087aa8..0000000 --- a/src/svg/fork-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/fullscreen-svgrepo-com.svg b/src/svg/fullscreen-svgrepo-com.svg deleted file mode 100644 index 15379af..0000000 --- a/src/svg/fullscreen-svgrepo-com.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/svg/github-svgrepo-com.svg b/src/svg/github-svgrepo-com.svg deleted file mode 100644 index eaac757..0000000 --- a/src/svg/github-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/minus-svgrepo-com.svg b/src/svg/minus-svgrepo-com.svg deleted file mode 100644 index 4f655c0..0000000 --- a/src/svg/minus-svgrepo-com.svg +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/src/svg/navigation-svgrepo-com.svg b/src/svg/navigation-svgrepo-com.svg deleted file mode 100644 index 92569ad..0000000 --- a/src/svg/navigation-svgrepo-com.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/svg/plus-svgrepo-com.svg b/src/svg/plus-svgrepo-com.svg deleted file mode 100644 index 8410ef7..0000000 --- a/src/svg/plus-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/search-svgrepo-com.svg b/src/svg/search-svgrepo-com.svg deleted file mode 100644 index 8369115..0000000 --- a/src/svg/search-svgrepo-com.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/svg/settings-svgrepo-com.svg b/src/svg/settings-svgrepo-com.svg deleted file mode 100644 index eaeef67..0000000 --- a/src/svg/settings-svgrepo-com.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/webfonts/fa-brands-400.ttf b/src/webfonts/fa-brands-400.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0f82a8360517d2c8b7d16e85434d40c6fb735954 GIT binary patch literal 210792 zcmd4437DKkwfJ52_P%#d?>$>j_ssN6W+s`Qt&@;t2#F*RAj-ZdK}3-?YLLhx!zSp} zOHdY3#Hh&iDk>r>D(YNCL`CI#@# z-rDQbsZ*y;oqD6RQYxq>luH$lJAT>FnLA!}sZzR!(5+`*c-FQrw;XjC3H(YW-~74@ z-tyYDH*9`hscyG&_NC4}=d9QCeY$WDY3~Kb&LzNog8NAP&j6k0UbuaS_XvN0@@`bh zKXJjuXP@PKwdFpgS|@nF?!vQnY;!ibUrs#btKvmxU3kuCKKJZZ%GI1x%H6u{;x}#o z$nVQrl&gKYQn{sywz_;C^@Gb!*>PrU)jkz+$fnevypyM;$D=0Toq0I5-#!Mi`;SQ zlyC#{bB=AtyeWTT{x8%Oc5Hsfzw!FJ)Z0wi zj;U+Xv_rzAY%k!Kbk5aEoB9bSZlSM@JSL6JBlr)>`%8h8Ys%h3yg)r2n3;AG=QioaP1ynBZ1}c%U8YW3hl!&e(l<5A zYoy1G>EG1bK)uxCC(N{W!5vpV^0h6h?_i @@Z|Lo2o%N8V+8O&i2d+$8BHR07ve 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 z

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