Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

intl-messageformat

Package Overview
Dependencies
Maintainers
3
Versions
295
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

intl-messageformat - npm Package Compare versions

Comparing version
11.0.8
to
11.0.9
+9
-4
index.d.ts

@@ -1,6 +0,11 @@

import { IntlMessageFormat } from './src/core.js';
export * from './src/core.js';
export * from './src/error.js';
export * from './src/formatters.js';
/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/
import { IntlMessageFormat } from "./src/core.js";
export * from "./src/core.js";
export * from "./src/error.js";
export * from "./src/formatters.js";
export { IntlMessageFormat };
export default IntlMessageFormat;

@@ -6,7 +6,7 @@ /*

*/
import { IntlMessageFormat } from './src/core.js';
export * from './src/core.js';
export * from './src/error.js';
export * from './src/formatters.js';
import { IntlMessageFormat } from "./src/core.js";
export * from "./src/core.js";
export * from "./src/error.js";
export * from "./src/formatters.js";
export { IntlMessageFormat };
export default IntlMessageFormat;
{
"name": "intl-messageformat",
"description": "Formats ICU Message strings with number, date, plural, and select placeholders to create localized messages.",
"version": "11.0.8",
"version": "11.0.9",
"license": "BSD-3-Clause",

@@ -15,5 +15,5 @@ "author": "Eric Ferraiuolo <eferraiuolo@gmail.com>",

"tslib": "^2.8.0",
"@formatjs/ecma402-abstract": "3.0.7",
"@formatjs/icu-messageformat-parser": "3.2.1",
"@formatjs/fast-memoize": "3.0.2"
"@formatjs/ecma402-abstract": "3.0.8",
"@formatjs/fast-memoize": "3.0.3",
"@formatjs/icu-messageformat-parser": "3.3.0"
},

@@ -20,0 +20,0 @@ "bugs": "https://github.com/formatjs/formatjs/issues",

@@ -1,26 +0,29 @@

import { MessageFormatElement, parse, ParserOptions } from '@formatjs/icu-messageformat-parser';
import { Formats, Formatters, FormatXMLElementFn, MessageFormatPart, PrimitiveType } from './formatters.js';
export interface Options extends Omit<ParserOptions, 'locale'> {
formatters?: Formatters;
import { type MessageFormatElement, parse, type ParserOptions } from "@formatjs/icu-messageformat-parser";
import { type Formats, type Formatters, type FormatXMLElementFn, type MessageFormatPart, type PrimitiveType } from "./formatters.js";
export interface Options extends Omit<ParserOptions, "locale"> {
formatters?: Formatters;
}
export declare class IntlMessageFormat {
private readonly ast;
private readonly locales;
private readonly resolvedLocale?;
private readonly formatters;
private readonly formats;
private readonly message;
private readonly formatterCache;
constructor(message: string | MessageFormatElement[], locales?: string | string[], overrideFormats?: Partial<Formats>, opts?: Options);
format: <T = void>(values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>) => string | T | (string | T)[];
formatToParts: <T>(values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>) => MessageFormatPart<T>[];
resolvedOptions: () => {
locale: string;
};
getAst: () => MessageFormatElement[];
private static memoizedDefaultLocale;
static get defaultLocale(): string;
static resolveLocale: (locales: string | string[]) => Intl.Locale | undefined;
static __parse: typeof parse | undefined;
static formats: Formats;
private readonly ast;
private readonly locales;
private readonly resolvedLocale?;
private readonly formatters;
private readonly formats;
private readonly message;
private readonly formatterCache;
constructor(message: string | MessageFormatElement[], locales?: string | string[], overrideFormats?: Partial<Formats>, opts?: Options);
format: <T = void>(values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>) => string | T | (string | T)[];
formatToParts: <T>(values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>) => MessageFormatPart<T>[];
resolvedOptions: () => {
locale: string;
};
getAst: () => MessageFormatElement[];
private static memoizedDefaultLocale;
static get defaultLocale(): string;
static resolveLocale: (locales: string | string[]) => Intl.Locale | undefined;
static __parse: typeof parse | undefined;
// Default format options used as the prototype of the `formats` provided to the
// constructor. These are used when constructing the internal Intl.NumberFormat
// and Intl.DateTimeFormat instances.
static formats: Formats;
}
+188
-227

@@ -6,236 +6,197 @@ /*

*/
import { __assign, __rest, __spreadArray } from "tslib";
import { memoize, strategies } from '@formatjs/fast-memoize';
import { parse, } from '@formatjs/icu-messageformat-parser';
import { formatToParts, PART_TYPE, } from './formatters.js';
import { memoize, strategies } from "@formatjs/fast-memoize";
import { parse } from "@formatjs/icu-messageformat-parser";
import { formatToParts, PART_TYPE } from "./formatters.js";
// -- MessageFormat --------------------------------------------------------
function mergeConfig(c1, c2) {
if (!c2) {
return c1;
}
return __assign(__assign(__assign({}, c1), c2), Object.keys(c1).reduce(function (all, k) {
all[k] = __assign(__assign({}, c1[k]), c2[k]);
return all;
}, {}));
if (!c2) {
return c1;
}
return {
...c1,
...c2,
...Object.keys(c1).reduce((all, k) => {
all[k] = {
...c1[k],
...c2[k]
};
return all;
}, {})
};
}
function mergeConfigs(defaultConfig, configs) {
if (!configs) {
return defaultConfig;
}
return Object.keys(defaultConfig).reduce(function (all, k) {
all[k] = mergeConfig(defaultConfig[k], configs[k]);
return all;
}, __assign({}, defaultConfig));
if (!configs) {
return defaultConfig;
}
return Object.keys(defaultConfig).reduce((all, k) => {
all[k] = mergeConfig(defaultConfig[k], configs[k]);
return all;
}, { ...defaultConfig });
}
function createFastMemoizeCache(store) {
return {
create: function () {
return {
get: function (key) {
return store[key];
},
set: function (key, value) {
store[key] = value;
},
};
},
};
return { create() {
return {
get(key) {
return store[key];
},
set(key, value) {
store[key] = value;
}
};
} };
}
function createDefaultFormatters(cache) {
if (cache === void 0) { cache = {
number: {},
dateTime: {},
pluralRules: {},
}; }
return {
getNumberFormat: memoize(function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return new ((_a = Intl.NumberFormat).bind.apply(_a, __spreadArray([void 0], args, false)))();
}, {
cache: createFastMemoizeCache(cache.number),
strategy: strategies.variadic,
}),
getDateTimeFormat: memoize(function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return new ((_a = Intl.DateTimeFormat).bind.apply(_a, __spreadArray([void 0], args, false)))();
}, {
cache: createFastMemoizeCache(cache.dateTime),
strategy: strategies.variadic,
}),
getPluralRules: memoize(function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return new ((_a = Intl.PluralRules).bind.apply(_a, __spreadArray([void 0], args, false)))();
}, {
cache: createFastMemoizeCache(cache.pluralRules),
strategy: strategies.variadic,
}),
};
function createDefaultFormatters(cache = {
number: {},
dateTime: {},
pluralRules: {}
}) {
return {
getNumberFormat: memoize((...args) => new Intl.NumberFormat(...args), {
cache: createFastMemoizeCache(cache.number),
strategy: strategies.variadic
}),
getDateTimeFormat: memoize((...args) => new Intl.DateTimeFormat(...args), {
cache: createFastMemoizeCache(cache.dateTime),
strategy: strategies.variadic
}),
getPluralRules: memoize((...args) => new Intl.PluralRules(...args), {
cache: createFastMemoizeCache(cache.pluralRules),
strategy: strategies.variadic
})
};
}
var IntlMessageFormat = /** @class */ (function () {
function IntlMessageFormat(message, locales, overrideFormats, opts) {
if (locales === void 0) { locales = IntlMessageFormat.defaultLocale; }
var _this = this;
this.formatterCache = {
number: {},
dateTime: {},
pluralRules: {},
};
this.format = function (values) {
var parts = _this.formatToParts(values);
// Hot path for straight simple msg translations
if (parts.length === 1) {
return parts[0].value;
}
var result = parts.reduce(function (all, part) {
if (!all.length ||
part.type !== PART_TYPE.literal ||
typeof all[all.length - 1] !== 'string') {
all.push(part.value);
}
else {
all[all.length - 1] += part.value;
}
return all;
}, []);
if (result.length <= 1) {
return result[0] || '';
}
return result;
};
this.formatToParts = function (values) {
return formatToParts(_this.ast, _this.locales, _this.formatters, _this.formats, values, undefined, _this.message);
};
this.resolvedOptions = function () {
var _a;
return ({
locale: ((_a = _this.resolvedLocale) === null || _a === void 0 ? void 0 : _a.toString()) ||
Intl.NumberFormat.supportedLocalesOf(_this.locales)[0],
});
};
this.getAst = function () { return _this.ast; };
// Defined first because it's used to build the format pattern.
this.locales = locales;
this.resolvedLocale = IntlMessageFormat.resolveLocale(locales);
if (typeof message === 'string') {
this.message = message;
if (!IntlMessageFormat.__parse) {
throw new TypeError('IntlMessageFormat.__parse must be set to process `message` of type `string`');
}
var parseOpts = __rest(opts || {}
// Parse string messages into an AST.
, []);
// Parse string messages into an AST.
this.ast = IntlMessageFormat.__parse(message, __assign(__assign({}, parseOpts), { locale: this.resolvedLocale }));
}
else {
this.ast = message;
}
if (!Array.isArray(this.ast)) {
throw new TypeError('A message must be provided as a String or AST.');
}
// Creates a new object with the specified `formats` merged with the default
// formats.
this.formats = mergeConfigs(IntlMessageFormat.formats, overrideFormats);
this.formatters =
(opts && opts.formatters) || createDefaultFormatters(this.formatterCache);
}
Object.defineProperty(IntlMessageFormat, "defaultLocale", {
get: function () {
if (!IntlMessageFormat.memoizedDefaultLocale) {
IntlMessageFormat.memoizedDefaultLocale =
new Intl.NumberFormat().resolvedOptions().locale;
}
return IntlMessageFormat.memoizedDefaultLocale;
},
enumerable: false,
configurable: true
});
IntlMessageFormat.memoizedDefaultLocale = null;
IntlMessageFormat.resolveLocale = function (locales) {
if (typeof Intl.Locale === 'undefined') {
return;
}
var supportedLocales = Intl.NumberFormat.supportedLocalesOf(locales);
if (supportedLocales.length > 0) {
return new Intl.Locale(supportedLocales[0]);
}
return new Intl.Locale(typeof locales === 'string' ? locales : locales[0]);
};
IntlMessageFormat.__parse = parse;
// Default format options used as the prototype of the `formats` provided to the
// constructor. These are used when constructing the internal Intl.NumberFormat
// and Intl.DateTimeFormat instances.
IntlMessageFormat.formats = {
number: {
integer: {
maximumFractionDigits: 0,
},
currency: {
style: 'currency',
},
percent: {
style: 'percent',
},
},
date: {
short: {
month: 'numeric',
day: 'numeric',
year: '2-digit',
},
medium: {
month: 'short',
day: 'numeric',
year: 'numeric',
},
long: {
month: 'long',
day: 'numeric',
year: 'numeric',
},
full: {
weekday: 'long',
month: 'long',
day: 'numeric',
year: 'numeric',
},
},
time: {
short: {
hour: 'numeric',
minute: 'numeric',
},
medium: {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
},
long: {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'short',
},
full: {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'short',
},
},
};
return IntlMessageFormat;
}());
export { IntlMessageFormat };
export class IntlMessageFormat {
ast;
locales;
resolvedLocale;
formatters;
formats;
message;
formatterCache = {
number: {},
dateTime: {},
pluralRules: {}
};
constructor(message, locales = IntlMessageFormat.defaultLocale, overrideFormats, opts) {
// Defined first because it's used to build the format pattern.
this.locales = locales;
this.resolvedLocale = IntlMessageFormat.resolveLocale(locales);
if (typeof message === "string") {
this.message = message;
if (!IntlMessageFormat.__parse) {
throw new TypeError("IntlMessageFormat.__parse must be set to process `message` of type `string`");
}
const { ...parseOpts } = opts || {};
// Parse string messages into an AST.
this.ast = IntlMessageFormat.__parse(message, {
...parseOpts,
locale: this.resolvedLocale
});
} else {
this.ast = message;
}
if (!Array.isArray(this.ast)) {
throw new TypeError("A message must be provided as a String or AST.");
}
// Creates a new object with the specified `formats` merged with the default
// formats.
this.formats = mergeConfigs(IntlMessageFormat.formats, overrideFormats);
this.formatters = opts && opts.formatters || createDefaultFormatters(this.formatterCache);
}
format = (values) => {
const parts = this.formatToParts(values);
// Hot path for straight simple msg translations
if (parts.length === 1) {
return parts[0].value;
}
const result = parts.reduce((all, part) => {
if (!all.length || part.type !== PART_TYPE.literal || typeof all[all.length - 1] !== "string") {
all.push(part.value);
} else {
all[all.length - 1] += part.value;
}
return all;
}, []);
if (result.length <= 1) {
return result[0] || "";
}
return result;
};
formatToParts = (values) => formatToParts(this.ast, this.locales, this.formatters, this.formats, values, undefined, this.message);
resolvedOptions = () => ({ locale: this.resolvedLocale?.toString() || Intl.NumberFormat.supportedLocalesOf(this.locales)[0] });
getAst = () => this.ast;
static memoizedDefaultLocale = null;
static get defaultLocale() {
if (!IntlMessageFormat.memoizedDefaultLocale) {
IntlMessageFormat.memoizedDefaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
}
return IntlMessageFormat.memoizedDefaultLocale;
}
static resolveLocale = (locales) => {
if (typeof Intl.Locale === "undefined") {
return;
}
const supportedLocales = Intl.NumberFormat.supportedLocalesOf(locales);
if (supportedLocales.length > 0) {
return new Intl.Locale(supportedLocales[0]);
}
return new Intl.Locale(typeof locales === "string" ? locales : locales[0]);
};
static __parse = parse;
// Default format options used as the prototype of the `formats` provided to the
// constructor. These are used when constructing the internal Intl.NumberFormat
// and Intl.DateTimeFormat instances.
static formats = {
number: {
integer: { maximumFractionDigits: 0 },
currency: { style: "currency" },
percent: { style: "percent" }
},
date: {
short: {
month: "numeric",
day: "numeric",
year: "2-digit"
},
medium: {
month: "short",
day: "numeric",
year: "numeric"
},
long: {
month: "long",
day: "numeric",
year: "numeric"
},
full: {
weekday: "long",
month: "long",
day: "numeric",
year: "numeric"
}
},
time: {
short: {
hour: "numeric",
minute: "numeric"
},
medium: {
hour: "numeric",
minute: "numeric",
second: "numeric"
},
long: {
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZoneName: "short"
},
full: {
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZoneName: "short"
}
}
};
}
export declare enum ErrorCode {
MISSING_VALUE = "MISSING_VALUE",
INVALID_VALUE = "INVALID_VALUE",
MISSING_INTL_API = "MISSING_INTL_API"
// When we have a placeholder but no value to format
MISSING_VALUE = "MISSING_VALUE",
// When value supplied is invalid
INVALID_VALUE = "INVALID_VALUE",
// When we need specific Intl API but it's not available
MISSING_INTL_API = "MISSING_INTL_API"
}
export declare class FormatError extends Error {
readonly code: ErrorCode;
/**
* Original message we're trying to format
* `undefined` if we're only dealing w/ AST
*
* @type {(string | undefined)}
* @memberof FormatError
*/
readonly originalMessage: string | undefined;
constructor(msg: string, code: ErrorCode, originalMessage?: string);
toString(): string;
readonly code: ErrorCode;
/**
* Original message we're trying to format
* `undefined` if we're only dealing w/ AST
*
* @type {(string | undefined)}
* @memberof FormatError
*/
readonly originalMessage: string | undefined;
constructor(msg: string, code: ErrorCode, originalMessage?: string);
toString(): string;
}
export declare class InvalidValueError extends FormatError {
constructor(variableId: string, value: any, options: string[], originalMessage?: string);
constructor(variableId: string, value: any, options: string[], originalMessage?: string);
}
export declare class InvalidValueTypeError extends FormatError {
constructor(value: any, type: string, originalMessage?: string);
constructor(value: any, type: string, originalMessage?: string);
}
export declare class MissingValueError extends FormatError {
constructor(variableId: string, originalMessage?: string);
constructor(variableId: string, originalMessage?: string);
}

@@ -1,48 +0,43 @@

import { __extends } from "tslib";
export var ErrorCode;
(function (ErrorCode) {
// When we have a placeholder but no value to format
ErrorCode["MISSING_VALUE"] = "MISSING_VALUE";
// When value supplied is invalid
ErrorCode["INVALID_VALUE"] = "INVALID_VALUE";
// When we need specific Intl API but it's not available
ErrorCode["MISSING_INTL_API"] = "MISSING_INTL_API";
})(ErrorCode || (ErrorCode = {}));
var FormatError = /** @class */ (function (_super) {
__extends(FormatError, _super);
function FormatError(msg, code, originalMessage) {
var _this = _super.call(this, msg) || this;
_this.code = code;
_this.originalMessage = originalMessage;
return _this;
}
FormatError.prototype.toString = function () {
return "[formatjs Error: ".concat(this.code, "] ").concat(this.message);
};
return FormatError;
}(Error));
export { FormatError };
var InvalidValueError = /** @class */ (function (_super) {
__extends(InvalidValueError, _super);
function InvalidValueError(variableId, value, options, originalMessage) {
return _super.call(this, "Invalid values for \"".concat(variableId, "\": \"").concat(value, "\". Options are \"").concat(Object.keys(options).join('", "'), "\""), ErrorCode.INVALID_VALUE, originalMessage) || this;
}
return InvalidValueError;
}(FormatError));
export { InvalidValueError };
var InvalidValueTypeError = /** @class */ (function (_super) {
__extends(InvalidValueTypeError, _super);
function InvalidValueTypeError(value, type, originalMessage) {
return _super.call(this, "Value for \"".concat(value, "\" must be of type ").concat(type), ErrorCode.INVALID_VALUE, originalMessage) || this;
}
return InvalidValueTypeError;
}(FormatError));
export { InvalidValueTypeError };
var MissingValueError = /** @class */ (function (_super) {
__extends(MissingValueError, _super);
function MissingValueError(variableId, originalMessage) {
return _super.call(this, "The intl string context variable \"".concat(variableId, "\" was not provided to the string \"").concat(originalMessage, "\""), ErrorCode.MISSING_VALUE, originalMessage) || this;
}
return MissingValueError;
}(FormatError));
export { MissingValueError };
export let ErrorCode = /* @__PURE__ */ function(ErrorCode) {
// When we have a placeholder but no value to format
ErrorCode["MISSING_VALUE"] = "MISSING_VALUE";
// When value supplied is invalid
ErrorCode["INVALID_VALUE"] = "INVALID_VALUE";
// When we need specific Intl API but it's not available
ErrorCode["MISSING_INTL_API"] = "MISSING_INTL_API";
return ErrorCode;
}({});
export class FormatError extends Error {
code;
/**
* Original message we're trying to format
* `undefined` if we're only dealing w/ AST
*
* @type {(string | undefined)}
* @memberof FormatError
*/
originalMessage;
constructor(msg, code, originalMessage) {
super(msg);
this.code = code;
this.originalMessage = originalMessage;
}
toString() {
return `[formatjs Error: ${this.code}] ${this.message}`;
}
}
export class InvalidValueError extends FormatError {
constructor(variableId, value, options, originalMessage) {
super(`Invalid values for "${variableId}": "${value}". Options are "${Object.keys(options).join("\", \"")}"`, ErrorCode.INVALID_VALUE, originalMessage);
}
}
export class InvalidValueTypeError extends FormatError {
constructor(value, type, originalMessage) {
super(`Value for "${value}" must be of type ${type}`, ErrorCode.INVALID_VALUE, originalMessage);
}
}
export class MissingValueError extends FormatError {
constructor(variableId, originalMessage) {
super(`The intl string context variable "${variableId}" was not provided to the string "${originalMessage}"`, ErrorCode.MISSING_VALUE, originalMessage);
}
}

@@ -1,40 +0,37 @@

import { NumberFormatOptions } from '@formatjs/ecma402-abstract';
import { MessageFormatElement } from '@formatjs/icu-messageformat-parser';
import { type NumberFormatOptions } from "@formatjs/ecma402-abstract";
import { type MessageFormatElement } from "@formatjs/icu-messageformat-parser";
declare global {
namespace FormatjsIntl {
interface Message {
}
interface IntlConfig {
}
interface Formats {
}
}
namespace FormatjsIntl {
interface Message {}
interface IntlConfig {}
interface Formats {}
}
}
type Format<Source = string> = Source extends keyof FormatjsIntl.Formats ? FormatjsIntl.Formats[Source] : string;
export interface Formats {
number: Record<Format<'number'>, NumberFormatOptions>;
date: Record<Format<'date'>, Intl.DateTimeFormatOptions>;
time: Record<Format<'time'>, Intl.DateTimeFormatOptions>;
number: Record<Format<"number">, NumberFormatOptions>;
date: Record<Format<"date">, Intl.DateTimeFormatOptions>;
time: Record<Format<"time">, Intl.DateTimeFormatOptions>;
}
export interface FormatterCache {
number: Record<string, NumberFormatOptions>;
dateTime: Record<string, Intl.DateTimeFormat>;
pluralRules: Record<string, Intl.PluralRules>;
number: Record<string, NumberFormatOptions>;
dateTime: Record<string, Intl.DateTimeFormat>;
pluralRules: Record<string, Intl.PluralRules>;
}
export interface Formatters {
getNumberFormat(locals?: string | string[], opts?: NumberFormatOptions): Intl.NumberFormat;
getDateTimeFormat(...args: ConstructorParameters<typeof Intl.DateTimeFormat>): Intl.DateTimeFormat;
getPluralRules(...args: ConstructorParameters<typeof Intl.PluralRules>): Intl.PluralRules;
getNumberFormat(locals?: string | string[], opts?: NumberFormatOptions): Intl.NumberFormat;
getDateTimeFormat(...args: ConstructorParameters<typeof Intl.DateTimeFormat>): Intl.DateTimeFormat;
getPluralRules(...args: ConstructorParameters<typeof Intl.PluralRules>): Intl.PluralRules;
}
export declare enum PART_TYPE {
literal = 0,
object = 1
literal = 0,
object = 1
}
export interface LiteralPart {
type: PART_TYPE.literal;
value: string;
type: PART_TYPE.literal;
value: string;
}
export interface ObjectPart<T = any> {
type: PART_TYPE.object;
value: T;
type: PART_TYPE.object;
value: T;
}

@@ -44,4 +41,8 @@ export type MessageFormatPart<T> = LiteralPart | ObjectPart<T>;

export declare function isFormatXMLElementFn<T>(el: PrimitiveType | T | FormatXMLElementFn<T>): el is FormatXMLElementFn<T>;
// TODO(skeleton): add skeleton support
export declare function formatToParts<T>(els: MessageFormatElement[], locales: string | string[], formatters: Formatters, formats: Formats, values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>, currentPluralValue?: number, originalMessage?: string): MessageFormatPart<T>[];
export type FormatXMLElementFn<T, R = string | T | (string | T)[]> = (parts: Array<string | T>) => R;
export type FormatXMLElementFn<
T,
R = string | T | (string | T)[]
> = (parts: Array<string | T>) => R;
export {};

@@ -1,207 +0,166 @@

import { isArgumentElement, isDateElement, isDateTimeSkeleton, isLiteralElement, isNumberElement, isNumberSkeleton, isPluralElement, isPoundElement, isSelectElement, isTagElement, isTimeElement, } from '@formatjs/icu-messageformat-parser';
import { ErrorCode, FormatError, InvalidValueError, InvalidValueTypeError, MissingValueError, } from './error.js';
export var PART_TYPE;
(function (PART_TYPE) {
PART_TYPE[PART_TYPE["literal"] = 0] = "literal";
PART_TYPE[PART_TYPE["object"] = 1] = "object";
})(PART_TYPE || (PART_TYPE = {}));
import "@formatjs/ecma402-abstract";
import { isArgumentElement, isDateElement, isDateTimeSkeleton, isLiteralElement, isNumberElement, isNumberSkeleton, isPluralElement, isPoundElement, isSelectElement, isTagElement, isTimeElement } from "@formatjs/icu-messageformat-parser";
import { ErrorCode, FormatError, InvalidValueError, InvalidValueTypeError, MissingValueError } from "./error.js";
export let PART_TYPE = /* @__PURE__ */ function(PART_TYPE) {
PART_TYPE[PART_TYPE["literal"] = 0] = "literal";
PART_TYPE[PART_TYPE["object"] = 1] = "object";
return PART_TYPE;
}({});
function mergeLiteral(parts) {
if (parts.length < 2) {
return parts;
}
return parts.reduce(function (all, part) {
var lastPart = all[all.length - 1];
if (!lastPart ||
lastPart.type !== PART_TYPE.literal ||
part.type !== PART_TYPE.literal) {
all.push(part);
}
else {
lastPart.value += part.value;
}
return all;
}, []);
if (parts.length < 2) {
return parts;
}
return parts.reduce((all, part) => {
const lastPart = all[all.length - 1];
if (!lastPart || lastPart.type !== PART_TYPE.literal || part.type !== PART_TYPE.literal) {
all.push(part);
} else {
lastPart.value += part.value;
}
return all;
}, []);
}
export function isFormatXMLElementFn(el) {
return typeof el === 'function';
return typeof el === "function";
}
// TODO(skeleton): add skeleton support
export function formatToParts(els, locales, formatters, formats, values, currentPluralValue,
// For debugging
originalMessage) {
// Hot path for straight simple msg translations
if (els.length === 1 && isLiteralElement(els[0])) {
return [
{
type: PART_TYPE.literal,
value: els[0].value,
},
];
}
var result = [];
for (var _i = 0, els_1 = els; _i < els_1.length; _i++) {
var el = els_1[_i];
// Exit early for string parts.
if (isLiteralElement(el)) {
result.push({
type: PART_TYPE.literal,
value: el.value,
});
continue;
}
// TODO: should this part be literal type?
// Replace `#` in plural rules with the actual numeric value.
if (isPoundElement(el)) {
if (typeof currentPluralValue === 'number') {
result.push({
type: PART_TYPE.literal,
value: formatters.getNumberFormat(locales).format(currentPluralValue),
});
}
continue;
}
var varName = el.value;
// Enforce that all required values are provided by the caller.
if (!(values && varName in values)) {
throw new MissingValueError(varName, originalMessage);
}
var value = values[varName];
if (isArgumentElement(el)) {
if (!value ||
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'bigint') {
value =
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'bigint'
? String(value)
: '';
}
result.push({
type: typeof value === 'string' ? PART_TYPE.literal : PART_TYPE.object,
value: value,
});
continue;
}
// Recursively format plural and select parts' option — which can be a
// nested pattern structure. The choosing of the option to use is
// abstracted-by and delegated-to the part helper object.
if (isDateElement(el)) {
var style = typeof el.style === 'string'
? formats.date[el.style]
: isDateTimeSkeleton(el.style)
? el.style.parsedOptions
: undefined;
result.push({
type: PART_TYPE.literal,
value: formatters
.getDateTimeFormat(locales, style)
.format(value),
});
continue;
}
if (isTimeElement(el)) {
var style = typeof el.style === 'string'
? formats.time[el.style]
: isDateTimeSkeleton(el.style)
? el.style.parsedOptions
: formats.time.medium;
result.push({
type: PART_TYPE.literal,
value: formatters
.getDateTimeFormat(locales, style)
.format(value),
});
continue;
}
if (isNumberElement(el)) {
var style = typeof el.style === 'string'
? formats.number[el.style]
: isNumberSkeleton(el.style)
? el.style.parsedOptions
: undefined;
if (style && style.scale) {
var scale = style.scale || 1;
// Handle bigint scale multiplication
// BigInt can only be multiplied by BigInt
if (typeof value === 'bigint') {
// Check if scale is a safe integer that can be converted to BigInt
if (!Number.isInteger(scale)) {
throw new TypeError("Cannot apply fractional scale ".concat(scale, " to bigint value. Scale must be an integer when formatting bigint."));
}
value = value * BigInt(scale);
}
else {
value = value * scale;
}
}
result.push({
type: PART_TYPE.literal,
value: formatters
.getNumberFormat(locales, style)
.format(value),
});
continue;
}
if (isTagElement(el)) {
var children = el.children, value_1 = el.value;
var formatFn = values[value_1];
if (!isFormatXMLElementFn(formatFn)) {
throw new InvalidValueTypeError(value_1, 'function', originalMessage);
}
var parts = formatToParts(children, locales, formatters, formats, values, currentPluralValue);
var chunks = formatFn(parts.map(function (p) { return p.value; }));
if (!Array.isArray(chunks)) {
chunks = [chunks];
}
result.push.apply(result, chunks.map(function (c) {
return {
type: typeof c === 'string' ? PART_TYPE.literal : PART_TYPE.object,
value: c,
};
}));
}
if (isSelectElement(el)) {
// GH #4490: Use hasOwnProperty to avoid prototype chain issues with keys like "constructor"
var key = value;
var opt = (Object.prototype.hasOwnProperty.call(el.options, key)
? el.options[key]
: undefined) || el.options.other;
if (!opt) {
throw new InvalidValueError(el.value, value, Object.keys(el.options), originalMessage);
}
result.push.apply(result, formatToParts(opt.value, locales, formatters, formats, values));
continue;
}
if (isPluralElement(el)) {
// GH #4490: Use hasOwnProperty to avoid prototype chain issues
var exactKey = "=".concat(value);
var opt = Object.prototype.hasOwnProperty.call(el.options, exactKey)
? el.options[exactKey]
: undefined;
if (!opt) {
if (!Intl.PluralRules) {
throw new FormatError("Intl.PluralRules is not available in this environment.\nTry polyfilling it using \"@formatjs/intl-pluralrules\"\n", ErrorCode.MISSING_INTL_API, originalMessage);
}
// Convert bigint to number for PluralRules (which only accepts number)
var numericValue_1 = typeof value === 'bigint' ? Number(value) : value;
var rule = formatters
.getPluralRules(locales, { type: el.pluralType })
.select(numericValue_1 - (el.offset || 0));
opt =
(Object.prototype.hasOwnProperty.call(el.options, rule)
? el.options[rule]
: undefined) || el.options.other;
}
if (!opt) {
throw new InvalidValueError(el.value, value, Object.keys(el.options), originalMessage);
}
// Convert bigint to number for currentPluralValue
var numericValue = typeof value === 'bigint' ? Number(value) : value;
result.push.apply(result, formatToParts(opt.value, locales, formatters, formats, values, numericValue - (el.offset || 0)));
continue;
}
}
return mergeLiteral(result);
export function formatToParts(els, locales, formatters, formats, values, currentPluralValue, originalMessage) {
// Hot path for straight simple msg translations
if (els.length === 1 && isLiteralElement(els[0])) {
return [{
type: PART_TYPE.literal,
value: els[0].value
}];
}
const result = [];
for (const el of els) {
// Exit early for string parts.
if (isLiteralElement(el)) {
result.push({
type: PART_TYPE.literal,
value: el.value
});
continue;
}
// TODO: should this part be literal type?
// Replace `#` in plural rules with the actual numeric value.
if (isPoundElement(el)) {
if (typeof currentPluralValue === "number") {
result.push({
type: PART_TYPE.literal,
value: formatters.getNumberFormat(locales).format(currentPluralValue)
});
}
continue;
}
const { value: varName } = el;
// Enforce that all required values are provided by the caller.
if (!(values && varName in values)) {
throw new MissingValueError(varName, originalMessage);
}
let value = values[varName];
if (isArgumentElement(el)) {
if (!value || typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
value = typeof value === "string" || typeof value === "number" || typeof value === "bigint" ? String(value) : "";
}
result.push({
type: typeof value === "string" ? PART_TYPE.literal : PART_TYPE.object,
value
});
continue;
}
// Recursively format plural and select parts' option — which can be a
// nested pattern structure. The choosing of the option to use is
// abstracted-by and delegated-to the part helper object.
if (isDateElement(el)) {
const style = typeof el.style === "string" ? formats.date[el.style] : isDateTimeSkeleton(el.style) ? el.style.parsedOptions : undefined;
result.push({
type: PART_TYPE.literal,
value: formatters.getDateTimeFormat(locales, style).format(value)
});
continue;
}
if (isTimeElement(el)) {
const style = typeof el.style === "string" ? formats.time[el.style] : isDateTimeSkeleton(el.style) ? el.style.parsedOptions : formats.time.medium;
result.push({
type: PART_TYPE.literal,
value: formatters.getDateTimeFormat(locales, style).format(value)
});
continue;
}
if (isNumberElement(el)) {
const style = typeof el.style === "string" ? formats.number[el.style] : isNumberSkeleton(el.style) ? el.style.parsedOptions : undefined;
if (style && style.scale) {
const scale = style.scale || 1;
// Handle bigint scale multiplication
// BigInt can only be multiplied by BigInt
if (typeof value === "bigint") {
// Check if scale is a safe integer that can be converted to BigInt
if (!Number.isInteger(scale)) {
throw new TypeError(`Cannot apply fractional scale ${scale} to bigint value. Scale must be an integer when formatting bigint.`);
}
value = value * BigInt(scale);
} else {
value = value * scale;
}
}
result.push({
type: PART_TYPE.literal,
value: formatters.getNumberFormat(locales, style).format(value)
});
continue;
}
if (isTagElement(el)) {
const { children, value } = el;
const formatFn = values[value];
if (!isFormatXMLElementFn(formatFn)) {
throw new InvalidValueTypeError(value, "function", originalMessage);
}
const parts = formatToParts(children, locales, formatters, formats, values, currentPluralValue);
let chunks = formatFn(parts.map((p) => p.value));
if (!Array.isArray(chunks)) {
chunks = [chunks];
}
result.push(...chunks.map((c) => {
return {
type: typeof c === "string" ? PART_TYPE.literal : PART_TYPE.object,
value: c
};
}));
}
if (isSelectElement(el)) {
// GH #4490: Use hasOwnProperty to avoid prototype chain issues with keys like "constructor"
const key = value;
const opt = (Object.prototype.hasOwnProperty.call(el.options, key) ? el.options[key] : undefined) || el.options.other;
if (!opt) {
throw new InvalidValueError(el.value, value, Object.keys(el.options), originalMessage);
}
result.push(...formatToParts(opt.value, locales, formatters, formats, values));
continue;
}
if (isPluralElement(el)) {
// GH #4490: Use hasOwnProperty to avoid prototype chain issues
const exactKey = `=${value}`;
let opt = Object.prototype.hasOwnProperty.call(el.options, exactKey) ? el.options[exactKey] : undefined;
if (!opt) {
if (!Intl.PluralRules) {
throw new FormatError(`Intl.PluralRules is not available in this environment.
Try polyfilling it using "@formatjs/intl-pluralrules"
`, ErrorCode.MISSING_INTL_API, originalMessage);
}
// Convert bigint to number for PluralRules (which only accepts number)
const numericValue = typeof value === "bigint" ? Number(value) : value;
const rule = formatters.getPluralRules(locales, { type: el.pluralType }).select(numericValue - (el.offset || 0));
opt = (Object.prototype.hasOwnProperty.call(el.options, rule) ? el.options[rule] : undefined) || el.options.other;
}
if (!opt) {
throw new InvalidValueError(el.value, value, Object.keys(el.options), originalMessage);
}
// Convert bigint to number for currentPluralValue
const numericValue = typeof value === "bigint" ? Number(value) : value;
result.push(...formatToParts(opt.value, locales, formatters, formats, values, numericValue - (el.offset || 0)));
continue;
}
}
return mergeLiteral(result);
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display