zpt
Version:
Zenon Page Templates - JS (ZPT-JS)
1,635 lines (1,633 loc) • 179 kB
JavaScript
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
// node_modules/@messageformat/core/messageformat.js
var require_messageformat = __commonJS({
"node_modules/@messageformat/core/messageformat.js"(exports, module) {
(function(global2, factory) {
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, global2.MessageFormat = factory());
})(exports, (function() {
"use strict";
var __assign = function() {
__assign = Object.assign || function __assign2(t2) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t2[p] = s[p];
}
return t2;
};
return __assign.apply(this, arguments);
};
function __values(o2) {
var s = typeof Symbol === "function" && Symbol.iterator, m2 = s && o2[s], i = 0;
if (m2) return m2.call(o2);
if (o2 && typeof o2.length === "number") return {
next: function() {
if (o2 && i >= o2.length) o2 = void 0;
return {
value: o2 && o2[i++],
done: !o2
};
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o2, n) {
var m2 = typeof Symbol === "function" && o2[Symbol.iterator];
if (!m2) return o2;
var i = m2.call(o2), r, ar2 = [], e2;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar2.push(r.value);
} catch (error) {
e2 = {
error
};
} finally {
try {
if (r && !r.done && (m2 = i["return"])) m2.call(i);
} finally {
if (e2) throw e2.error;
}
}
return ar2;
}
function __spreadArray(to2, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar2; i < l; i++) {
if (ar2 || !(i in from)) {
if (!ar2) ar2 = Array.prototype.slice.call(from, 0, i);
ar2[i] = from[i];
}
}
return to2.concat(ar2 || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
var e2 = new Error(message);
return e2.name = "SuppressedError", e2.error = error, e2.suppressed = suppressed, e2;
};
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) {
let onError = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : (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 getDateFormatter(locales, tokens, timeZone, onError) {
if (typeof tokens === "string") tokens = parseDateTokens(tokens);
if (typeof timeZone === "function") {
onError = timeZone;
timeZone = void 0;
}
const opt = getDateFormatOptions(tokens, timeZone, onError);
const dtf = new Intl.DateTimeFormat(locales, opt);
return (date2) => dtf.format(date2);
}
function getDateFormatterSource(locales, tokens, timeZone, onError) {
if (typeof tokens === "string") tokens = parseDateTokens(tokens);
if (typeof timeZone === "function") {
onError = timeZone;
timeZone = void 0;
}
const opt = getDateFormatOptions(tokens, timeZone, onError);
const lines = [`(function() {`, `var opt = ${JSON.stringify(opt)};`, `var dtf = new Intl.DateTimeFormat(${JSON.stringify(locales)}, opt);`, `return function(value) { return dtf.format(value); }`];
return lines.join("\n ") + "\n})()";
}
class NumberFormatError extends Error {
/** @internal */
constructor(code, msg) {
super(msg);
this.code = code;
}
}
class BadOptionError extends NumberFormatError {
constructor(stem, opt) {
super("BAD_OPTION", `Unknown ${stem} option: ${opt}`);
this.stem = stem;
this.option = opt;
}
}
class BadStemError extends NumberFormatError {
constructor(stem) {
super("BAD_STEM", `Unknown stem: ${stem}`);
this.stem = stem;
}
}
class MaskedValueError extends NumberFormatError {
constructor(type, prev) {
super("MASKED_VALUE", `Value for ${type} is set multiple times`);
this.type = type;
this.prev = prev;
}
}
class MissingOptionError extends NumberFormatError {
constructor(stem) {
super("MISSING_OPTION", `Required option missing for ${stem}`);
this.stem = stem;
}
}
class PatternError extends NumberFormatError {
constructor(char, msg) {
super("BAD_PATTERN", msg);
this.char = char;
}
}
class TooManyOptionsError extends NumberFormatError {
constructor(stem, options, maxOpt) {
const maxOptStr = maxOpt > 1 ? `${maxOpt} options` : "one option";
super("TOO_MANY_OPTIONS", `Token ${stem} only supports ${maxOptStr} (got ${options.length})`);
this.stem = stem;
this.options = options;
}
}
class UnsupportedError extends NumberFormatError {
constructor(stem, source) {
super("UNSUPPORTED", `The stem ${stem} is not supported`);
this.stem = stem;
if (source) {
this.message += ` with value ${source}`;
this.source = source;
}
}
}
function getNumberFormatLocales(locales, _ref) {
let {
numberingSystem
} = _ref;
if (!Array.isArray(locales)) locales = [locales];
return numberingSystem ? locales.map((lc) => {
const ext = lc.indexOf("-u-") === -1 ? "u-nu" : "nu";
return `${lc}-${ext}-${numberingSystem}`;
}).concat(locales) : locales;
}
function round(x2, precision) {
const y = +x2 + precision / 2;
return y - y % +precision;
}
function getNumberFormatMultiplier(_ref) {
let {
scale,
unit
} = _ref;
let mult = typeof scale === "number" && scale >= 0 ? scale : 1;
if (unit && unit.style === "percent") mult *= 0.01;
return mult;
}
function getNumberFormatModifier(skeleton) {
const mult = getNumberFormatMultiplier(skeleton);
const {
precision
} = skeleton;
if (precision && precision.style === "precision-increment") {
return (n) => round(n, precision.increment) * mult;
} else {
return (n) => n * mult;
}
}
function getNumberFormatModifierSource(skeleton) {
const mult = getNumberFormatMultiplier(skeleton);
const {
precision
} = skeleton;
if (precision && precision.style === "precision-increment") {
const setX = `+n + ${precision.increment / 2}`;
let res = `x - (x % +${precision.increment})`;
if (mult !== 1) res = `(${res}) * ${mult}`;
return `function(n) { var x = ${setX}; return ${res}; }`;
}
return mult !== 1 ? `function(n) { return n * ${mult}; }` : null;
}
function getNumberFormatOptions(skeleton, onUnsupported) {
const {
decimal,
group,
integerWidth,
notation,
precision,
roundingMode,
sign,
unit,
unitPer,
unitWidth
} = skeleton;
const fail = (stem, source) => {
if (onUnsupported) onUnsupported(new UnsupportedError(stem, source));
};
const opt = {};
if (unit) {
switch (unit.style) {
case "base-unit":
opt.style = "decimal";
break;
case "currency":
opt.style = "currency";
opt.currency = unit.currency;
break;
case "measure-unit":
opt.style = "unit";
opt.unit = unit.unit.replace(/.*-/, "");
if (unitPer) opt.unit += "-per-" + unitPer.replace(/.*-/, "");
break;
case "percent":
opt.style = "percent";
break;
case "permille":
fail("permille");
break;
}
}
switch (unitWidth) {
case "unit-width-full-name":
opt.currencyDisplay = "name";
opt.unitDisplay = "long";
break;
case "unit-width-hidden":
fail(unitWidth);
break;
case "unit-width-iso-code":
opt.currencyDisplay = "code";
break;
case "unit-width-narrow":
opt.currencyDisplay = "narrowSymbol";
opt.unitDisplay = "narrow";
break;
case "unit-width-short":
opt.currencyDisplay = "symbol";
opt.unitDisplay = "short";
break;
}
switch (group) {
case "group-off":
opt.useGrouping = false;
break;
case "group-auto":
opt.useGrouping = true;
break;
case "group-min2":
case "group-on-aligned":
case "group-thousands":
fail(group);
opt.useGrouping = true;
break;
}
if (precision) {
switch (precision.style) {
case "precision-fraction": {
const {
minFraction: minF,
maxFraction: maxF,
minSignificant: minS,
maxSignificant: maxS,
source
} = precision;
if (typeof minF === "number") {
opt.minimumFractionDigits = minF;
if (typeof minS === "number") fail("precision-fraction", source);
}
if (typeof maxF === "number") opt.maximumFractionDigits = maxF;
if (typeof minS === "number") opt.minimumSignificantDigits = minS;
if (typeof maxS === "number") opt.maximumSignificantDigits = maxS;
break;
}
case "precision-integer":
opt.maximumFractionDigits = 0;
break;
case "precision-unlimited":
opt.maximumFractionDigits = 20;
break;
case "precision-increment":
break;
case "precision-currency-standard":
opt.trailingZeroDisplay = precision.trailingZero;
break;
case "precision-currency-cash":
fail(precision.style);
break;
}
}
if (notation) {
switch (notation.style) {
case "compact-short":
opt.notation = "compact";
opt.compactDisplay = "short";
break;
case "compact-long":
opt.notation = "compact";
opt.compactDisplay = "long";
break;
case "notation-simple":
opt.notation = "standard";
break;
case "scientific":
case "engineering": {
const {
expDigits,
expSign,
source,
style
} = notation;
opt.notation = style;
if (expDigits && expDigits > 1 || expSign && expSign !== "sign-auto") {
fail(style, source);
}
break;
}
}
}
if (integerWidth) {
const {
min,
max,
source
} = integerWidth;
if (min > 0) opt.minimumIntegerDigits = min;
if (Number(max) > 0) {
const hasExp = opt.notation === "engineering" || opt.notation === "scientific";
if (max === 3 && hasExp) opt.notation = "engineering";
else fail("integer-width", source);
}
}
switch (sign) {
case "sign-auto":
opt.signDisplay = "auto";
break;
case "sign-always":
opt.signDisplay = "always";
break;
case "sign-except-zero":
opt.signDisplay = "exceptZero";
break;
case "sign-never":
opt.signDisplay = "never";
break;
case "sign-accounting":
opt.currencySign = "accounting";
break;
case "sign-accounting-always":
opt.currencySign = "accounting";
opt.signDisplay = "always";
break;
case "sign-accounting-except-zero":
opt.currencySign = "accounting";
opt.signDisplay = "exceptZero";
break;
}
if (decimal === "decimal-always") fail(decimal);
if (roundingMode) fail(roundingMode);
return opt;
}
function parseAffixToken(src, pos, onError) {
const char = src[pos];
switch (char) {
case "%":
return {
char: "%",
style: "percent",
width: 1
};
case "\u2030":
return {
char: "%",
style: "permille",
width: 1
};
case "\xA4": {
let width = 1;
while (src[++pos] === "\xA4") ++width;
switch (width) {
case 1:
return {
char,
currency: "default",
width
};
case 2:
return {
char,
currency: "iso-code",
width
};
case 3:
return {
char,
currency: "full-name",
width
};
case 5:
return {
char,
currency: "narrow",
width
};
default: {
const msg = `Invalid number (${width}) of \xA4 chars in pattern`;
onError(new PatternError("\xA4", msg));
return null;
}
}
}
case "*": {
const pad = src[pos + 1];
if (pad) return {
char,
pad,
width: 2
};
break;
}
case "+":
case "-":
return {
char,
width: 1
};
case "'": {
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}`;
onError(new PatternError("'", msg));
return {
char,
str,
width
};
} else if (next === "'") {
if (src[++pos] !== "'") return {
char,
str,
width
};
else ++width;
}
str += next;
}
}
}
return null;
}
const isDigit = (char) => char >= "0" && char <= "9";
function parseNumberToken(src, pos) {
const char = src[pos];
if (isDigit(char)) {
let digits = char;
while (true) {
const next = src[++pos];
if (isDigit(next)) digits += next;
else return {
char: "0",
digits,
width: digits.length
};
}
}
switch (char) {
case "#": {
let width = 1;
while (src[++pos] === "#") ++width;
return {
char,
width
};
}
case "@": {
let min = 1;
while (src[++pos] === "@") ++min;
let width = min;
pos -= 1;
while (src[++pos] === "#") ++width;
return {
char,
min,
width
};
}
case "E": {
const plus = src[pos + 1] === "+";
if (plus) ++pos;
let expDigits = 0;
while (src[++pos] === "0") ++expDigits;
const width = (plus ? 2 : 1) + expDigits;
if (expDigits) return {
char,
expDigits,
plus,
width
};
else break;
}
case ".":
case ",":
return {
char,
width: 1
};
}
return null;
}
function parseSubpattern(src, pos, onError) {
let State;
(function(State2) {
State2[State2["Prefix"] = 0] = "Prefix";
State2[State2["Number"] = 1] = "Number";
State2[State2["Suffix"] = 2] = "Suffix";
})(State || (State = {}));
const prefix = [];
const number2 = [];
const suffix = [];
let state = State.Prefix;
let str = "";
while (pos < src.length) {
const char = src[pos];
if (char === ";") {
pos += 1;
break;
}
switch (state) {
case State.Prefix: {
const token = parseAffixToken(src, pos, onError);
if (token) {
if (str) {
prefix.push({
char: "'",
str,
width: str.length
});
str = "";
}
prefix.push(token);
pos += token.width;
} else {
const token2 = parseNumberToken(src, pos);
if (token2) {
if (str) {
prefix.push({
char: "'",
str,
width: str.length
});
str = "";
}
state = State.Number;
number2.push(token2);
pos += token2.width;
} else {
str += char;
pos += 1;
}
}
break;
}
case State.Number: {
const token = parseNumberToken(src, pos);
if (token) {
number2.push(token);
pos += token.width;
} else {
state = State.Suffix;
}
break;
}
case State.Suffix: {
const token = parseAffixToken(src, pos, onError);
if (token) {
if (str) {
suffix.push({
char: "'",
str,
width: str.length
});
str = "";
}
suffix.push(token);
pos += token.width;
} else {
str += char;
pos += 1;
}
break;
}
}
}
if (str) suffix.push({
char: "'",
str,
width: str.length
});
return {
pattern: {
prefix,
number: number2,
suffix
},
pos
};
}
function parseTokens(src, onError) {
const {
pattern,
pos
} = parseSubpattern(src, 0, onError);
if (pos < src.length) {
const {
pattern: negative
} = parseSubpattern(src, pos, onError);
return {
tokens: pattern,
negative
};
}
return {
tokens: pattern
};
}
function parseNumberAsSkeleton(tokens, onError) {
const res = {};
let hasGroups = false;
let hasExponent = false;
let intOptional = 0;
let intDigits = "";
let decimalPos = -1;
let fracDigits = "";
let fracOptional = 0;
for (let pos = 0; pos < tokens.length; ++pos) {
const token = tokens[pos];
switch (token.char) {
case "#": {
if (decimalPos === -1) {
if (intDigits) {
const msg = "Pattern has # after integer digits";
onError(new PatternError("#", msg));
}
intOptional += token.width;
} else {
fracOptional += token.width;
}
break;
}
case "0": {
if (decimalPos === -1) {
intDigits += token.digits;
} else {
if (fracOptional) {
const msg = "Pattern has digits after # in fraction";
onError(new PatternError("0", msg));
}
fracDigits += token.digits;
}
break;
}
case "@": {
if (res.precision) {
onError(new MaskedValueError("precision", res.precision));
}
res.precision = {
style: "precision-fraction",
minSignificant: token.min,
maxSignificant: token.width
};
break;
}
case ",":
hasGroups = true;
break;
case ".":
if (decimalPos === 1) {
const msg = "Pattern has more than one decimal separator";
onError(new PatternError(".", msg));
}
decimalPos = pos;
break;
case "E": {
if (hasExponent) {
onError(new MaskedValueError("exponent", res.notation));
}
if (hasGroups) {
const msg = "Exponential patterns may not contain grouping separators";
onError(new PatternError("E", msg));
}
res.notation = {
style: "scientific"
};
if (token.expDigits > 1) res.notation.expDigits = token.expDigits;
if (token.plus) res.notation.expSign = "sign-always";
hasExponent = true;
}
}
}
if (hasGroups) res.group = "group-auto";
else if (intOptional + intDigits.length > 3) res.group = "group-off";
const increment = Number(`${intDigits || "0"}.${fracDigits}`);
if (increment) res.precision = {
style: "precision-increment",
increment
};
if (!hasExponent) {
if (intDigits.length > 1) res.integerWidth = {
min: intDigits.length
};
if (!res.precision && (fracDigits.length || fracOptional)) {
res.precision = {
style: "precision-fraction",
minFraction: fracDigits.length,
maxFraction: fracDigits.length + fracOptional
};
}
} else {
if (!res.precision || increment) {
res.integerWidth = intOptional ? {
min: 1,
max: intOptional + intDigits.length
} : {
min: Math.max(1, intDigits.length)
};
}
if (res.precision) {
if (!increment) res.integerWidth = {
min: 1,
max: 1
};
} else {
const dc = intDigits.length + fracDigits.length;
if (decimalPos === -1) {
if (dc > 0) {
res.precision = {
style: "precision-fraction",
maxSignificant: dc
};
}
} else {
res.precision = {
style: "precision-fraction",
maxSignificant: Math.max(1, dc) + fracOptional
};
if (dc > 1) res.precision.minSignificant = dc;
}
}
}
return res;
}
function handleAffix(affixTokens, res, currency, onError, isPrefix) {
let inFmt = false;
let str = "";
for (const token of affixTokens) {
switch (token.char) {
case "%":
res.unit = {
style: token.style
};
if (isPrefix) inFmt = true;
else str = "";
break;
case "\xA4":
if (!currency) {
const msg = `The \xA4 pattern requires a currency`;
onError(new PatternError("\xA4", msg));
break;
}
res.unit = {
style: "currency",
currency
};
switch (token.currency) {
case "iso-code":
res.unitWidth = "unit-width-iso-code";
break;
case "full-name":
res.unitWidth = "unit-width-full-name";
break;
case "narrow":
res.unitWidth = "unit-width-narrow";
break;
}
if (isPrefix) inFmt = true;
else str = "";
break;
case "*":
break;
case "+":
if (!inFmt) str += "+";
break;
case "'":
if (!inFmt) str += token.str;
break;
}
}
return str;
}
function getNegativeAffix(affixTokens, isPrefix) {
let inFmt = false;
let str = "";
for (const token of affixTokens) {
switch (token.char) {
case "%":
case "\xA4":
if (isPrefix) inFmt = true;
else str = "";
break;
case "-":
if (!inFmt) str += "-";
break;
case "'":
if (!inFmt) str += token.str;
break;
}
}
return str;
}
function parseNumberPattern(src, currency) {
let onError = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : (error) => {
throw error;
};
const {
tokens,
negative
} = parseTokens(src, onError);
const res = parseNumberAsSkeleton(tokens.number, onError);
const prefix = handleAffix(tokens.prefix, res, currency, onError, true);
const suffix = handleAffix(tokens.suffix, res, currency, onError, false);
if (negative) {
const negPrefix = getNegativeAffix(negative.prefix, true);
const negSuffix = getNegativeAffix(negative.suffix, false);
res.affix = {
pos: [prefix, suffix],
neg: [negPrefix, negSuffix]
};
res.sign = "sign-never";
} else if (prefix || suffix) {
res.affix = {
pos: [prefix, suffix]
};
}
return res;
}
function isNumberingSystem(ns) {
const systems = ["arab", "arabext", "bali", "beng", "deva", "fullwide", "gujr", "guru", "hanidec", "khmr", "knda", "laoo", "latn", "limb", "mlym", "mong", "mymr", "orya", "tamldec", "telu", "thai", "tibt"];
return systems.indexOf(ns) !== -1;
}
function isUnit(unit) {
const types = ["acceleration", "angle", "area", "concentr", "consumption", "digital", "duration", "electric", "energy", "force", "frequency", "graphics", "length", "light", "mass", "power", "pressure", "speed", "temperature", "torque", "volume"];
const [type] = unit.split("-", 1);
return types.indexOf(type) !== -1;
}
const maxOptions = {
"compact-short": 0,
"compact-long": 0,
"notation-simple": 0,
scientific: 2,
engineering: 2,
percent: 0,
permille: 0,
"base-unit": 0,
currency: 1,
"measure-unit": 1,
"per-measure-unit": 1,
"unit-width-narrow": 0,
"unit-width-short": 0,
"unit-width-full-name": 0,
"unit-width-iso-code": 0,
"unit-width-hidden": 0,
"precision-integer": 0,
"precision-unlimited": 0,
"precision-currency-standard": 1,
"precision-currency-cash": 0,
"precision-increment": 1,
"rounding-mode-ceiling": 0,
"rounding-mode-floor": 0,
"rounding-mode-down": 0,
"rounding-mode-up": 0,
"rounding-mode-half-even": 0,
"rounding-mode-half-down": 0,
"rounding-mode-half-up": 0,
"rounding-mode-unnecessary": 0,
"integer-width": 1,
scale: 1,
"group-off": 0,
"group-min2": 0,
"group-auto": 0,
"group-on-aligned": 0,
"group-thousands": 0,
latin: 0,
"numbering-system": 1,
"sign-auto": 0,
"sign-always": 0,
"sign-never": 0,
"sign-accounting": 0,
"sign-accounting-always": 0,
"sign-except-zero": 0,
"sign-accounting-except-zero": 0,
"decimal-auto": 0,
"decimal-always": 0
};
const minOptions = {
currency: 1,
"integer-width": 1,
"measure-unit": 1,
"numbering-system": 1,
"per-measure-unit": 1,
"precision-increment": 1,
scale: 1
};
function hasMaxOption(stem) {
return stem in maxOptions;
}
function hasMinOption(stem) {
return stem in minOptions;
}
function validOptions(stem, options, onError) {
if (hasMaxOption(stem)) {
const maxOpt = maxOptions[stem];
if (options.length > maxOpt) {
if (maxOpt === 0) {
for (const opt of options) onError(new BadOptionError(stem, opt));
} else {
onError(new TooManyOptionsError(stem, options, maxOpt));
}
return false;
} else if (hasMinOption(stem) && options.length < minOptions[stem]) {
onError(new MissingOptionError(stem));
return false;
}
}
return true;
}
function parseBlueprintDigits(src, style) {
const re = style === "fraction" ? /^\.(0*)(\+|#*)$/ : /^(@+)(\+|#*)$/;
const match = src && src.match(re);
if (match) {
const min = match[1].length;
switch (match[2].charAt(0)) {
case "":
return {
min,
max: min
};
case "+":
return {
min,
max: null
};
case "#": {
return {
min,
max: min + match[2].length
};
}
}
}
return null;
}
function parsePrecisionBlueprint(stem, options, onError) {
const fd = parseBlueprintDigits(stem, "fraction");
if (fd) {
if (options.length > 1) onError(new TooManyOptionsError(stem, options, 1));
const res = {
style: "precision-fraction",
source: stem,
minFraction: fd.min
};
if (fd.max != null) res.maxFraction = fd.max;
const option = options[0];
const sd3 = parseBlueprintDigits(option, "significant");
if (sd3) {
res.source = `${stem}/${option}`;
res.minSignificant = sd3.min;
if (sd3.max != null) res.maxSignificant = sd3.max;
} else if (option) {
onError(new BadOptionError(stem, option));
}
return res;
}
const sd2 = parseBlueprintDigits(stem, "significant");
if (sd2) {
for (const opt of options) onError(new BadOptionError(stem, opt));
const res = {
style: "precision-fraction",
source: stem,
minSignificant: sd2.min
};
if (sd2.max != null) res.maxSignificant = sd2.max;
return res;
}
return null;
}
class TokenParser {
constructor(onError) {
this.skeleton = {};
this.onError = onError;
}
badOption(stem, opt) {
this.onError(new BadOptionError(stem, opt));
}
assertEmpty(key) {
const prev = this.skeleton[key];
if (prev) this.onError(new MaskedValueError(key, prev));
}
parseToken(stem, options) {
if (!validOptions(stem, options, this.onError)) return;
const option = options[0];
const res = this.skeleton;
switch (stem) {
// notation
case "compact-short":
case "compact-long":
case "notation-simple":
this.assertEmpty("notation");
res.notation = {
style: stem
};
break;
case "scientific":
case "engineering": {
let expDigits = null;
let expSign = void 0;
for (const opt of options) {
switch (opt) {
case "sign-auto":
case "sign-always":
case "sign-never":
case "sign-accounting":
case "sign-accounting-always":
case "sign-except-zero":
case "sign-accounting-except-zero":
expSign = opt;
break;
default:
if (/^\+e+$/.test(opt)) {
expDigits = opt.length - 1;
} else {
this.badOption(stem, opt);
}
}
}
this.assertEmpty("notation");
const source = options.join("/");
res.notation = expDigits && expSign ? {
style: stem,
source,
expDigits,
expSign
} : expDigits ? {
style: stem,
source,
expDigits
} : expSign ? {
style: stem,
source,
expSign
} : {
style: stem,
source
};
break;
}
// unit
case "percent":
case "permille":
case "base-unit":
this.assertEmpty("unit");
res.unit = {
style: stem
};
break;
case "currency":
if (/^[A-Z]{3}$/.test(option)) {
this.assertEmpty("unit");
res.unit = {
style: stem,
currency: option
};
} else {
this.badOption(stem, option);
}
break;
case "measure-unit": {
if (isUnit(option)) {
this.assertEmpty("unit");
res.unit = {
style: stem,
unit: option
};
} else {
this.badOption(stem, option);
}
break;
}
// unitPer
case "per-measure-unit": {
if (isUnit(option)) {
this.assertEmpty("unitPer");
res.unitPer = option;
} else {
this.badOption(stem, option);
}
break;
}
// unitWidth
case "unit-width-narrow":
case "unit-width-short":
case "unit-width-full-name":
case "unit-width-iso-code":
case "unit-width-hidden":
this.assertEmpty("unitWidth");
res.unitWidth = stem;
break;
// precision
case "precision-integer":
case "precision-unlimited":
case "precision-currency-cash":
this.assertEmpty("precision");
res.precision = {
style: stem
};
break;
case "precision-currency-standard":
this.assertEmpty("precision");
if (option === "w") {
res.precision = {
style: stem,
trailingZero: "stripIfInteger"
};
} else {
res.precision = {
style: stem
};
}
break;
case "precision-increment": {
const increment = Number(option);
if (increment > 0) {
this.assertEmpty("precision");
res.precision = {
style: stem,
increment
};
} else {
this.badOption(stem, option);
}
break;
}
// roundingMode
case "rounding-mode-ceiling":
case "rounding-mode-floor":
case "rounding-mode-down":
case "rounding-mode-up":
case "rounding-mode-half-even":
case "rounding-mode-half-odd":
case "rounding-mode-half-ceiling":
case "rounding-mode-half-floor":
case "rounding-mode-half-down":
case "rounding-mode-half-up":
case "rounding-mode-unnecessary":
this.assertEmpty("roundingMode");
res.roundingMode = stem;
break;
// integerWidth
case "integer-width": {
if (/^\+0*$/.test(option)) {
this.assertEmpty("integerWidth");
res.integerWidth = {
source: option,
min: option.length - 1
};
} else {
const m2 = option.match(/^#*(0*)$/);
if (m2) {
this.assertEmpty("integerWidth");
res.integerWidth = {
source: option,
min: m2[1].length,