Skip to content

Commit 57b8a7e

Browse files
authored
chore!: Update dependencies & API docs (#607)
* chore!: Drop Node.js v12 support, add v18 & latest to CI tests - Require Node.js 14.18 for build & tests, to match Rollup v3 requirements * chore: Refresh lockfile * chore: Update dev dependencies to mocha@10 & sinon@15 * chore(react): Update dev dependencies to jest@29 * chore: Update to gh-pages@5 * chore: Update to rollup@3 * chore: Update to [email protected] * docs: Use /** comments */ where appropriate - Also drop a few unnecessary eslint directive comments * docs: Update code comments to reduce typedoc warnings * chore(react): Update dev dependencies to react@18 * chore(dom): Update dev dependencies to jsdom@21
1 parent a6ccb2d commit 57b8a7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+4185
-4565
lines changed

.github/workflows/legacy.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
node: [12.x, 14.x]
13+
node: ['14.18']
1414
steps:
15-
- uses: actions/checkout@v2
15+
- uses: actions/checkout@v3
1616
- name: Use Node.js ${{matrix.node}}
17-
uses: actions/setup-node@v1
17+
uses: actions/setup-node@v3
1818
with:
1919
node-version: ${{matrix.node}}
2020
- run: npm install --global npm@7

.github/workflows/test.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
node: [16.x]
13+
node: [16, 18, latest]
1414
steps:
15-
- uses: actions/checkout@v2
15+
- uses: actions/checkout@v3
1616
- name: Use Node.js ${{matrix.node}}
17-
uses: actions/setup-node@v1
17+
uses: actions/setup-node@v3
1818
with:
1919
node-version: ${{matrix.node}}
2020
- run: npm ci

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Hacking on `fluent.js` is easy! To quickly get started clone the repo:
6363
$ git clone https://github.com/projectfluent/fluent.js.git
6464
$ cd fluent.js
6565

66-
You'll need at least **Node.js 12** and **npm v7**.
66+
You'll need at least **Node.js 14.18** and **npm 7**.
6767
Older versions are not supported.
6868

6969
Install the dependencies used by all packages, which are managed as

fluent-bundle/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"test": "mocha 'test/*_test.js'"
4646
},
4747
"engines": {
48-
"node": ">=12.0.0",
48+
"node": ">=14.0.0",
4949
"npm": ">=7.0.0"
5050
},
5151
"devDependencies": {

fluent-bundle/src/ast.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Raw messages are `{value, attributes}` shapes containing translation units
3+
* called `Patterns`. `Patterns` are implementation-specific; they should be
4+
* treated as black boxes and formatted with `FluentBundle.formatPattern`.
5+
*/
16
export type Message = {
27
id: string;
38
value: Pattern | null;

fluent-bundle/src/bundle.ts

+64-53
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import { NUMBER, DATETIME } from "./builtins.js";
77
import { getMemoizerForLocale, IntlCache } from "./memoizer.js";
88

99
export type TextTransform = (text: string) => string;
10-
11-
type NativeValue = string | number | Date;
12-
export type FluentVariable = FluentValue | NativeValue;
10+
export type FluentVariable = FluentValue | string | number | Date;
1311

1412
/**
1513
* Message bundles are single-language stores of translation resources. They are
@@ -18,41 +16,38 @@ export type FluentVariable = FluentValue | NativeValue;
1816
export class FluentBundle {
1917
public locales: Array<string>;
2018

19+
/** @ignore */
2120
public _terms: Map<string, Term> = new Map();
21+
/** @ignore */
2222
public _messages: Map<string, Message> = new Map();
23+
/** @ignore */
2324
public _functions: Record<string, FluentFunction>;
25+
/** @ignore */
2426
public _useIsolating: boolean;
27+
/** @ignore */
2528
public _transform: TextTransform;
29+
/** @ignore */
2630
public _intls: IntlCache;
2731

2832
/**
2933
* Create an instance of `FluentBundle`.
3034
*
31-
* The `locales` argument is used to instantiate `Intl` formatters used by
32-
* translations. The `options` object can be used to configure the bundle.
33-
*
34-
* Examples:
35-
*
36-
* let bundle = new FluentBundle(["en-US", "en"]);
37-
*
38-
* let bundle = new FluentBundle(locales, {useIsolating: false});
35+
* @example
36+
* ```js
37+
* let bundle = new FluentBundle(["en-US", "en"]);
3938
*
40-
* let bundle = new FluentBundle(locales, {
41-
* useIsolating: true,
42-
* functions: {
43-
* NODE_ENV: () => process.env.NODE_ENV
44-
* }
45-
* });
39+
* let bundle = new FluentBundle(locales, {useIsolating: false});
4640
*
47-
* Available options:
41+
* let bundle = new FluentBundle(locales, {
42+
* useIsolating: true,
43+
* functions: {
44+
* NODE_ENV: () => process.env.NODE_ENV
45+
* }
46+
* });
47+
* ```
4848
*
49-
* - `functions` - an object of additional functions available to
50-
* translations as builtins.
51-
*
52-
* - `useIsolating` - boolean specifying whether to use Unicode isolation
53-
* marks (FSI, PDI) for bidi interpolations. Default: `true`.
54-
*
55-
* - `transform` - a function used to transform string parts of patterns.
49+
* @param locales - Used to instantiate `Intl` formatters used by translations.
50+
* @param options - Optional configuration for the bundle.
5651
*/
5752
constructor(
5853
locales: string | Array<string>,
@@ -61,8 +56,15 @@ export class FluentBundle {
6156
useIsolating = true,
6257
transform = (v: string): string => v,
6358
}: {
59+
/** Additional functions available to translations as builtins. */
6460
functions?: Record<string, FluentFunction>;
61+
/**
62+
* Whether to use Unicode isolation marks (FSI, PDI) for bidi interpolations.
63+
*
64+
* Default: `true`.
65+
*/
6566
useIsolating?: boolean;
67+
/** A function used to transform string parts of patterns. */
6668
transform?: TextTransform;
6769
} = {}
6870
) {
@@ -102,24 +104,30 @@ export class FluentBundle {
102104
/**
103105
* Add a translation resource to the bundle.
104106
*
105-
* The translation resource must be an instance of `FluentResource`.
106-
*
107-
* let res = new FluentResource("foo = Foo");
108-
* bundle.addResource(res);
109-
* bundle.getMessage("foo");
110-
* // → {value: .., attributes: {..}}
111-
*
112-
* Available options:
107+
* @example
108+
* ```js
109+
* let res = new FluentResource("foo = Foo");
110+
* bundle.addResource(res);
111+
* bundle.getMessage("foo");
112+
* // → {value: .., attributes: {..}}
113+
* ```
113114
*
114-
* - `allowOverrides` - boolean specifying whether it's allowed to override
115-
* an existing message or term with a new value. Default: `false`.
116-
*
117-
* @param res - FluentResource object.
118-
* @param options
115+
* @param res
116+
* @param options
119117
*/
120118
addResource(
121119
res: FluentResource,
122-
{ allowOverrides = false }: { allowOverrides?: boolean } = {}
120+
{
121+
allowOverrides = false,
122+
}: {
123+
/**
124+
* Boolean specifying whether it's allowed to override
125+
* an existing message or term with a new value.
126+
*
127+
* Default: `false`.
128+
*/
129+
allowOverrides?: boolean;
130+
} = {}
123131
): Array<Error> {
124132
const errors = [];
125133

@@ -160,21 +168,24 @@ export class FluentBundle {
160168
* reasons, the encountered errors are not returned but instead are appended
161169
* to the `errors` array passed as the third argument.
162170
*
163-
* let errors = [];
164-
* bundle.addResource(
165-
* new FluentResource("hello = Hello, {$name}!"));
166-
*
167-
* let hello = bundle.getMessage("hello");
168-
* if (hello.value) {
169-
* bundle.formatPattern(hello.value, {name: "Jane"}, errors);
170-
* // Returns "Hello, Jane!" and `errors` is empty.
171-
*
172-
* bundle.formatPattern(hello.value, undefined, errors);
173-
* // Returns "Hello, {$name}!" and `errors` is now:
174-
* // [<ReferenceError: Unknown variable: name>]
175-
* }
176-
*
177171
* If `errors` is omitted, the first encountered error will be thrown.
172+
*
173+
* @example
174+
* ```js
175+
* let errors = [];
176+
* bundle.addResource(
177+
* new FluentResource("hello = Hello, {$name}!"));
178+
*
179+
* let hello = bundle.getMessage("hello");
180+
* if (hello.value) {
181+
* bundle.formatPattern(hello.value, {name: "Jane"}, errors);
182+
* // Returns "Hello, Jane!" and `errors` is empty.
183+
*
184+
* bundle.formatPattern(hello.value, undefined, errors);
185+
* // Returns "Hello, {$name}!" and `errors` is now:
186+
* // [<ReferenceError: Unknown variable: name>]
187+
* }
188+
* ```
178189
*/
179190
formatPattern(
180191
pattern: Pattern,

fluent-bundle/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
*
88
*/
99

10+
export type { Message } from "./ast.js";
1011
export { FluentBundle, FluentVariable, TextTransform } from "./bundle.js";
1112
export { FluentResource } from "./resource.js";
13+
export type { Scope } from "./scope.js";
1214
export {
1315
FluentValue,
1416
FluentType,

fluent-bundle/src/resolver.ts

+20-16
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,18 @@ import {
4646
} from "./ast.js";
4747
import { FluentVariable } from "./bundle.js";
4848

49-
// The maximum number of placeables which can be expanded in a single call to
50-
// `formatPattern`. The limit protects against the Billion Laughs and Quadratic
51-
// Blowup attacks. See https://msdn.microsoft.com/en-us/magazine/ee335713.aspx.
49+
/**
50+
* The maximum number of placeables which can be expanded in a single call to
51+
* `formatPattern`. The limit protects against the Billion Laughs and Quadratic
52+
* Blowup attacks. See https://msdn.microsoft.com/en-us/magazine/ee335713.aspx.
53+
*/
5254
const MAX_PLACEABLES = 100;
5355

54-
// Unicode bidi isolation characters.
56+
/** Unicode bidi isolation characters. */
5557
const FSI = "\u2068";
5658
const PDI = "\u2069";
5759

58-
// Helper: match a variant key to the given selector.
60+
/** Helper: match a variant key to the given selector. */
5961
function match(scope: Scope, selector: FluentValue, key: FluentValue): boolean {
6062
if (key === selector) {
6163
// Both are strings.
@@ -86,7 +88,7 @@ function match(scope: Scope, selector: FluentValue, key: FluentValue): boolean {
8688
return false;
8789
}
8890

89-
// Helper: resolve the default variant from a list of variants.
91+
/** Helper: resolve the default variant from a list of variants. */
9092
function getDefault(
9193
scope: Scope,
9294
variants: Array<Variant>,
@@ -105,7 +107,7 @@ interface Arguments {
105107
named: Record<string, FluentValue>;
106108
}
107109

108-
// Helper: resolve arguments to a call expression.
110+
/** Helper: resolve arguments to a call expression. */
109111
function getArguments(
110112
scope: Scope,
111113
args: Array<Expression | NamedArgument>
@@ -124,7 +126,7 @@ function getArguments(
124126
return { positional, named };
125127
}
126128

127-
// Resolve an expression to a Fluent type.
129+
/** Resolve an expression to a Fluent type. */
128130
function resolveExpression(scope: Scope, expr: Expression): FluentValue {
129131
switch (expr.type) {
130132
case "str":
@@ -148,7 +150,7 @@ function resolveExpression(scope: Scope, expr: Expression): FluentValue {
148150
}
149151
}
150152

151-
// Resolve a reference to a variable.
153+
/** Resolve a reference to a variable. */
152154
function resolveVariableReference(
153155
scope: Scope,
154156
{ name }: VariableReference
@@ -197,7 +199,7 @@ function resolveVariableReference(
197199
}
198200
}
199201

200-
// Resolve a reference to another message.
202+
/** Resolve a reference to another message. */
201203
function resolveMessageReference(
202204
scope: Scope,
203205
{ name, attr }: MessageReference
@@ -225,7 +227,7 @@ function resolveMessageReference(
225227
return new FluentNone(name);
226228
}
227229

228-
// Resolve a call to a Term with key-value arguments.
230+
/** Resolve a call to a Term with key-value arguments. */
229231
function resolveTermReference(
230232
scope: Scope,
231233
{ name, attr, args }: TermReference
@@ -256,7 +258,7 @@ function resolveTermReference(
256258
return resolved;
257259
}
258260

259-
// Resolve a call to a Function with positional and key-value arguments.
261+
/** Resolve a call to a Function with positional and key-value arguments. */
260262
function resolveFunctionReference(
261263
scope: Scope,
262264
{ name, args }: FunctionReference
@@ -283,7 +285,7 @@ function resolveFunctionReference(
283285
}
284286
}
285287

286-
// Resolve a select expression to the member object.
288+
/** Resolve a select expression to the member object. */
287289
function resolveSelectExpression(
288290
scope: Scope,
289291
{ selector, variants, star }: SelectExpression
@@ -304,7 +306,7 @@ function resolveSelectExpression(
304306
return getDefault(scope, variants, star);
305307
}
306308

307-
// Resolve a pattern (a complex string with placeables).
309+
/** Resolve a pattern (a complex string with placeables). */
308310
export function resolveComplexPattern(
309311
scope: Scope,
310312
ptn: ComplexPattern
@@ -356,8 +358,10 @@ export function resolveComplexPattern(
356358
return result.join("");
357359
}
358360

359-
// Resolve a simple or a complex Pattern to a FluentString (which is really the
360-
// string primitive).
361+
/**
362+
* Resolve a simple or a complex Pattern to a FluentString
363+
* (which is really the string primitive).
364+
*/
361365
function resolvePattern(scope: Scope, value: Pattern): FluentValue {
362366
// Resolve a simple pattern.
363367
if (typeof value === "string") {

fluent-bundle/src/resource.ts

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const TOKEN_BLANK = /\s+/y;
6969
* Fluent Resource is a structure storing parsed localization entries.
7070
*/
7171
export class FluentResource {
72+
/** @ignore */
7273
public body: Array<Message | Term>;
7374

7475
constructor(source: string) {

fluent-bundle/src/scope.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@ export class Scope {
88
public errors: Array<Error> | null;
99
/** A dict of developer-provided variables. */
1010
public args: Record<string, FluentVariable> | null;
11-
/** The Set of patterns already encountered during this resolution.
12-
* Used to detect and prevent cyclic resolutions. */
11+
/**
12+
* The Set of patterns already encountered during this resolution.
13+
* Used to detect and prevent cyclic resolutions.
14+
* @ignore
15+
*/
1316
public dirty: WeakSet<ComplexPattern> = new WeakSet();
1417
/** A dict of parameters passed to a TermReference. */
1518
public params: Record<string, FluentVariable> | null = null;
16-
/** The running count of placeables resolved so far. Used to detect the
17-
* Billion Laughs and Quadratic Blowup attacks. */
19+
/**
20+
* The running count of placeables resolved so far.
21+
* Used to detect the Billion Laughs and Quadratic Blowup attacks.
22+
* @ignore
23+
*/
1824
public placeables: number = 0;
1925

2026
constructor(

fluent-bundle/src/types.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { Scope } from "./scope.js";
22

3-
/* global Intl */
4-
53
export type FluentValue = FluentType<unknown> | string;
64

75
export type FluentFunction = (

0 commit comments

Comments
 (0)