intl-messageformat 7.8.4 → 8.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/README.md +19 -16
- package/dist/core.d.ts +3 -4
- package/dist/core.js +20 -4
- package/dist/error.d.ts +16 -0
- package/dist/error.js +44 -0
- package/dist/formatters.d.ts +7 -9
- package/dist/formatters.js +27 -169
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/umd/intl-messageformat.js +767 -416
- package/dist/umd/intl-messageformat.js.map +1 -1
- package/dist/umd/intl-messageformat.min.js +1 -1
- package/dist/umd/intl-messageformat.min.js.map +1 -1
- package/lib/core.d.ts +3 -4
- package/lib/core.js +21 -5
- package/lib/error.d.ts +16 -0
- package/lib/error.js +42 -0
- package/lib/formatters.d.ts +7 -9
- package/lib/formatters.js +28 -168
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/intl-messageformat.d.ts +30 -15
- package/package.json +3 -3
- package/src/core.ts +29 -24
- package/src/error.ts +39 -0
- package/src/formatters.ts +69 -245
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,71 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [8.2.1](https://github.com/formatjs/formatjs/compare/intl-messageformat@8.2.0...intl-messageformat@8.2.1) (2020-03-05)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **intl-messageformat:** export Error obj ([614debb](https://github.com/formatjs/formatjs/commit/614debb80f654966bc3ba832d6e5603be88da3d9))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [8.2.0](https://github.com/formatjs/formatjs/compare/intl-messageformat@8.1.0...intl-messageformat@8.2.0) (2020-03-05)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **intl-messageformat:** Add error type for better debugging ([6200573](https://github.com/formatjs/formatjs/commit/6200573c9f88b23f157bede7305fcc5da64b842b))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# [8.1.0](https://github.com/formatjs/formatjs/compare/intl-messageformat@8.0.0...intl-messageformat@8.1.0) (2020-03-05)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
* **intl-messageformat-parser:** Allow - in embedded HTML tag ([43aa6a7](https://github.com/formatjs/formatjs/commit/43aa6a727ab6fd5eb3fb4d8c4035039a2c27b6c5)), closes [#545](https://github.com/formatjs/formatjs/issues/545)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# [8.0.0](https://github.com/formatjs/formatjs/compare/intl-messageformat@7.8.3...intl-messageformat@8.0.0) (2020-03-04)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
* **intl-messageformat:** combine formatHTMLMessage into format ([d59fbf1](https://github.com/formatjs/formatjs/commit/d59fbf1a4a017a3a023254cb9947575eef9cf803))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### BREAKING CHANGES
|
|
48
|
+
|
|
49
|
+
* **intl-messageformat:** We've modified the way we parse and format embedded
|
|
50
|
+
XML/HTML as follow:
|
|
51
|
+
|
|
52
|
+
1. `formatHTMLMessage` has been combined with `format`
|
|
53
|
+
2. All tags specified must have corresponding values and will throw
|
|
54
|
+
error if it's missing, e.g: `new IntlMessageFormat("a
|
|
55
|
+
<b>strong</b>").format({ b: (...chunks) => <strong>chunks</strong> })`
|
|
56
|
+
3. Self-closing tags are treated as string literal by default. We don't
|
|
57
|
+
allow formatting self-closing tags because we already use ICU
|
|
58
|
+
`{placeholder}` syntax for that.
|
|
59
|
+
4. XML/HTML tags are escaped using apostrophe just like other ICU
|
|
60
|
+
constructs.
|
|
61
|
+
5. Remove dependency on DOMParser and restrictions on void element like
|
|
62
|
+
`<link>`. This effectively means you don't need to polyfill DOMParser in
|
|
63
|
+
Node anymore
|
|
64
|
+
|
|
65
|
+
fix(intl-messageformat-parser): fix escaping for XML tag
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
6
71
|
## [7.8.4](https://github.com/formatjs/formatjs/compare/intl-messageformat@7.8.3...intl-messageformat@7.8.4) (2020-01-27)
|
|
7
72
|
|
|
8
73
|
**Note:** Version bump only for package intl-messageformat
|
package/README.md
CHANGED
|
@@ -164,32 +164,35 @@ console.log(output); // => "My name is Eric."
|
|
|
164
164
|
|
|
165
165
|
_Note: A value **must** be supplied for every argument in the message pattern the instance was constructed with._
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
Return the underlying AST for the compiled message
|
|
170
|
-
|
|
171
|
-
### `formatHTMLMessage` method
|
|
172
|
-
|
|
173
|
-
Formats message containing HTML tags & can be used to embed rich text formatters such as React. For example:
|
|
167
|
+
#### Rich Text support
|
|
174
168
|
|
|
175
169
|
```tsx
|
|
176
170
|
const mf = new IntlMessageFormat('hello <b>world</b>', 'en');
|
|
177
|
-
mf.
|
|
171
|
+
mf.format({b: str => <span>{str}</span>});
|
|
178
172
|
// returns ['hello ', React element rendered as <span>world</span>]
|
|
179
173
|
```
|
|
180
174
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
This is not meant to be a full-fledged method to embed HTML, but rather to tag specific text chunk so translation can be more contextual. Therefore, the following restrictions apply:
|
|
175
|
+
We support embedded XML tag in the message, e.g `this is a <b>strong</b> tag`. This is not meant to be a full-fledged method to embed HTML, but rather to tag specific text chunk so translation can be more contextual. Therefore, the following restrictions apply:
|
|
184
176
|
|
|
185
177
|
1. Any attributes on the HTML tag are also ignored.
|
|
186
|
-
2. Self-closing tags are not supported, please use regular ICU placeholder like `{placeholder}`.
|
|
187
|
-
3.
|
|
188
|
-
|
|
178
|
+
2. Self-closing tags are treated as string literal and not supported, please use regular ICU placeholder like `{placeholder}`.
|
|
179
|
+
3. All tags specified must have corresponding values and will throw
|
|
180
|
+
error if it's missing, e.g: `new IntlMessageFormat("a<b>strong</b>").format({ b: (...chunks) => <strong>chunks</strong> })`.
|
|
181
|
+
4. XML/HTML tags are escaped using apostrophe just like other ICU constructs. In order to escape you can do things like:
|
|
189
182
|
|
|
190
|
-
|
|
183
|
+
```tsx
|
|
184
|
+
new IntlMessageFormat("I '<'3 cats").format(); // "I <3 cats"
|
|
185
|
+
new IntlMessageFormat("raw '<b>HTML</b>'").format(); // "raw <b>HTML</b>"
|
|
186
|
+
new IntlMessageFormat(
|
|
187
|
+
"raw '<b>HTML</b>' with '<a>'{placeholder}'</a>'"
|
|
188
|
+
).format({placeholder: 'some word'}); // "raw <b>HTML</b> with <a>some word</a>"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
5. Embedded valid HTML tag is a bit of a grey area right now since we're not supporting the full HTML/XHTML/XML spec.
|
|
192
|
+
|
|
193
|
+
### `getAst` Method
|
|
191
194
|
|
|
192
|
-
|
|
195
|
+
Return the underlying AST for the compiled message.
|
|
193
196
|
|
|
194
197
|
### User Defined Formats
|
|
195
198
|
|
package/dist/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parse, MessageFormatElement } from 'intl-messageformat-parser';
|
|
2
|
-
import { FormatterCache, Formatters, Formats, FormatXMLElementFn,
|
|
2
|
+
import { FormatterCache, Formatters, Formats, FormatXMLElementFn, MessageFormatPart } from './formatters';
|
|
3
3
|
export interface Options {
|
|
4
4
|
formatters?: Formatters;
|
|
5
5
|
}
|
|
@@ -12,9 +12,8 @@ export declare class IntlMessageFormat {
|
|
|
12
12
|
private readonly message;
|
|
13
13
|
private readonly formatterCache;
|
|
14
14
|
constructor(message: string | MessageFormatElement[], locales?: string | string[], overrideFormats?: Partial<Formats>, opts?: Options);
|
|
15
|
-
format: (values?: Record<string,
|
|
16
|
-
formatToParts: (values?: Record<string,
|
|
17
|
-
formatHTMLMessage: (values?: Record<string, string | number | boolean | object | Date | FormatXMLElementFn | null | undefined> | undefined) => (string | object)[];
|
|
15
|
+
format: <T = void>(values?: Record<string, string | number | boolean | Date | T | FormatXMLElementFn<T> | null | undefined> | undefined) => string | T | (string | T)[];
|
|
16
|
+
formatToParts: <T>(values?: Record<string, string | number | boolean | Date | T | FormatXMLElementFn<T> | null | undefined> | undefined) => MessageFormatPart<T>[];
|
|
18
17
|
resolvedOptions: () => {
|
|
19
18
|
locale: string;
|
|
20
19
|
};
|
package/dist/core.js
CHANGED
|
@@ -61,14 +61,30 @@ var IntlMessageFormat = /** @class */ (function () {
|
|
|
61
61
|
pluralRules: {},
|
|
62
62
|
};
|
|
63
63
|
this.format = function (values) {
|
|
64
|
-
|
|
64
|
+
var parts = _this.formatToParts(values);
|
|
65
|
+
// Hot path for straight simple msg translations
|
|
66
|
+
if (parts.length === 1) {
|
|
67
|
+
return parts[0].value;
|
|
68
|
+
}
|
|
69
|
+
var result = parts.reduce(function (all, part) {
|
|
70
|
+
if (!all.length ||
|
|
71
|
+
part.type !== 0 /* literal */ ||
|
|
72
|
+
typeof all[all.length - 1] !== 'string') {
|
|
73
|
+
all.push(part.value);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
all[all.length - 1] += part.value;
|
|
77
|
+
}
|
|
78
|
+
return all;
|
|
79
|
+
}, []);
|
|
80
|
+
if (result.length <= 1) {
|
|
81
|
+
return result[0] || '';
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
65
84
|
};
|
|
66
85
|
this.formatToParts = function (values) {
|
|
67
86
|
return formatters_1.formatToParts(_this.ast, _this.locales, _this.formatters, _this.formats, values, undefined, _this.message);
|
|
68
87
|
};
|
|
69
|
-
this.formatHTMLMessage = function (values) {
|
|
70
|
-
return formatters_1.formatHTMLMessage(_this.ast, _this.locales, _this.formatters, _this.formats, values, _this.message);
|
|
71
|
-
};
|
|
72
88
|
this.resolvedOptions = function () { return ({
|
|
73
89
|
locale: Intl.NumberFormat.supportedLocalesOf(_this.locales)[0],
|
|
74
90
|
}); };
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const enum ErrorCode {
|
|
2
|
+
MISSING_VALUE = 0,
|
|
3
|
+
INVALID_VALUE = 1,
|
|
4
|
+
MISSING_INTL_API = 2
|
|
5
|
+
}
|
|
6
|
+
export declare class FormatError extends Error {
|
|
7
|
+
readonly code: ErrorCode;
|
|
8
|
+
constructor(msg: string, code: ErrorCode);
|
|
9
|
+
toString(): string;
|
|
10
|
+
}
|
|
11
|
+
export declare class InvalidValueError extends FormatError {
|
|
12
|
+
constructor(variableId: string, value: any, options: string[]);
|
|
13
|
+
}
|
|
14
|
+
export declare class MissingValueError extends FormatError {
|
|
15
|
+
constructor(variableId: string, originalMessage?: string);
|
|
16
|
+
}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
extendStatics(d, b);
|
|
11
|
+
function __() { this.constructor = d; }
|
|
12
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
var FormatError = /** @class */ (function (_super) {
|
|
17
|
+
__extends(FormatError, _super);
|
|
18
|
+
function FormatError(msg, code) {
|
|
19
|
+
var _this = _super.call(this, msg) || this;
|
|
20
|
+
_this.code = code;
|
|
21
|
+
return _this;
|
|
22
|
+
}
|
|
23
|
+
FormatError.prototype.toString = function () {
|
|
24
|
+
return "[formatjs Error: " + this.code + "] " + this.message;
|
|
25
|
+
};
|
|
26
|
+
return FormatError;
|
|
27
|
+
}(Error));
|
|
28
|
+
exports.FormatError = FormatError;
|
|
29
|
+
var InvalidValueError = /** @class */ (function (_super) {
|
|
30
|
+
__extends(InvalidValueError, _super);
|
|
31
|
+
function InvalidValueError(variableId, value, options) {
|
|
32
|
+
return _super.call(this, "Invalid values for \"" + variableId + "\": \"" + value + "\". Options are \"" + Object.keys(options).join('", "') + "\"", 1 /* INVALID_VALUE */) || this;
|
|
33
|
+
}
|
|
34
|
+
return InvalidValueError;
|
|
35
|
+
}(FormatError));
|
|
36
|
+
exports.InvalidValueError = InvalidValueError;
|
|
37
|
+
var MissingValueError = /** @class */ (function (_super) {
|
|
38
|
+
__extends(MissingValueError, _super);
|
|
39
|
+
function MissingValueError(variableId, originalMessage) {
|
|
40
|
+
return _super.call(this, "The intl string context variable \"" + variableId + "\" was not provided to the string \"" + originalMessage + "\"", 0 /* MISSING_VALUE */) || this;
|
|
41
|
+
}
|
|
42
|
+
return MissingValueError;
|
|
43
|
+
}(FormatError));
|
|
44
|
+
exports.MissingValueError = MissingValueError;
|
package/dist/formatters.d.ts
CHANGED
|
@@ -16,19 +16,17 @@ export interface Formatters {
|
|
|
16
16
|
}
|
|
17
17
|
export declare const enum PART_TYPE {
|
|
18
18
|
literal = 0,
|
|
19
|
-
|
|
19
|
+
object = 1
|
|
20
20
|
}
|
|
21
21
|
export interface LiteralPart {
|
|
22
22
|
type: PART_TYPE.literal;
|
|
23
23
|
value: string;
|
|
24
24
|
}
|
|
25
|
-
export interface
|
|
26
|
-
type: PART_TYPE.
|
|
27
|
-
value:
|
|
25
|
+
export interface ObjectPart<T = any> {
|
|
26
|
+
type: PART_TYPE.object;
|
|
27
|
+
value: T;
|
|
28
28
|
}
|
|
29
|
-
export declare type MessageFormatPart = LiteralPart |
|
|
29
|
+
export declare type MessageFormatPart<T> = LiteralPart | ObjectPart<T>;
|
|
30
30
|
export declare type PrimitiveType = string | number | boolean | null | undefined | Date;
|
|
31
|
-
export declare function formatToParts(els: MessageFormatElement[], locales: string | string[], formatters: Formatters, formats: Formats, values?: Record<string,
|
|
32
|
-
export declare
|
|
33
|
-
export declare type FormatXMLElementFn = (...args: any[]) => string | object;
|
|
34
|
-
export declare function formatHTMLMessage(els: MessageFormatElement[], locales: string | string[], formatters: Formatters, formats: Formats, values?: Record<string, PrimitiveType | object | FormatXMLElementFn>, originalMessage?: string): Array<string | object>;
|
|
31
|
+
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>[];
|
|
32
|
+
export declare type FormatXMLElementFn<T> = (...args: Array<string | T>) => string | Array<string | T>;
|
package/dist/formatters.js
CHANGED
|
@@ -1,35 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
extendStatics(d, b);
|
|
11
|
-
function __() { this.constructor = d; }
|
|
12
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
13
|
-
};
|
|
14
|
-
})();
|
|
15
|
-
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
|
16
|
-
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
17
|
-
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
18
|
-
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
19
|
-
r[k] = a[j];
|
|
20
|
-
return r;
|
|
21
|
-
};
|
|
22
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
3
|
var intl_messageformat_parser_1 = require("intl-messageformat-parser");
|
|
24
|
-
var
|
|
25
|
-
__extends(FormatError, _super);
|
|
26
|
-
function FormatError(msg, variableId) {
|
|
27
|
-
var _this = _super.call(this, msg) || this;
|
|
28
|
-
_this.variableId = variableId;
|
|
29
|
-
return _this;
|
|
30
|
-
}
|
|
31
|
-
return FormatError;
|
|
32
|
-
}(Error));
|
|
4
|
+
var error_1 = require("./error");
|
|
33
5
|
function mergeLiteral(parts) {
|
|
34
6
|
if (parts.length < 2) {
|
|
35
7
|
return parts;
|
|
@@ -47,6 +19,9 @@ function mergeLiteral(parts) {
|
|
|
47
19
|
return all;
|
|
48
20
|
}, []);
|
|
49
21
|
}
|
|
22
|
+
function isFormatXMLElementFn(el) {
|
|
23
|
+
return typeof el === 'function';
|
|
24
|
+
}
|
|
50
25
|
// TODO(skeleton): add skeleton support
|
|
51
26
|
function formatToParts(els, locales, formatters, formats, values, currentPluralValue,
|
|
52
27
|
// For debugging
|
|
@@ -85,7 +60,7 @@ originalMessage) {
|
|
|
85
60
|
var varName = el.value;
|
|
86
61
|
// Enforce that all required values are provided by the caller.
|
|
87
62
|
if (!(values && varName in values)) {
|
|
88
|
-
throw new
|
|
63
|
+
throw new error_1.MissingValueError(varName, originalMessage);
|
|
89
64
|
}
|
|
90
65
|
var value = values[varName];
|
|
91
66
|
if (intl_messageformat_parser_1.isArgumentElement(el)) {
|
|
@@ -96,7 +71,7 @@ originalMessage) {
|
|
|
96
71
|
: '';
|
|
97
72
|
}
|
|
98
73
|
result.push({
|
|
99
|
-
type: 1 /*
|
|
74
|
+
type: typeof value === 'string' ? 0 /* literal */ : 1 /* object */,
|
|
100
75
|
value: value,
|
|
101
76
|
});
|
|
102
77
|
continue;
|
|
@@ -142,10 +117,28 @@ originalMessage) {
|
|
|
142
117
|
});
|
|
143
118
|
continue;
|
|
144
119
|
}
|
|
120
|
+
if (intl_messageformat_parser_1.isTagElement(el)) {
|
|
121
|
+
var children = el.children, value_1 = el.value;
|
|
122
|
+
var formatFn = values[value_1];
|
|
123
|
+
if (!isFormatXMLElementFn(formatFn)) {
|
|
124
|
+
throw new TypeError("Value for \"" + value_1 + "\" must be a function");
|
|
125
|
+
}
|
|
126
|
+
var parts = formatToParts(children, locales, formatters, formats, values);
|
|
127
|
+
var chunks = formatFn.apply(void 0, parts.map(function (p) { return p.value; }));
|
|
128
|
+
if (!Array.isArray(chunks)) {
|
|
129
|
+
chunks = [chunks];
|
|
130
|
+
}
|
|
131
|
+
result.push.apply(result, chunks.map(function (c) {
|
|
132
|
+
return {
|
|
133
|
+
type: typeof c === 'string' ? 0 /* literal */ : 1 /* object */,
|
|
134
|
+
value: c,
|
|
135
|
+
};
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
145
138
|
if (intl_messageformat_parser_1.isSelectElement(el)) {
|
|
146
139
|
var opt = el.options[value] || el.options.other;
|
|
147
140
|
if (!opt) {
|
|
148
|
-
throw new
|
|
141
|
+
throw new error_1.InvalidValueError(el.value, value, Object.keys(el.options));
|
|
149
142
|
}
|
|
150
143
|
result.push.apply(result, formatToParts(opt.value, locales, formatters, formats, values));
|
|
151
144
|
continue;
|
|
@@ -154,7 +147,7 @@ originalMessage) {
|
|
|
154
147
|
var opt = el.options["=" + value];
|
|
155
148
|
if (!opt) {
|
|
156
149
|
if (!Intl.PluralRules) {
|
|
157
|
-
throw new FormatError("Intl.PluralRules is not available in this environment.\nTry polyfilling it using \"@formatjs/intl-pluralrules\"\n");
|
|
150
|
+
throw new error_1.FormatError("Intl.PluralRules is not available in this environment.\nTry polyfilling it using \"@formatjs/intl-pluralrules\"\n", 2 /* MISSING_INTL_API */);
|
|
158
151
|
}
|
|
159
152
|
var rule = formatters
|
|
160
153
|
.getPluralRules(locales, { type: el.pluralType })
|
|
@@ -162,7 +155,7 @@ originalMessage) {
|
|
|
162
155
|
opt = el.options[rule] || el.options.other;
|
|
163
156
|
}
|
|
164
157
|
if (!opt) {
|
|
165
|
-
throw new
|
|
158
|
+
throw new error_1.InvalidValueError(el.value, value, Object.keys(el.options));
|
|
166
159
|
}
|
|
167
160
|
result.push.apply(result, formatToParts(opt.value, locales, formatters, formats, values, value - (el.offset || 0)));
|
|
168
161
|
continue;
|
|
@@ -171,138 +164,3 @@ originalMessage) {
|
|
|
171
164
|
return mergeLiteral(result);
|
|
172
165
|
}
|
|
173
166
|
exports.formatToParts = formatToParts;
|
|
174
|
-
function formatToString(els, locales, formatters, formats, values,
|
|
175
|
-
// For debugging
|
|
176
|
-
originalMessage) {
|
|
177
|
-
var parts = formatToParts(els, locales, formatters, formats, values, undefined, originalMessage);
|
|
178
|
-
// Hot path for straight simple msg translations
|
|
179
|
-
if (parts.length === 1) {
|
|
180
|
-
return parts[0].value;
|
|
181
|
-
}
|
|
182
|
-
return parts.reduce(function (all, part) { return (all += part.value); }, '');
|
|
183
|
-
}
|
|
184
|
-
exports.formatToString = formatToString;
|
|
185
|
-
// Singleton
|
|
186
|
-
var domParser;
|
|
187
|
-
var TOKEN_DELIMITER = '@@';
|
|
188
|
-
var TOKEN_REGEX = /@@(\d+_\d+)@@/g;
|
|
189
|
-
var counter = 0;
|
|
190
|
-
function generateId() {
|
|
191
|
-
return Date.now() + "_" + ++counter;
|
|
192
|
-
}
|
|
193
|
-
function restoreRichPlaceholderMessage(text, objectParts) {
|
|
194
|
-
return text
|
|
195
|
-
.split(TOKEN_REGEX)
|
|
196
|
-
.filter(Boolean)
|
|
197
|
-
.map(function (c) { return (objectParts[c] != null ? objectParts[c] : c); })
|
|
198
|
-
.reduce(function (all, c) {
|
|
199
|
-
if (!all.length) {
|
|
200
|
-
all.push(c);
|
|
201
|
-
}
|
|
202
|
-
else if (typeof c === 'string' &&
|
|
203
|
-
typeof all[all.length - 1] === 'string') {
|
|
204
|
-
all[all.length - 1] += c;
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
all.push(c);
|
|
208
|
-
}
|
|
209
|
-
return all;
|
|
210
|
-
}, []);
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Not exhaustive, just for sanity check
|
|
214
|
-
*/
|
|
215
|
-
var SIMPLE_XML_REGEX = /(<([0-9a-zA-Z-_]*?)>(.*?)<\/([0-9a-zA-Z-_]*?)>)|(<[0-9a-zA-Z-_]*?\/>)/;
|
|
216
|
-
var TEMPLATE_ID = Date.now() + '@@';
|
|
217
|
-
var VOID_ELEMENTS = [
|
|
218
|
-
'area',
|
|
219
|
-
'base',
|
|
220
|
-
'br',
|
|
221
|
-
'col',
|
|
222
|
-
'embed',
|
|
223
|
-
'hr',
|
|
224
|
-
'img',
|
|
225
|
-
'input',
|
|
226
|
-
'link',
|
|
227
|
-
'meta',
|
|
228
|
-
'param',
|
|
229
|
-
'source',
|
|
230
|
-
'track',
|
|
231
|
-
'wbr',
|
|
232
|
-
];
|
|
233
|
-
function formatHTMLElement(el, objectParts, values) {
|
|
234
|
-
var tagName = el.tagName;
|
|
235
|
-
var outerHTML = el.outerHTML, textContent = el.textContent, childNodes = el.childNodes;
|
|
236
|
-
// Regular text
|
|
237
|
-
if (!tagName) {
|
|
238
|
-
return restoreRichPlaceholderMessage(textContent || '', objectParts);
|
|
239
|
-
}
|
|
240
|
-
tagName = tagName.toLowerCase();
|
|
241
|
-
var isVoidElement = ~VOID_ELEMENTS.indexOf(tagName);
|
|
242
|
-
var formatFnOrValue = values[tagName];
|
|
243
|
-
if (formatFnOrValue && isVoidElement) {
|
|
244
|
-
throw new FormatError(tagName + " is a self-closing tag and can not be used, please use another tag name.");
|
|
245
|
-
}
|
|
246
|
-
if (!childNodes.length) {
|
|
247
|
-
return [outerHTML];
|
|
248
|
-
}
|
|
249
|
-
var chunks = Array.prototype.slice.call(childNodes).reduce(function (all, child) {
|
|
250
|
-
return all.concat(formatHTMLElement(child, objectParts, values));
|
|
251
|
-
}, []);
|
|
252
|
-
// Legacy HTML
|
|
253
|
-
if (!formatFnOrValue) {
|
|
254
|
-
return __spreadArrays(["<" + tagName + ">"], chunks, ["</" + tagName + ">"]);
|
|
255
|
-
}
|
|
256
|
-
// HTML Tag replacement
|
|
257
|
-
if (typeof formatFnOrValue === 'function') {
|
|
258
|
-
return [formatFnOrValue.apply(void 0, chunks)];
|
|
259
|
-
}
|
|
260
|
-
return [formatFnOrValue];
|
|
261
|
-
}
|
|
262
|
-
function formatHTMLMessage(els, locales, formatters, formats, values,
|
|
263
|
-
// For debugging
|
|
264
|
-
originalMessage) {
|
|
265
|
-
var parts = formatToParts(els, locales, formatters, formats, values, undefined, originalMessage);
|
|
266
|
-
var objectParts = {};
|
|
267
|
-
var formattedMessage = parts.reduce(function (all, part) {
|
|
268
|
-
if (part.type === 0 /* literal */) {
|
|
269
|
-
return (all += part.value);
|
|
270
|
-
}
|
|
271
|
-
var id = generateId();
|
|
272
|
-
objectParts[id] = part.value;
|
|
273
|
-
return (all += "" + TOKEN_DELIMITER + id + TOKEN_DELIMITER);
|
|
274
|
-
}, '');
|
|
275
|
-
// Not designed to filter out aggressively
|
|
276
|
-
if (!SIMPLE_XML_REGEX.test(formattedMessage)) {
|
|
277
|
-
return restoreRichPlaceholderMessage(formattedMessage, objectParts);
|
|
278
|
-
}
|
|
279
|
-
if (!values) {
|
|
280
|
-
throw new FormatError('Message has placeholders but no values was given');
|
|
281
|
-
}
|
|
282
|
-
if (typeof DOMParser === 'undefined') {
|
|
283
|
-
throw new FormatError('Cannot format XML message without DOMParser');
|
|
284
|
-
}
|
|
285
|
-
if (!domParser) {
|
|
286
|
-
domParser = new DOMParser();
|
|
287
|
-
}
|
|
288
|
-
var content = domParser
|
|
289
|
-
.parseFromString("<formatted-message id=\"" + TEMPLATE_ID + "\">" + formattedMessage + "</formatted-message>", 'text/html')
|
|
290
|
-
.getElementById(TEMPLATE_ID);
|
|
291
|
-
if (!content) {
|
|
292
|
-
throw new FormatError("Malformed HTML message " + formattedMessage);
|
|
293
|
-
}
|
|
294
|
-
var tagsToFormat = Object.keys(values).filter(function (varName) { return !!content.getElementsByTagName(varName).length; });
|
|
295
|
-
// No tags to format
|
|
296
|
-
if (!tagsToFormat.length) {
|
|
297
|
-
return restoreRichPlaceholderMessage(formattedMessage, objectParts);
|
|
298
|
-
}
|
|
299
|
-
var caseSensitiveTags = tagsToFormat.filter(function (tagName) { return tagName !== tagName.toLowerCase(); });
|
|
300
|
-
if (caseSensitiveTags.length) {
|
|
301
|
-
throw new FormatError("HTML tag must be lowercased but the following tags are not: " + caseSensitiveTags.join(', '));
|
|
302
|
-
}
|
|
303
|
-
// We're doing this since top node is `<formatted-message/>` which does not have a formatter
|
|
304
|
-
return Array.prototype.slice
|
|
305
|
-
.call(content.childNodes)
|
|
306
|
-
.reduce(function (all, child) { return all.concat(formatHTMLElement(child, objectParts, values)); }, []);
|
|
307
|
-
}
|
|
308
|
-
exports.formatHTMLMessage = formatHTMLMessage;
|
package/dist/index.d.ts
CHANGED