mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-04 23:08:39 +09:00
Backport Basilisk internal userscripts
This commit is contained in:
parent
15bec18421
commit
5c168f64fc
23 changed files with 2648 additions and 0 deletions
|
|
@ -0,0 +1,233 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
// ==UserScript==
|
||||
// @name Intl.ListFormat Polyfill (minimal)
|
||||
// @namespace internal-userscripts
|
||||
// @description Provides a minimal Intl.ListFormat implementation for environments without native support.
|
||||
// @match *://*/*
|
||||
// @grant none
|
||||
// @run-at document-start
|
||||
// ==/UserScript==
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
if (typeof Intl !== "object" || typeof Intl.ListFormat === "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
var TYPE_VALUES = { conjunction: true, disjunction: true, unit: true };
|
||||
var STYLE_VALUES = { long: true, short: true, narrow: true };
|
||||
var LOCALE_MATCHER_VALUES = { lookup: true, "best fit": true };
|
||||
var PATTERNS = {
|
||||
conjunction: {
|
||||
long: { pair: " and ", middle: ", ", end: ", and " },
|
||||
short: { pair: " & ", middle: ", ", end: ", & " },
|
||||
narrow: { pair: ", ", middle: ", ", end: ", " },
|
||||
},
|
||||
disjunction: {
|
||||
long: { pair: " or ", middle: ", ", end: ", or " },
|
||||
short: { pair: " or ", middle: ", ", end: ", or " },
|
||||
narrow: { pair: " or ", middle: ", ", end: ", or " },
|
||||
},
|
||||
unit: {
|
||||
long: { pair: ", ", middle: ", ", end: ", " },
|
||||
short: { pair: ", ", middle: ", ", end: ", " },
|
||||
narrow: { pair: " ", middle: " ", end: " " },
|
||||
},
|
||||
};
|
||||
|
||||
function canonicalizeLocales(locales) {
|
||||
if (typeof Intl.getCanonicalLocales === "function") {
|
||||
return Intl.getCanonicalLocales(locales);
|
||||
}
|
||||
if (locales == null) {
|
||||
return [];
|
||||
}
|
||||
if (Array.isArray(locales)) {
|
||||
return locales.map(function (locale) {
|
||||
return String(locale);
|
||||
});
|
||||
}
|
||||
return [String(locales)];
|
||||
}
|
||||
|
||||
function defaultLocale() {
|
||||
try {
|
||||
if (typeof Intl.DateTimeFormat === "function") {
|
||||
return Intl.DateTimeFormat().resolvedOptions().locale;
|
||||
}
|
||||
} catch (e) {}
|
||||
if (typeof navigator !== "undefined" && navigator.language) {
|
||||
return String(navigator.language);
|
||||
}
|
||||
return "en-US";
|
||||
}
|
||||
|
||||
function toStringValue(value) {
|
||||
if (typeof value === "symbol") {
|
||||
throw new TypeError("Cannot convert a Symbol value to a string");
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
|
||||
function toStringList(list) {
|
||||
if (list == null) {
|
||||
throw new TypeError("List argument is required");
|
||||
}
|
||||
|
||||
var result = [];
|
||||
if (typeof Symbol !== "undefined" && list[Symbol.iterator] != null) {
|
||||
var iterator = list[Symbol.iterator]();
|
||||
if (!iterator || typeof iterator.next !== "function") {
|
||||
throw new TypeError("List argument must be iterable");
|
||||
}
|
||||
while (true) {
|
||||
var step = iterator.next();
|
||||
if (step.done) {
|
||||
break;
|
||||
}
|
||||
result.push(toStringValue(step.value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Fallback for very old environments without Symbol.iterator.
|
||||
if (Array.isArray(list)) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
result.push(toStringValue(list[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new TypeError("List argument must be iterable");
|
||||
}
|
||||
|
||||
function requireListFormatInstance(value) {
|
||||
if (
|
||||
value == null ||
|
||||
(typeof value !== "object" && typeof value !== "function") ||
|
||||
!TYPE_VALUES[value._type] ||
|
||||
!STYLE_VALUES[value._style]
|
||||
) {
|
||||
throw new TypeError(
|
||||
"Method Intl.ListFormat.prototype called on incompatible receiver",
|
||||
);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function buildParts(items, pattern) {
|
||||
var parts = [];
|
||||
var i = 0;
|
||||
var lastIndex = items.length - 1;
|
||||
|
||||
if (items.length === 0) {
|
||||
return parts;
|
||||
}
|
||||
if (items.length === 1) {
|
||||
parts.push({ type: "element", value: items[0] });
|
||||
return parts;
|
||||
}
|
||||
if (items.length === 2) {
|
||||
parts.push({ type: "element", value: items[0] });
|
||||
parts.push({ type: "literal", value: pattern.pair });
|
||||
parts.push({ type: "element", value: items[1] });
|
||||
return parts;
|
||||
}
|
||||
|
||||
parts.push({ type: "element", value: items[0] });
|
||||
for (i = 1; i < lastIndex; i++) {
|
||||
parts.push({ type: "literal", value: pattern.middle });
|
||||
parts.push({ type: "element", value: items[i] });
|
||||
}
|
||||
parts.push({ type: "literal", value: pattern.end });
|
||||
parts.push({ type: "element", value: items[lastIndex] });
|
||||
return parts;
|
||||
}
|
||||
|
||||
function ListFormat(locales, options) {
|
||||
if (!(this instanceof ListFormat)) {
|
||||
throw new TypeError("Intl.ListFormat must be called with new");
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
var type = options.type == null ? "conjunction" : String(options.type);
|
||||
var style = options.style == null ? "long" : String(options.style);
|
||||
var localeMatcher =
|
||||
options.localeMatcher == null
|
||||
? "best fit"
|
||||
: String(options.localeMatcher);
|
||||
|
||||
if (!TYPE_VALUES[type]) {
|
||||
throw new RangeError("Invalid type");
|
||||
}
|
||||
if (!STYLE_VALUES[style]) {
|
||||
throw new RangeError("Invalid style");
|
||||
}
|
||||
if (!LOCALE_MATCHER_VALUES[localeMatcher]) {
|
||||
throw new RangeError("Invalid localeMatcher");
|
||||
}
|
||||
|
||||
var localeList = canonicalizeLocales(locales);
|
||||
this._locale = localeList.length ? localeList[0] : defaultLocale();
|
||||
this._type = type;
|
||||
this._style = style;
|
||||
}
|
||||
|
||||
ListFormat.supportedLocalesOf = function (locales, options) {
|
||||
if (options != null && typeof options === "object") {
|
||||
var localeMatcher = options.localeMatcher;
|
||||
if (
|
||||
localeMatcher != null &&
|
||||
!LOCALE_MATCHER_VALUES[String(localeMatcher)]
|
||||
) {
|
||||
throw new RangeError("Invalid localeMatcher");
|
||||
}
|
||||
}
|
||||
return canonicalizeLocales(locales);
|
||||
};
|
||||
|
||||
ListFormat.prototype.resolvedOptions = function () {
|
||||
var self = requireListFormatInstance(this);
|
||||
return {
|
||||
locale: self._locale,
|
||||
type: self._type,
|
||||
style: self._style,
|
||||
};
|
||||
};
|
||||
|
||||
ListFormat.prototype.formatToParts = function (list) {
|
||||
var self = requireListFormatInstance(this);
|
||||
var items = toStringList(list);
|
||||
var pattern = PATTERNS[self._type][self._style];
|
||||
return buildParts(items, pattern);
|
||||
};
|
||||
|
||||
ListFormat.prototype._format = function (list) {
|
||||
var parts = this.formatToParts(list);
|
||||
var result = "";
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
result += parts[i].value;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Object.defineProperty(ListFormat.prototype, "format", {
|
||||
configurable: true,
|
||||
get: function () {
|
||||
var self = requireListFormatInstance(this);
|
||||
if (!self._boundFormat) {
|
||||
self._boundFormat = function (list) {
|
||||
return self._format(list);
|
||||
};
|
||||
}
|
||||
return self._boundFormat;
|
||||
},
|
||||
});
|
||||
|
||||
Intl.ListFormat = ListFormat;
|
||||
try {
|
||||
window.__internalUserscriptsIntlListFormatPolyfill = true;
|
||||
} catch (e) {}
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue