@u27n/js 0.1.1 → 0.2.0

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.
@@ -0,0 +1,16 @@
1
+ import { U27n } from "./core.js";
2
+ export declare class Plural {
3
+ #private;
4
+ constructor(options?: Intl.PluralRulesOptions);
5
+ select<T>(locale: string, count: number, values: T[]): T;
6
+ }
7
+ export declare function interpolate(value: string, params: Record<string, any>): string;
8
+ export interface FormatPluralParams {
9
+ count: number;
10
+ }
11
+ export type FormatFn = <V extends string | string[], P extends (V extends string[] ? FormatPluralParams : {})>(value: V, params: P, options?: FormatOptions) => string;
12
+ export interface FormatOptions {
13
+ plural?: Plural;
14
+ }
15
+ export declare function createFormatter(u27n: U27n): FormatFn;
16
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,qBAAa,MAAM;;gBAIN,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB;IAI7C,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC;CAexD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CA0B9E;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,QAAQ,GAAG,CACtB,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAC3B,CAAC,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,kBAAkB,GAAG,EAAE,CAAC,EACvD,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAYpD"}
package/dist/format.js ADDED
@@ -0,0 +1,65 @@
1
+ export class Plural {
2
+ #options;
3
+ #rules = {};
4
+ constructor(options) {
5
+ this.#options = options;
6
+ }
7
+ select(locale, count, values) {
8
+ let instance = this.#rules[locale];
9
+ if (instance === undefined) {
10
+ const rules = new Intl.PluralRules(locale, this.#options);
11
+ instance = this.#rules[locale] = {
12
+ r: rules,
13
+ f: rules.resolvedOptions().pluralCategories,
14
+ };
15
+ }
16
+ const form = instance.r.select(count);
17
+ const index = instance.f.indexOf(form);
18
+ return index < 0 || index >= values.length
19
+ ? values[values.length - 1]
20
+ : values[index];
21
+ }
22
+ }
23
+ export function interpolate(value, params) {
24
+ let output = "";
25
+ let index = 0;
26
+ while (index < value.length) {
27
+ const start = value.indexOf("{", index);
28
+ if (start < 0) {
29
+ output += value.slice(index);
30
+ break;
31
+ }
32
+ if (start > 0 && value[start - 1] === "\\") {
33
+ output += value.slice(index, start - 1) + "{";
34
+ index = start + 1;
35
+ }
36
+ else {
37
+ output += value.slice(index, start);
38
+ const end = value.indexOf("}", start + 1);
39
+ if (end < 0) {
40
+ throw new Error();
41
+ }
42
+ const key = value.slice(start + 1, end);
43
+ if (!Object.hasOwn(params, key)) {
44
+ throw new Error();
45
+ }
46
+ output += String(params[key]);
47
+ index = end + 1;
48
+ }
49
+ }
50
+ return output;
51
+ }
52
+ export function createFormatter(u27n) {
53
+ let defaultPlural;
54
+ return (value, params, options) => {
55
+ if (Array.isArray(value)) {
56
+ const plural = options?.plural ?? defaultPlural ?? (defaultPlural = new Plural());
57
+ value = plural.select(u27n.locale, params.count, value);
58
+ }
59
+ if (Object.keys(params).length > 0) {
60
+ return interpolate(value, params);
61
+ }
62
+ return value;
63
+ };
64
+ }
65
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./core.js";
2
+ export * from "./format.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./core.js";
2
+ export * from "./format.js";
2
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@u27n/js",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
package/src/format.ts ADDED
@@ -0,0 +1,81 @@
1
+ import { U27n } from "./core.js";
2
+
3
+ export class Plural {
4
+ #options: Intl.PluralRulesOptions | undefined;
5
+ #rules: Record<string, { r: Intl.PluralRules, f: Intl.LDMLPluralRule[] }> = {};
6
+
7
+ constructor(options?: Intl.PluralRulesOptions) {
8
+ this.#options = options;
9
+ }
10
+
11
+ select<T>(locale: string, count: number, values: T[]): T {
12
+ let instance = this.#rules[locale];
13
+ if (instance === undefined) {
14
+ const rules = new Intl.PluralRules(locale, this.#options);
15
+ instance = this.#rules[locale] = {
16
+ r: rules,
17
+ f: rules.resolvedOptions().pluralCategories,
18
+ };
19
+ }
20
+ const form = instance.r.select(count);
21
+ const index = instance.f.indexOf(form);
22
+ return index < 0 || index >= values.length
23
+ ? values[values.length - 1]
24
+ : values[index];
25
+ }
26
+ }
27
+
28
+ export function interpolate(value: string, params: Record<string, any>): string {
29
+ let output = "";
30
+ let index = 0;
31
+ while (index < value.length) {
32
+ const start = value.indexOf("{", index);
33
+ if (start < 0) {
34
+ output += value.slice(index);
35
+ break;
36
+ } if (start > 0 && value[start - 1] === "\\") {
37
+ output += value.slice(index, start - 1) + "{";
38
+ index = start + 1;
39
+ } else {
40
+ output += value.slice(index, start);
41
+ const end = value.indexOf("}", start + 1);
42
+ if (end < 0) {
43
+ throw new Error();
44
+ }
45
+ const key = value.slice(start + 1, end);
46
+ if (!Object.hasOwn(params, key)) {
47
+ throw new Error();
48
+ }
49
+ output += String(params[key]);
50
+ index = end + 1;
51
+ }
52
+ }
53
+ return output;
54
+ }
55
+
56
+ export interface FormatPluralParams {
57
+ count: number;
58
+ }
59
+
60
+ export type FormatFn = <
61
+ V extends string | string[],
62
+ P extends (V extends string[] ? FormatPluralParams : {})
63
+ >(value: V, params: P, options?: FormatOptions) => string;
64
+
65
+ export interface FormatOptions {
66
+ plural?: Plural;
67
+ }
68
+
69
+ export function createFormatter(u27n: U27n): FormatFn {
70
+ let defaultPlural: Plural | undefined;
71
+ return (value: string | string[], params: object, options?: FormatOptions): string => {
72
+ if (Array.isArray(value)) {
73
+ const plural = options?.plural ?? defaultPlural ?? (defaultPlural = new Plural());
74
+ value = plural.select(u27n.locale, (params as FormatPluralParams).count, value);
75
+ }
76
+ if (Object.keys(params).length > 0) {
77
+ return interpolate(value, params);
78
+ }
79
+ return value;
80
+ };
81
+ }
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./core.js";
2
+ export * from "./format.js";