starchild-widget
Version:
Starchild Widget
1,484 lines (1,483 loc) • 523 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import * as React from "react";
import React__default from "react";
import * as ReactDOM from "react-dom";
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
function getDefaultExportFromCjs(x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}
var parser = {};
var lexer = {};
var moo$1 = { exports: {} };
var moo = moo$1.exports;
var hasRequiredMoo;
function requireMoo() {
if (hasRequiredMoo) return moo$1.exports;
hasRequiredMoo = 1;
(function(module) {
(function(root2, factory) {
if (module.exports) {
module.exports = factory();
} else {
root2.moo = factory();
}
})(moo, function() {
var hasOwnProperty2 = Object.prototype.hasOwnProperty;
var toString2 = Object.prototype.toString;
var hasSticky = typeof new RegExp().sticky === "boolean";
function isRegExp(o) {
return o && toString2.call(o) === "[object RegExp]";
}
function isObject(o) {
return o && typeof o === "object" && !isRegExp(o) && !Array.isArray(o);
}
function reEscape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
}
function reGroups(s) {
var re2 = new RegExp("|" + s);
return re2.exec("").length - 1;
}
function reCapture(s) {
return "(" + s + ")";
}
function reUnion(regexps) {
if (!regexps.length) return "(?!)";
var source = regexps.map(function(s) {
return "(?:" + s + ")";
}).join("|");
return "(?:" + source + ")";
}
function regexpOrLiteral(obj) {
if (typeof obj === "string") {
return "(?:" + reEscape(obj) + ")";
} else if (isRegExp(obj)) {
if (obj.ignoreCase) throw new Error("RegExp /i flag not allowed");
if (obj.global) throw new Error("RegExp /g flag is implied");
if (obj.sticky) throw new Error("RegExp /y flag is implied");
if (obj.multiline) throw new Error("RegExp /m flag is implied");
return obj.source;
} else {
throw new Error("Not a pattern: " + obj);
}
}
function pad(s, length) {
if (s.length > length) {
return s;
}
return Array(length - s.length + 1).join(" ") + s;
}
function lastNLines(string2, numLines) {
var position2 = string2.length;
var lineBreaks = 0;
while (true) {
var idx = string2.lastIndexOf("\n", position2 - 1);
if (idx === -1) {
break;
} else {
lineBreaks++;
}
position2 = idx;
if (lineBreaks === numLines) {
break;
}
if (position2 === 0) {
break;
}
}
var startPosition = lineBreaks < numLines ? 0 : position2 + 1;
return string2.substring(startPosition).split("\n");
}
function objectToRules(object) {
var keys2 = Object.getOwnPropertyNames(object);
var result = [];
for (var i = 0; i < keys2.length; i++) {
var key = keys2[i];
var thing = object[key];
var rules = [].concat(thing);
if (key === "include") {
for (var j = 0; j < rules.length; j++) {
result.push({ include: rules[j] });
}
continue;
}
var match = [];
rules.forEach(function(rule) {
if (isObject(rule)) {
if (match.length) result.push(ruleOptions(key, match));
result.push(ruleOptions(key, rule));
match = [];
} else {
match.push(rule);
}
});
if (match.length) result.push(ruleOptions(key, match));
}
return result;
}
function arrayToRules(array) {
var result = [];
for (var i = 0; i < array.length; i++) {
var obj = array[i];
if (obj.include) {
var include = [].concat(obj.include);
for (var j = 0; j < include.length; j++) {
result.push({ include: include[j] });
}
continue;
}
if (!obj.type) {
throw new Error("Rule has no type: " + JSON.stringify(obj));
}
result.push(ruleOptions(obj.type, obj));
}
return result;
}
function ruleOptions(type, obj) {
if (!isObject(obj)) {
obj = { match: obj };
}
if (obj.include) {
throw new Error("Matching rules cannot also include states");
}
var options = {
defaultType: type,
lineBreaks: !!obj.error || !!obj.fallback,
pop: false,
next: null,
push: null,
error: false,
fallback: false,
value: null,
type: null,
shouldThrow: false
};
for (var key in obj) {
if (hasOwnProperty2.call(obj, key)) {
options[key] = obj[key];
}
}
if (typeof options.type === "string" && type !== options.type) {
throw new Error("Type transform cannot be a string (type '" + options.type + "' for token '" + type + "')");
}
var match = options.match;
options.match = Array.isArray(match) ? match : match ? [match] : [];
options.match.sort(function(a, b) {
return isRegExp(a) && isRegExp(b) ? 0 : isRegExp(b) ? -1 : isRegExp(a) ? 1 : b.length - a.length;
});
return options;
}
function toRules(spec) {
return Array.isArray(spec) ? arrayToRules(spec) : objectToRules(spec);
}
var defaultErrorRule = ruleOptions("error", { lineBreaks: true, shouldThrow: true });
function compileRules(rules, hasStates) {
var errorRule = null;
var fast = /* @__PURE__ */ Object.create(null);
var fastAllowed = true;
var unicodeFlag = null;
var groups = [];
var parts = [];
for (var i = 0; i < rules.length; i++) {
if (rules[i].fallback) {
fastAllowed = false;
}
}
for (var i = 0; i < rules.length; i++) {
var options = rules[i];
if (options.include) {
throw new Error("Inheritance is not allowed in stateless lexers");
}
if (options.error || options.fallback) {
if (errorRule) {
if (!options.fallback === !errorRule.fallback) {
throw new Error("Multiple " + (options.fallback ? "fallback" : "error") + " rules not allowed (for token '" + options.defaultType + "')");
} else {
throw new Error("fallback and error are mutually exclusive (for token '" + options.defaultType + "')");
}
}
errorRule = options;
}
var match = options.match.slice();
if (fastAllowed) {
while (match.length && typeof match[0] === "string" && match[0].length === 1) {
var word = match.shift();
fast[word.charCodeAt(0)] = options;
}
}
if (options.pop || options.push || options.next) {
if (!hasStates) {
throw new Error("State-switching options are not allowed in stateless lexers (for token '" + options.defaultType + "')");
}
if (options.fallback) {
throw new Error("State-switching options are not allowed on fallback tokens (for token '" + options.defaultType + "')");
}
}
if (match.length === 0) {
continue;
}
fastAllowed = false;
groups.push(options);
for (var j = 0; j < match.length; j++) {
var obj = match[j];
if (!isRegExp(obj)) {
continue;
}
if (unicodeFlag === null) {
unicodeFlag = obj.unicode;
} else if (unicodeFlag !== obj.unicode && options.fallback === false) {
throw new Error("If one rule is /u then all must be");
}
}
var pat = reUnion(match.map(regexpOrLiteral));
var regexp = new RegExp(pat);
if (regexp.test("")) {
throw new Error("RegExp matches empty string: " + regexp);
}
var groupCount = reGroups(pat);
if (groupCount > 0) {
throw new Error("RegExp has capture groups: " + regexp + "\nUse (?: … ) instead");
}
if (!options.lineBreaks && regexp.test("\n")) {
throw new Error("Rule should declare lineBreaks: " + regexp);
}
parts.push(reCapture(pat));
}
var fallbackRule = errorRule && errorRule.fallback;
var flags = hasSticky && !fallbackRule ? "ym" : "gm";
var suffix = hasSticky || fallbackRule ? "" : "|";
if (unicodeFlag === true) flags += "u";
var combined = new RegExp(reUnion(parts) + suffix, flags);
return { regexp: combined, groups, fast, error: errorRule || defaultErrorRule };
}
function compile(rules) {
var result = compileRules(toRules(rules));
return new Lexer({ start: result }, "start");
}
function checkStateGroup(g, name2, map2) {
var state = g && (g.push || g.next);
if (state && !map2[state]) {
throw new Error("Missing state '" + state + "' (in token '" + g.defaultType + "' of state '" + name2 + "')");
}
if (g && g.pop && +g.pop !== 1) {
throw new Error("pop must be 1 (in token '" + g.defaultType + "' of state '" + name2 + "')");
}
}
function compileStates(states, start2) {
var all2 = states.$all ? toRules(states.$all) : [];
delete states.$all;
var keys2 = Object.getOwnPropertyNames(states);
if (!start2) start2 = keys2[0];
var ruleMap = /* @__PURE__ */ Object.create(null);
for (var i = 0; i < keys2.length; i++) {
var key = keys2[i];
ruleMap[key] = toRules(states[key]).concat(all2);
}
for (var i = 0; i < keys2.length; i++) {
var key = keys2[i];
var rules = ruleMap[key];
var included = /* @__PURE__ */ Object.create(null);
for (var j = 0; j < rules.length; j++) {
var rule = rules[j];
if (!rule.include) continue;
var splice2 = [j, 1];
if (rule.include !== key && !included[rule.include]) {
included[rule.include] = true;
var newRules = ruleMap[rule.include];
if (!newRules) {
throw new Error("Cannot include nonexistent state '" + rule.include + "' (in state '" + key + "')");
}
for (var k = 0; k < newRules.length; k++) {
var newRule = newRules[k];
if (rules.indexOf(newRule) !== -1) continue;
splice2.push(newRule);
}
}
rules.splice.apply(rules, splice2);
j--;
}
}
var map2 = /* @__PURE__ */ Object.create(null);
for (var i = 0; i < keys2.length; i++) {
var key = keys2[i];
map2[key] = compileRules(ruleMap[key], true);
}
for (var i = 0; i < keys2.length; i++) {
var name2 = keys2[i];
var state = map2[name2];
var groups = state.groups;
for (var j = 0; j < groups.length; j++) {
checkStateGroup(groups[j], name2, map2);
}
var fastKeys = Object.getOwnPropertyNames(state.fast);
for (var j = 0; j < fastKeys.length; j++) {
checkStateGroup(state.fast[fastKeys[j]], name2, map2);
}
}
return new Lexer(map2, start2);
}
function keywordTransform(map2) {
var isMap = typeof Map !== "undefined";
var reverseMap = isMap ? /* @__PURE__ */ new Map() : /* @__PURE__ */ Object.create(null);
var types2 = Object.getOwnPropertyNames(map2);
for (var i = 0; i < types2.length; i++) {
var tokenType = types2[i];
var item = map2[tokenType];
var keywordList = Array.isArray(item) ? item : [item];
keywordList.forEach(function(keyword) {
if (typeof keyword !== "string") {
throw new Error("keyword must be string (in keyword '" + tokenType + "')");
}
if (isMap) {
reverseMap.set(keyword, tokenType);
} else {
reverseMap[keyword] = tokenType;
}
});
}
return function(k) {
return isMap ? reverseMap.get(k) : reverseMap[k];
};
}
var Lexer = function(states, state) {
this.startState = state;
this.states = states;
this.buffer = "";
this.stack = [];
this.reset();
};
Lexer.prototype.reset = function(data, info) {
this.buffer = data || "";
this.index = 0;
this.line = info ? info.line : 1;
this.col = info ? info.col : 1;
this.queuedToken = info ? info.queuedToken : null;
this.queuedText = info ? info.queuedText : "";
this.queuedThrow = info ? info.queuedThrow : null;
this.setState(info ? info.state : this.startState);
this.stack = info && info.stack ? info.stack.slice() : [];
return this;
};
Lexer.prototype.save = function() {
return {
line: this.line,
col: this.col,
state: this.state,
stack: this.stack.slice(),
queuedToken: this.queuedToken,
queuedText: this.queuedText,
queuedThrow: this.queuedThrow
};
};
Lexer.prototype.setState = function(state) {
if (!state || this.state === state) return;
this.state = state;
var info = this.states[state];
this.groups = info.groups;
this.error = info.error;
this.re = info.regexp;
this.fast = info.fast;
};
Lexer.prototype.popState = function() {
this.setState(this.stack.pop());
};
Lexer.prototype.pushState = function(state) {
this.stack.push(this.state);
this.setState(state);
};
var eat = hasSticky ? function(re2, buffer) {
return re2.exec(buffer);
} : function(re2, buffer) {
var match = re2.exec(buffer);
if (match[0].length === 0) {
return null;
}
return match;
};
Lexer.prototype._getGroup = function(match) {
var groupCount = this.groups.length;
for (var i = 0; i < groupCount; i++) {
if (match[i + 1] !== void 0) {
return this.groups[i];
}
}
throw new Error("Cannot find token type for matched text");
};
function tokenToString() {
return this.value;
}
Lexer.prototype.next = function() {
var index2 = this.index;
if (this.queuedGroup) {
var token = this._token(this.queuedGroup, this.queuedText, index2);
this.queuedGroup = null;
this.queuedText = "";
return token;
}
var buffer = this.buffer;
if (index2 === buffer.length) {
return;
}
var group = this.fast[buffer.charCodeAt(index2)];
if (group) {
return this._token(group, buffer.charAt(index2), index2);
}
var re2 = this.re;
re2.lastIndex = index2;
var match = eat(re2, buffer);
var error = this.error;
if (match == null) {
return this._token(error, buffer.slice(index2, buffer.length), index2);
}
var group = this._getGroup(match);
var text2 = match[0];
if (error.fallback && match.index !== index2) {
this.queuedGroup = group;
this.queuedText = text2;
return this._token(error, buffer.slice(index2, match.index), index2);
}
return this._token(group, text2, index2);
};
Lexer.prototype._token = function(group, text2, offset2) {
var lineBreaks = 0;
if (group.lineBreaks) {
var matchNL = /\n/g;
var nl = 1;
if (text2 === "\n") {
lineBreaks = 1;
} else {
while (matchNL.exec(text2)) {
lineBreaks++;
nl = matchNL.lastIndex;
}
}
}
var token = {
type: typeof group.type === "function" && group.type(text2) || group.defaultType,
value: typeof group.value === "function" ? group.value(text2) : text2,
text: text2,
toString: tokenToString,
offset: offset2,
lineBreaks,
line: this.line,
col: this.col
};
var size = text2.length;
this.index += size;
this.line += lineBreaks;
if (lineBreaks !== 0) {
this.col = size - nl + 1;
} else {
this.col += size;
}
if (group.shouldThrow) {
var err2 = new Error(this.formatError(token, "invalid syntax"));
throw err2;
}
if (group.pop) this.popState();
else if (group.push) this.pushState(group.push);
else if (group.next) this.setState(group.next);
return token;
};
if (typeof Symbol !== "undefined" && Symbol.iterator) {
var LexerIterator = function(lexer2) {
this.lexer = lexer2;
};
LexerIterator.prototype.next = function() {
var token = this.lexer.next();
return { value: token, done: !token };
};
LexerIterator.prototype[Symbol.iterator] = function() {
return this;
};
Lexer.prototype[Symbol.iterator] = function() {
return new LexerIterator(this);
};
}
Lexer.prototype.formatError = function(token, message) {
if (token == null) {
var text2 = this.buffer.slice(this.index);
var token = {
text: text2,
offset: this.index,
lineBreaks: text2.indexOf("\n") === -1 ? 0 : 1,
line: this.line,
col: this.col
};
}
var numLinesAround = 2;
var firstDisplayedLine = Math.max(token.line - numLinesAround, 1);
var lastDisplayedLine = token.line + numLinesAround;
var lastLineDigits = String(lastDisplayedLine).length;
var displayedLines = lastNLines(
this.buffer,
this.line - token.line + numLinesAround + 1
).slice(0, 5);
var errorLines = [];
errorLines.push(message + " at line " + token.line + " col " + token.col + ":");
errorLines.push("");
for (var i = 0; i < displayedLines.length; i++) {
var line = displayedLines[i];
var lineNo = firstDisplayedLine + i;
errorLines.push(pad(String(lineNo), lastLineDigits) + " " + line);
if (lineNo === token.line) {
errorLines.push(pad("", lastLineDigits + token.col + 1) + "^");
}
}
return errorLines.join("\n");
};
Lexer.prototype.clone = function() {
return new Lexer(this.states, this.state);
};
Lexer.prototype.has = function(tokenType) {
return true;
};
return {
compile,
states: compileStates,
error: Object.freeze({ error: true }),
fallback: Object.freeze({ fallback: true }),
keywords: keywordTransform
};
});
})(moo$1);
return moo$1.exports;
}
var hasRequiredLexer;
function requireLexer() {
if (hasRequiredLexer) return lexer;
hasRequiredLexer = 1;
(function(exports) {
var __importDefault = lexer && lexer.__importDefault || function(mod) {
return mod && mod.__esModule ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.lexer = exports.states = void 0;
const moo_1 = __importDefault(/* @__PURE__ */ requireMoo());
exports.states = {
body: {
doubleapos: { match: "''", value: () => "'" },
quoted: {
lineBreaks: true,
match: /'[{}#](?:[^']|'')*'(?!')/u,
value: (src) => src.slice(1, -1).replace(/''/g, "'")
},
argument: {
lineBreaks: true,
match: /\{\s*[^\p{Pat_Syn}\p{Pat_WS}]+\s*/u,
push: "arg",
value: (src) => src.substring(1).trim()
},
octothorpe: "#",
end: { match: "}", pop: 1 },
content: { lineBreaks: true, match: /[^][^{}#']*/u }
},
arg: {
select: {
lineBreaks: true,
match: /,\s*(?:plural|select|selectordinal)\s*,\s*/u,
next: "select",
value: (src) => src.split(",")[1].trim()
},
"func-args": {
lineBreaks: true,
match: /,\s*[^\p{Pat_Syn}\p{Pat_WS}]+\s*,/u,
next: "body",
value: (src) => src.split(",")[1].trim()
},
"func-simple": {
lineBreaks: true,
match: /,\s*[^\p{Pat_Syn}\p{Pat_WS}]+\s*/u,
value: (src) => src.substring(1).trim()
},
end: { match: "}", pop: 1 }
},
select: {
offset: {
lineBreaks: true,
match: /\s*offset\s*:\s*\d+\s*/u,
value: (src) => src.split(":")[1].trim()
},
case: {
lineBreaks: true,
match: /\s*(?:=\d+|[^\p{Pat_Syn}\p{Pat_WS}]+)\s*\{/u,
push: "body",
value: (src) => src.substring(0, src.indexOf("{")).trim()
},
end: { match: /\s*\}/u, pop: 1 }
}
};
exports.lexer = moo_1.default.states(exports.states);
})(lexer);
return lexer;
}
var hasRequiredParser;
function requireParser() {
if (hasRequiredParser) return parser;
hasRequiredParser = 1;
Object.defineProperty(parser, "__esModule", { value: true });
parser.ParseError = void 0;
parser.parse = parse2;
const lexer_js_1 = /* @__PURE__ */ requireLexer();
const getContext = (lt) => ({
offset: lt.offset,
line: lt.line,
col: lt.col,
text: lt.text,
lineBreaks: lt.lineBreaks
});
const isSelectType = (type) => type === "plural" || type === "select" || type === "selectordinal";
function strictArgStyleParam(lt, param) {
let value = "";
let text2 = "";
for (const p of param) {
const pText = p.ctx.text;
text2 += pText;
switch (p.type) {
case "content":
value += p.value;
break;
case "argument":
case "function":
case "octothorpe":
value += pText;
break;
default:
throw new ParseError(lt, `Unsupported part in strict mode function arg style: ${pText}`);
}
}
const c = {
type: "content",
value: value.trim(),
ctx: Object.assign({}, param[0].ctx, { text: text2 })
};
return [c];
}
const strictArgTypes = [
"number",
"date",
"time",
"spellout",
"ordinal",
"duration"
];
const defaultPluralKeys = ["zero", "one", "two", "few", "many", "other"];
class ParseError extends Error {
/** @internal */
constructor(lt, msg) {
super(lexer_js_1.lexer.formatError(lt, msg));
}
}
parser.ParseError = ParseError;
class Parser {
constructor(src, opt) {
var _a2, _b, _c, _d2;
this.lexer = lexer_js_1.lexer.reset(src);
this.cardinalKeys = (_a2 = opt === null || opt === void 0 ? void 0 : opt.cardinal) !== null && _a2 !== void 0 ? _a2 : defaultPluralKeys;
this.ordinalKeys = (_b = opt === null || opt === void 0 ? void 0 : opt.ordinal) !== null && _b !== void 0 ? _b : defaultPluralKeys;
this.strict = (_c = opt === null || opt === void 0 ? void 0 : opt.strict) !== null && _c !== void 0 ? _c : false;
this.strictPluralKeys = (_d2 = opt === null || opt === void 0 ? void 0 : opt.strictPluralKeys) !== null && _d2 !== void 0 ? _d2 : true;
}
parse() {
return this.parseBody(false, true);
}
checkSelectKey(lt, type, key) {
if (key[0] === "=") {
if (type === "select") {
throw new ParseError(lt, `The case ${key} is not valid with select`);
}
} else if (type !== "select") {
const keys2 = type === "plural" ? this.cardinalKeys : this.ordinalKeys;
if (this.strictPluralKeys && keys2.length > 0 && !keys2.includes(key)) {
const msg = `The ${type} case ${key} is not valid in this locale`;
throw new ParseError(lt, msg);
}
}
}
parseSelect({ value: arg }, inPlural, ctx, type) {
const sel = { type, arg, cases: [], ctx };
if (type === "plural" || type === "selectordinal")
inPlural = true;
else if (this.strict)
inPlural = false;
for (const lt of this.lexer) {
switch (lt.type) {
case "offset":
if (type === "select") {
throw new ParseError(lt, "Unexpected plural offset for select");
}
if (sel.cases.length > 0) {
throw new ParseError(lt, "Plural offset must be set before cases");
}
sel.pluralOffset = Number(lt.value);
ctx.text += lt.text;
ctx.lineBreaks += lt.lineBreaks;
break;
case "case": {
this.checkSelectKey(lt, type, lt.value);
sel.cases.push({
key: lt.value,
tokens: this.parseBody(inPlural),
ctx: getContext(lt)
});
break;
}
case "end":
return sel;
/* istanbul ignore next: never happens */
default:
throw new ParseError(lt, `Unexpected lexer token: ${lt.type}`);
}
}
throw new ParseError(null, "Unexpected message end");
}
parseArgToken(lt, inPlural) {
const ctx = getContext(lt);
const argType = this.lexer.next();
if (!argType)
throw new ParseError(null, "Unexpected message end");
ctx.text += argType.text;
ctx.lineBreaks += argType.lineBreaks;
if (this.strict && (argType.type === "func-simple" || argType.type === "func-args") && !strictArgTypes.includes(argType.value)) {
const msg = `Invalid strict mode function arg type: ${argType.value}`;
throw new ParseError(lt, msg);
}
switch (argType.type) {
case "end":
return { type: "argument", arg: lt.value, ctx };
case "func-simple": {
const end2 = this.lexer.next();
if (!end2)
throw new ParseError(null, "Unexpected message end");
if (end2.type !== "end") {
throw new ParseError(end2, `Unexpected lexer token: ${end2.type}`);
}
ctx.text += end2.text;
if (isSelectType(argType.value.toLowerCase())) {
throw new ParseError(argType, `Invalid type identifier: ${argType.value}`);
}
return {
type: "function",
arg: lt.value,
key: argType.value,
ctx
};
}
case "func-args": {
if (isSelectType(argType.value.toLowerCase())) {
const msg = `Invalid type identifier: ${argType.value}`;
throw new ParseError(argType, msg);
}
let param = this.parseBody(this.strict ? false : inPlural);
if (this.strict && param.length > 0) {
param = strictArgStyleParam(lt, param);
}
return {
type: "function",
arg: lt.value,
key: argType.value,
param,
ctx
};
}
case "select":
if (isSelectType(argType.value)) {
return this.parseSelect(lt, inPlural, ctx, argType.value);
} else {
throw new ParseError(argType, `Unexpected select type ${argType.value}`);
}
/* istanbul ignore next: never happens */
default:
throw new ParseError(argType, `Unexpected lexer token: ${argType.type}`);
}
}
parseBody(inPlural, atRoot) {
const tokens = [];
let content2 = null;
for (const lt of this.lexer) {
if (lt.type === "argument") {
if (content2)
content2 = null;
tokens.push(this.parseArgToken(lt, inPlural));
} else if (lt.type === "octothorpe" && inPlural) {
if (content2)
content2 = null;
tokens.push({ type: "octothorpe", ctx: getContext(lt) });
} else if (lt.type === "end" && !atRoot) {
return tokens;
} else {
let value = lt.value;
if (!inPlural && lt.type === "quoted" && value[0] === "#") {
if (value.includes("{")) {
const errMsg = `Unsupported escape pattern: ${value}`;
throw new ParseError(lt, errMsg);
}
value = lt.text;
}
if (content2) {
content2.value += value;
content2.ctx.text += lt.text;
content2.ctx.lineBreaks += lt.lineBreaks;
} else {
content2 = { type: "content", value, ctx: getContext(lt) };
tokens.push(content2);
}
}
}
if (atRoot)
return tokens;
throw new ParseError(null, "Unexpected message end");
}
}
function parse2(src, options = {}) {
const parser2 = new Parser(src, options);
return parser2.parse();
}
return parser;
}
var parserExports = /* @__PURE__ */ requireParser();
class DateFormatError extends Error {
/** @internal */
constructor(msg, token, type) {
super(msg);
this.token = token;
this.type = type || "error";
}
}
const alpha = (width) => width < 4 ? "short" : width === 4 ? "long" : "narrow";
const numeric = (width) => width % 2 === 0 ? "2-digit" : "numeric";
function yearOptions(token, onError) {
switch (token.char) {
case "y":
return { year: numeric(token.width) };
case "r":
return { calendar: "gregory", year: "numeric" };
case "u":
case "U":
case "Y":
default:
onError(`${token.desc} is not supported; falling back to year:numeric`, DateFormatError.WARNING);
return { year: "numeric" };
}
}
function monthStyle(token, onError) {
switch (token.width) {
case 1:
return "numeric";
case 2:
return "2-digit";
case 3:
return "short";
case 4:
return "long";
case 5:
return "narrow";
default:
onError(`${token.desc} is not supported with width ${token.width}`);
return void 0;
}
}
function dayStyle(token, onError) {
const { char, desc, width } = token;
if (char === "d") {
return numeric(width);
} else {
onError(`${desc} is not supported`);
return void 0;
}
}
function weekdayStyle(token, onError) {
const { char, desc, width } = token;
if ((char === "c" || char === "e") && width < 3) {
const msg = `Numeric value is not supported for ${desc}; falling back to weekday:short`;
onError(msg, DateFormatError.WARNING);
}
return alpha(width);
}
function hourOptions(token) {
const hour = numeric(token.width);
let hourCycle;
switch (token.char) {
case "h":
hourCycle = "h12";
break;
case "H":
hourCycle = "h23";
break;
case "k":
hourCycle = "h24";
break;
case "K":
hourCycle = "h11";
break;
}
return hourCycle ? { hour, hourCycle } : { hour };
}
function timeZoneNameStyle(token, onError) {
const { char, desc, width } = token;
switch (char) {
case "v":
case "z":
return width === 4 ? "long" : "short";
case "V":
if (width === 4)
return "long";
onError(`${desc} is not supported with width ${width}`);
return void 0;
case "X":
onError(`${desc} is not supported`);
return void 0;
}
return "short";
}
function compileOptions(token, onError) {
switch (token.field) {
case "era":
return { era: alpha(token.width) };
case "year":
return yearOptions(token, onError);
case "month":
return { month: monthStyle(token, onError) };
case "day":
return { day: dayStyle(token, onError) };
case "weekday":
return { weekday: weekdayStyle(token, onError) };
case "period":
return void 0;
case "hour":
return hourOptions(token);
case "min":
return { minute: numeric(token.width) };
case "sec":
return { second: numeric(token.width) };
case "tz":
return { timeZoneName: timeZoneNameStyle(token, onError) };
case "quarter":
case "week":
case "sec-frac":
case "ms":
onError(`${token.desc} is not supported`);
}
return void 0;
}
function getDateFormatOptions(tokens, timeZone, onError = (error) => {
throw error;
}) {
const options = {
timeZone
};
const fields2 = [];
for (const token of tokens) {
const { error, field, str } = token;
if (error) {
const dte = new DateFormatError(error.message, token);
dte.stack = error.stack;
onError(dte);
}
if (str) {
const msg = `Ignoring string part: ${str}`;
onError(new DateFormatError(msg, token, DateFormatError.WARNING));
}
if (field) {
if (fields2.indexOf(field) === -1)
fields2.push(field);
else
onError(new DateFormatError(`Duplicate ${field} token`, token));
}
const opt = compileOptions(token, (msg, isWarning) => onError(new DateFormatError(msg, token, isWarning)));
if (opt)
Object.assign(options, opt);
}
return options;
}
const fields = {
G: { field: "era", desc: "Era" },
y: { field: "year", desc: "Year" },
Y: { field: "year", desc: 'Year of "Week of Year"' },
u: { field: "year", desc: "Extended year" },
U: { field: "year", desc: "Cyclic year name" },
r: { field: "year", desc: "Related Gregorian year" },
Q: { field: "quarter", desc: "Quarter" },
q: { field: "quarter", desc: "Stand-alone quarter" },
M: { field: "month", desc: "Month in year" },
L: { field: "month", desc: "Stand-alone month in year" },
w: { field: "week", desc: "Week of year" },
W: { field: "week", desc: "Week of month" },
d: { field: "day", desc: "Day in month" },
D: { field: "day", desc: "Day of year" },
F: { field: "day", desc: "Day of week in month" },
g: { field: "day", desc: "Modified julian day" },
E: { field: "weekday", desc: "Day of week" },
e: { field: "weekday", desc: "Local day of week" },
c: { field: "weekday", desc: "Stand-alone local day of week" },
a: { field: "period", desc: "AM/PM marker" },
b: { field: "period", desc: "AM/PM/noon/midnight marker" },
B: { field: "period", desc: "Flexible day period" },
h: { field: "hour", desc: "Hour in AM/PM (1~12)" },
H: { field: "hour", desc: "Hour in day (0~23)" },
k: { field: "hour", desc: "Hour in day (1~24)" },
K: { field: "hour", desc: "Hour in AM/PM (0~11)" },
j: { field: "hour", desc: "Hour in preferred cycle" },
J: { field: "hour", desc: "Hour in preferred cycle without marker" },
C: { field: "hour", desc: "Hour in preferred cycle with flexible marker" },
m: { field: "min", desc: "Minute in hour" },
s: { field: "sec", desc: "Second in minute" },
S: { field: "sec-frac", desc: "Fractional second" },
A: { field: "ms", desc: "Milliseconds in day" },
z: { field: "tz", desc: "Time Zone: specific non-location" },
Z: { field: "tz", desc: "Time Zone" },
O: { field: "tz", desc: "Time Zone: localized" },
v: { field: "tz", desc: "Time Zone: generic non-location" },
V: { field: "tz", desc: "Time Zone: ID" },
X: { field: "tz", desc: "Time Zone: ISO8601 with Z" },
x: { field: "tz", desc: "Time Zone: ISO8601" }
};
const isLetter = (char) => char >= "A" && char <= "Z" || char >= "a" && char <= "z";
function readFieldToken(src, pos) {
const char = src[pos];
let width = 1;
while (src[++pos] === char)
++width;
const field = fields[char];
if (!field) {
const msg = `The letter ${char} is not a valid field identifier`;
return { char, error: new Error(msg), width };
}
return { char, field: field.field, desc: field.desc, width };
}
function readQuotedToken(src, pos) {
let str = src[++pos];
let width = 2;
if (str === "'")
return { char: "'", str, width };
while (true) {
const next = src[++pos];
++width;
if (next === void 0) {
const msg = `Unterminated quoted literal in pattern: ${str || src}`;
return { char: "'", error: new Error(msg), str, width };
} else if (next === "'") {
if (src[++pos] !== "'")
return { char: "'", str, width };
else
++width;
}
str += next;
}
}
function readToken(src, pos) {
const char = src[pos];
if (!char)
return null;
if (isLetter(char))
return readFieldToken(src, pos);
if (char === "'")
return readQuotedToken(src, pos);
let str = char;
let width = 1;
while (true) {
const next = src[++pos];
if (!next || isLetter(next) || next === "'")
return { char, str, width };
str += next;
width += 1;
}
}
function parseDateTokens(src) {
const tokens = [];
let pos = 0;
while (true) {
const token = readToken(src, pos);
if (!token)
return tokens;
tokens.push(token);
pos += token.width;
}
}
function processTokens(tokens, mapText) {
if (!tokens.filter((token) => token.type !== "content").length) {
return tokens.map((token) => mapText(token.value));
}
return tokens.map((token) => {
var _a2;
if (token.type === "content") {
return mapText(token.value);
} else if (token.type === "octothorpe") {
return "#";
} else if (token.type === "argument") {
return [token.arg];
} else if (token.type === "function") {
const _param = (_a2 = token == null ? void 0 : token.param) == null ? void 0 : _a2[0];
if (token.key === "date" && _param) {
const opts = compileDateExpression(_param.value.trim(), (e) => {
throw new Error(`Unable to compile date expression: ${e.message}`);
});
return [token.arg, token.key, opts];
}
if (_param) {
return [token.arg, token.key, _param.value.trim()];
} else {
return [token.arg, token.key];
}
}
const offset2 = token.pluralOffset;
const formatProps = {};
token.cases.forEach(({ key, tokens: tokens2 }) => {
const prop = key[0] === "=" ? key.slice(1) : key;
formatProps[prop] = processTokens(tokens2, mapText);
});
return [
token.arg,
token.type,
{
offset: offset2,
...formatProps
}
];
});
}
function compileDateExpression(format, onError) {
if (/^::/.test(format)) {
const tokens = parseDateTokens(format.substring(2));
return getDateFormatOptions(tokens, void 0, onError);
}
return format;
}
function compileMessageOrThrow(message, mapText = (v) => v) {
return processTokens(parserExports.parse(message), mapText);
}
function compileMessage(message, mapText = (v) => v) {
try {
return compileMessageOrThrow(message, mapText);
} catch (e) {
console.error(`${e.message}
Message: ${message}`);
return [message];
}
}
const isString = (s) => typeof s === "string";
const isFunction = (f) => typeof f === "function";
const cache = /* @__PURE__ */ new Map();
const defaultLocale = "en";
function normalizeLocales(locales) {
const out = Array.isArray(locales) ? locales : [locales];
return [...out, defaultLocale];
}
function date(locales, value, format) {
const _locales = normalizeLocales(locales);
if (!format) {
format = "default";
}
let o;
if (typeof format === "string") {
o = {
day: "numeric",
month: "short",
year: "numeric"
};
switch (format) {
case "full":
o.weekday = "long";
case "long":
o.month = "long";
break;
case "short":
o.month = "numeric";
break;
}
} else {
o = format;
}
const formatter = getMemoized(
() => cacheKey("date", _locales, format),
() => new Intl.DateTimeFormat(_locales, o)
);
return formatter.format(isString(value) ? new Date(value) : value);
}
function time(locales, value, format) {
let o;
if (!format) {
format = "default";
}
if (typeof format === "string") {
o = {
second: "numeric",
minute: "numeric",
hour: "numeric"
};
switch (format) {
case "full":
case "long":
o.timeZoneName = "short";
break;
case "short":
delete o.second;
}
} else {
o = format;
}
return date(locales, value, o);
}
function number$1(locales, value, format) {
const _locales = normalizeLocales(locales);
const formatter = getMemoized(
() => cacheKey("number", _locales, format),
() => new Intl.NumberFormat(_locales, format)
);
return formatter.format(value);
}
function plural(locales, ordinal, value, { offset: offset2 = 0, ...rules }) {
const _locales = normalizeLocales(locales);
const plurals = ordinal ? getMemoized(
() => cacheKey("plural-ordinal", _locales),
() => new Intl.PluralRules(_locales, { type: "ordinal" })
) : getMemoized(
() => cacheKey("plural-cardinal", _locales),
() => new Intl.PluralRules(_locales, { type: "cardinal" })
);
return rules[value] ?? rules[plurals.select(value - offset2)] ?? rules.other;
}
function getMemoized(getKey, construct) {
const key = getKey();
let formatter = cache.get(key);
if (!formatter) {
formatter = construct();
cache.set(key, formatter);
}
return formatter;
}
function cacheKey(type, locales, options) {
const localeKey = locales.join("-");
return `${type}-${localeKey}-${JSON.stringify(options)}`;
}
const ESCAPE_SEQUENCE_REGEX = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/;
const decodeEscapeSequences = (str) => {
return str.replace(
// Same pattern but with capturing groups for extracting values during replacement
/\\u([a-fA-F0-9]{4})|\\x([a-fA-F0-9]{2})/g,
(_, unicode, hex) => {
if (unicode) {
const codePoint = parseInt(unicode, 16);
return String.fromCharCode(codePoint);
} else {
const codePoint = parseInt(hex, 16);
return String.fromCharCode(codePoint);
}
}
);
};
const OCTOTHORPE_PH = "%__lingui_octothorpe__%";
const getDefaultFormats = (locale, passedLocales, formats = {}) => {
const locales = passedLocales || locale;
const style = (format) => {
if (typeof format === "object")
return format;
return formats[format];
};
const replaceOctothorpe = (value, message) => {
const numberFormat = Object.keys(formats).length ? style("number") : void 0;
const valueStr = number$1(locales, value, numberFormat);
return message.replace(new RegExp(OCTOTHORPE_PH, "g"), valueStr);
};
return {
plural: (value, cases) => {
const { offset: offset2 = 0 } = cases;
const message = plural(locales, false, value, cases);
return replaceOctothorpe(value - offset2, message);
},
selectordinal: (value, cases) => {
const { offset: offset2 = 0 } = cases;
const message = plural(locales, true, value, cases);
return replaceOctothorpe(value - offset2, message);
},
select: selectFormatter,
number: (value, format) => number$1(
locales,
value,
style(format) || { style: format }
),
date: (value, format) => date(locales, value, style(format) || format),
time: (value, format) => time(locales, value, style(format) || format)
};
};
const selectFormatter = (value, rules) => rules[value] ?? rules.other;
function interpolate(translation, locale, locales) {
return (values = {}, formats) => {
const formatters = getDefaultFormats(locale, locales, formats);
const formatMessage = (tokens, replaceOctothorpe = false) => {
if (!Array.isArray(tokens))
return tokens;
return tokens.reduce((message, token) => {
if (token === "#" && replaceOctothorpe) {
return message + OCTOTHORPE_PH;
}
if (isString(token)) {
return message + token;
}
const [name2, type, format] = token;
let interpolatedFormat = {};
if (type === "plural" || type === "selectordinal" || type === "select") {
Object.entries(format).forEach(
([key, value2]) => {
interpolatedFormat[key] = formatMessage(
value2,
type === "plural" || type === "selectordinal"
);
}
);
} else {
interpolatedFormat = format;
}
let value;
if (type) {
const formatter = formatters[type];
value = formatter(values[name2], interpolatedFormat);
} else {
value = values[name2];
}
if (value == null) {
return message;
}
return message + value;
}, "");
};
const result = formatMessage(translation);
if (isString(result) && ESCAPE_SEQUENCE_REGEX.test(result)) {
return decodeEscapeSequences(result);
}
if (isString(result))
return result;
return result ? String(result) : "";
};
}
var __defProp$1 = Object.defineProperty;
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$1 = (obj, key, value) => {
__defNormalProp$1(obj, key + "", value);
return value;
};
class EventEmitter {
constructor() {
__publicField$1(this, "_events", {});
}
on(event, listener) {
var _a2;
(_a2 = this._events)[event] ?? (_a2[event] = []);
this._events[event].push(listener);
return () => this.removeListener(event, listener);
}
removeListener(event, listener) {
const maybeListeners = this._getListeners(event);
if (!maybeListeners)
return;
const index2 = maybeListeners.indexOf(listener);
if (~index2)
maybeListeners.splice(index2, 1);
}
emit(event, ...args) {
const maybeListeners = this._getListeners(event);
if (!maybeListeners)
return;
maybeListeners.map((listener) => listener.apply(this, args));
}
_getListeners(event) {
const maybeListeners = this._events[event];
return Array.isArray(maybeListeners) ? maybeListeners : false;
}
}
var __defProp2 = Object.defineProperty;
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField2 = (obj, key, value) => {
__defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class I18n extends EventEmitter {
constructor(params) {
super();
__publicField2(this, "_locale", "");
__publicField2(this, "_locales");
__publicField2(this, "_localeData", {});
__publicField2(this, "_messages", {});
__publicField2(this, "_missing");
__publicField2(this, "_messageCompiler");
__publicField2(this, "t", this._.bind(this));
if (process.env.NODE_ENV !== "production") {
this.setMessagesCompiler(compileMessage);
}
if (params.missing != null)
this._missing = params.missing;
if (params.messages != null)
this.load(params.messages);
if (params.localeData != null)
this.loadLocaleData(params.localeData);
if (typeof params.locale === "string" || params.locales) {
this.activate(params.locale ?? defaultLocale, params.locales);
}
}
get locale() {
return this._locale;
}
get locales() {
return this._locales;
}
get messages() {
return this._messages[this._locale] ?? {};
}
/**
* @deprecated this has no effect. Please remove this from the code. Deprecated in v4
*/
get localeData() {
return this._localeData[this._locale] ?? {};
}
_loadLocaleData(locale, localeData) {
const maybeLocaleData = this._localeData[locale];
if (!maybeLocaleData) {
this._localeData[locale] = localeData;
} else {
Object.assign(maybeLocaleData, localeData);
}
}
/**
* Registers a `MessageCompiler` to enable the use of uncompiled catalogs at runtime.
*
* In production builds, the `MessageCompiler` is typically excluded to reduce bundle size.
* By default, message catalogs should be precompiled during the build process. However,
* if you need to compile catalogs at runtime, you can use this method to set a message compiler.
*
* Example usage:
*
* ```ts
* import { compileMessage } from "@lingui/message-utils/compileMessage";
*
* i18n.setMessagesCompiler(compileMessage);
* ```
*/
setMessagesCompiler(compiler2) {
this._messageCompiler = compiler2;
return this;
}
/**
* @deprecated Plurals automatically used from Intl.PluralRules you can safely remove this call. Deprecated in v4
*/
loadLocaleData(localeOrAllData, localeData) {
if (typeof localeOrAllData === "string") {
this._loadLocaleData(localeOrAllData, localeData);
} else {
Object.keys(localeOrAllData).forEach(
(locale) => this._loadLocaleData(locale, localeOrAllData[locale])
);
}
this.emit("change");
}
_load(locale, messages) {
const maybeMessages = this._messages[locale];
if (!maybeMessages) {
this._messages[locale] = messages;
} else {
Object.assign(maybeMessages, messages);
}
}
load(localeOrMessages, messages) {
if (typeof