@saykit/config 0.11.1 → 0.12.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.
@@ -1,47 +1,56 @@
1
- import { a as Message, n as Config, t as Bucket } from "../../shapes-CRlXtss0.cjs";
2
- //#region src/features/catalogue/merge.d.ts
3
- declare function mergeExtractedMessages(messages: Message[]): {
1
+ import { a as Message, n as Config, t as Bucket } from "../../shapes-Dq0aJdsn.cjs";
2
+ /**
3
+ * Where a locale's generated module goes: beside its catalogue, as `.js`.
4
+ *
5
+ * @throws If that is the catalogue itself, as for a formatter with a `.js` extension
6
+ */
7
+ export declare function modulePathFor(bucket: Bucket, locale: string): string;
8
+ /**
9
+ * Build the source of a locale's generated module from its assembled record.
10
+ *
11
+ * The module is plain data, so it can cross a server/client boundary as JSON.
12
+ *
13
+ * @param record The locale's messages, keyed by id, as ICU
14
+ */
15
+ export declare function generateCatalogueModule(record: Record<string, string>): string;
16
+ /**
17
+ * Compile one locale's catalogue, and its fallbacks, into a module on disk.
18
+ *
19
+ * The fallback chain is merged here, so the app still imports one module per locale.
20
+ */
21
+ export declare function emitCatalogueModule(config: Config, bucket: Bucket, locale: string): Promise<{
22
+ path: string;
23
+ count: number;
24
+ }>;
25
+ export declare function mergeExtractedMessages(messages: Message[]): {
4
26
  message: string;
5
- comments: string[];
6
- references: string[];
7
27
  translation?: string | undefined;
8
28
  id?: string | undefined;
9
29
  context?: string | undefined;
10
- }[];
11
- declare function pruneLocaleMessages(existingMessages: Message[], sourceMessages: Message[]): {
12
- message: string;
13
30
  comments: string[];
14
31
  references: string[];
32
+ }[];
33
+ export declare function pruneLocaleMessages(existingMessages: Message[], sourceMessages: Message[]): {
34
+ message: string;
15
35
  translation?: string | undefined;
16
36
  id?: string | undefined;
17
37
  context?: string | undefined;
38
+ comments: string[];
39
+ references: string[];
18
40
  }[];
19
- //#endregion
20
- //#region src/features/catalogue/path.d.ts
21
- declare function expandBucketOutputPath(bucket: Bucket, locale: string, extension?: `.${string}`): string;
22
- /**
23
- * The declaration file that types a catalogue, e.g. `en.json` -> `en.d.json.ts`.
24
- *
25
- * TypeScript resolves `./en.json` by stripping the extension and looking for
26
- * `en.d.json.ts`; the `en.json.d.ts` form is only consulted for extensions the
27
- * resolver does not recognise. Non-JS extensions additionally require
28
- * `allowArbitraryExtensions` in the consumer's tsconfig.
29
- */
30
- declare function declarationPathFor(cataloguePath: string): string;
31
- //#endregion
32
- //#region src/features/catalogue/record.d.ts
41
+ export declare function expandBucketOutputPath(bucket: Bucket, locale: string, extension?: `.${string}`): string;
33
42
  /**
34
43
  * Resolve the fallback chain for a locale, most specific first. The source
35
44
  * locale (the first configured locale) is always the final fallback, so an
36
45
  * untranslated key ultimately resolves to the source string.
37
46
  */
38
- declare function resolveFallbackChain(config: Config, locale: string): string[];
47
+ export declare function resolveFallbackChain(config: Config, locale: string): string[];
39
48
  /**
40
49
  * Resolve the catalogue files that contribute to a locale module, most specific
41
50
  * first. When the path does not map to a configured locale it is loaded on its
42
51
  * own.
43
52
  */
44
- declare function resolveCatalogueSources(config: Config, bucket: Bucket, path: string): {
53
+ export declare function resolveCatalogueSources(config: Config, bucket: Bucket, path: string): {
45
54
  locale: string | undefined;
46
55
  sources: string[];
47
56
  };
@@ -51,17 +60,13 @@ declare function resolveCatalogueSources(config: Config, bucket: Bucket, path: s
51
60
  * (most specific first): more specific locales override their fallbacks, and any
52
61
  * key still untranslated falls back to its source message.
53
62
  */
54
- declare function assembleCatalogueRecord(bucket: Bucket, contents: string[]): Record<string, string>;
55
- //#endregion
56
- //#region src/features/catalogue/storage.d.ts
57
- declare function readCatalogueMessages(bucket: Bucket, locale: string, path?: string): Promise<{
63
+ export declare function assembleCatalogueRecord(bucket: Bucket, contents: string[]): Record<string, string>;
64
+ export declare function readCatalogueMessages(bucket: Bucket, locale: string, path?: string): Promise<{
58
65
  message: string;
59
- comments: string[];
60
- references: string[];
61
66
  translation?: string | undefined;
62
67
  id?: string | undefined;
63
68
  context?: string | undefined;
69
+ comments: string[];
70
+ references: string[];
64
71
  }[]>;
65
- declare function writeCatalogueMessages(bucket: Bucket, locale: string, messages: Message[], path?: string): Promise<void>;
66
- //#endregion
67
- export { assembleCatalogueRecord, declarationPathFor, expandBucketOutputPath, mergeExtractedMessages, pruneLocaleMessages, readCatalogueMessages, resolveCatalogueSources, resolveFallbackChain, writeCatalogueMessages };
72
+ export declare function writeCatalogueMessages(bucket: Bucket, locale: string, messages: Message[], path?: string): Promise<void>;
@@ -1,47 +1,56 @@
1
- import { a as Message, n as Config, t as Bucket } from "../../shapes-CRlXtss0.mjs";
2
- //#region src/features/catalogue/merge.d.ts
3
- declare function mergeExtractedMessages(messages: Message[]): {
1
+ import { a as Message, n as Config, t as Bucket } from "../../shapes-Dq0aJdsn.mjs";
2
+ /**
3
+ * Where a locale's generated module goes: beside its catalogue, as `.js`.
4
+ *
5
+ * @throws If that is the catalogue itself, as for a formatter with a `.js` extension
6
+ */
7
+ export declare function modulePathFor(bucket: Bucket, locale: string): string;
8
+ /**
9
+ * Build the source of a locale's generated module from its assembled record.
10
+ *
11
+ * The module is plain data, so it can cross a server/client boundary as JSON.
12
+ *
13
+ * @param record The locale's messages, keyed by id, as ICU
14
+ */
15
+ export declare function generateCatalogueModule(record: Record<string, string>): string;
16
+ /**
17
+ * Compile one locale's catalogue, and its fallbacks, into a module on disk.
18
+ *
19
+ * The fallback chain is merged here, so the app still imports one module per locale.
20
+ */
21
+ export declare function emitCatalogueModule(config: Config, bucket: Bucket, locale: string): Promise<{
22
+ path: string;
23
+ count: number;
24
+ }>;
25
+ export declare function mergeExtractedMessages(messages: Message[]): {
4
26
  message: string;
5
- comments: string[];
6
- references: string[];
7
27
  translation?: string | undefined;
8
28
  id?: string | undefined;
9
29
  context?: string | undefined;
10
- }[];
11
- declare function pruneLocaleMessages(existingMessages: Message[], sourceMessages: Message[]): {
12
- message: string;
13
30
  comments: string[];
14
31
  references: string[];
32
+ }[];
33
+ export declare function pruneLocaleMessages(existingMessages: Message[], sourceMessages: Message[]): {
34
+ message: string;
15
35
  translation?: string | undefined;
16
36
  id?: string | undefined;
17
37
  context?: string | undefined;
38
+ comments: string[];
39
+ references: string[];
18
40
  }[];
19
- //#endregion
20
- //#region src/features/catalogue/path.d.ts
21
- declare function expandBucketOutputPath(bucket: Bucket, locale: string, extension?: `.${string}`): string;
22
- /**
23
- * The declaration file that types a catalogue, e.g. `en.json` -> `en.d.json.ts`.
24
- *
25
- * TypeScript resolves `./en.json` by stripping the extension and looking for
26
- * `en.d.json.ts`; the `en.json.d.ts` form is only consulted for extensions the
27
- * resolver does not recognise. Non-JS extensions additionally require
28
- * `allowArbitraryExtensions` in the consumer's tsconfig.
29
- */
30
- declare function declarationPathFor(cataloguePath: string): string;
31
- //#endregion
32
- //#region src/features/catalogue/record.d.ts
41
+ export declare function expandBucketOutputPath(bucket: Bucket, locale: string, extension?: `.${string}`): string;
33
42
  /**
34
43
  * Resolve the fallback chain for a locale, most specific first. The source
35
44
  * locale (the first configured locale) is always the final fallback, so an
36
45
  * untranslated key ultimately resolves to the source string.
37
46
  */
38
- declare function resolveFallbackChain(config: Config, locale: string): string[];
47
+ export declare function resolveFallbackChain(config: Config, locale: string): string[];
39
48
  /**
40
49
  * Resolve the catalogue files that contribute to a locale module, most specific
41
50
  * first. When the path does not map to a configured locale it is loaded on its
42
51
  * own.
43
52
  */
44
- declare function resolveCatalogueSources(config: Config, bucket: Bucket, path: string): {
53
+ export declare function resolveCatalogueSources(config: Config, bucket: Bucket, path: string): {
45
54
  locale: string | undefined;
46
55
  sources: string[];
47
56
  };
@@ -51,17 +60,13 @@ declare function resolveCatalogueSources(config: Config, bucket: Bucket, path: s
51
60
  * (most specific first): more specific locales override their fallbacks, and any
52
61
  * key still untranslated falls back to its source message.
53
62
  */
54
- declare function assembleCatalogueRecord(bucket: Bucket, contents: string[]): Record<string, string>;
55
- //#endregion
56
- //#region src/features/catalogue/storage.d.ts
57
- declare function readCatalogueMessages(bucket: Bucket, locale: string, path?: string): Promise<{
63
+ export declare function assembleCatalogueRecord(bucket: Bucket, contents: string[]): Record<string, string>;
64
+ export declare function readCatalogueMessages(bucket: Bucket, locale: string, path?: string): Promise<{
58
65
  message: string;
59
- comments: string[];
60
- references: string[];
61
66
  translation?: string | undefined;
62
67
  id?: string | undefined;
63
68
  context?: string | undefined;
69
+ comments: string[];
70
+ references: string[];
64
71
  }[]>;
65
- declare function writeCatalogueMessages(bucket: Bucket, locale: string, messages: Message[], path?: string): Promise<void>;
66
- //#endregion
67
- export { assembleCatalogueRecord, declarationPathFor, expandBucketOutputPath, mergeExtractedMessages, pruneLocaleMessages, readCatalogueMessages, resolveCatalogueSources, resolveFallbackChain, writeCatalogueMessages };
72
+ export declare function writeCatalogueMessages(bucket: Bucket, locale: string, messages: Message[], path?: string): Promise<void>;
@@ -1,39 +1 @@
1
- import { t as generateHash } from "../../hash-DvzpieJD.mjs";
2
- import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, r as declarationPathFor, t as readCatalogueMessages } from "../../storage-8485YdBh.mjs";
3
- import { resolve } from "node:path";
4
- //#region src/features/catalogue/record.ts
5
- function resolveFallbackChain(config, locale) {
6
- const source = config.locales[0];
7
- const configured = config.fallbackLocales?.[locale];
8
- const fallbacks = configured ? Array.isArray(configured) ? configured : [configured] : [];
9
- return Array.from(/* @__PURE__ */ new Set([
10
- locale,
11
- ...fallbacks,
12
- source
13
- ]));
14
- }
15
- function resolveCatalogueSources(config, bucket, path) {
16
- const resolved = resolve(path);
17
- const locale = config.locales.find((l) => expandBucketOutputPath(bucket, l) === resolved);
18
- return {
19
- locale,
20
- sources: locale ? resolveFallbackChain(config, locale).map((l) => expandBucketOutputPath(bucket, l)) : [resolved]
21
- };
22
- }
23
- function assembleCatalogueRecord(bucket, contents) {
24
- const record = {};
25
- for (const content of [...contents].reverse()) {
26
- if (!content) continue;
27
- for (const message of bucket.formatter.parse(content)) {
28
- const key = message.id || generateHash(message.message, message.context);
29
- if (message.translation) {
30
- record[key] = message.translation;
31
- continue;
32
- }
33
- if (!record[key] && message.message) record[key] = message.message;
34
- }
35
- }
36
- return record;
37
- }
38
- //#endregion
39
- export { assembleCatalogueRecord, declarationPathFor, expandBucketOutputPath, mergeExtractedMessages, pruneLocaleMessages, readCatalogueMessages, resolveCatalogueSources, resolveFallbackChain, writeCatalogueMessages };
1
+ export { i as assembleCatalogueRecord, t as emitCatalogueModule, l as expandBucketOutputPath, n as generateCatalogueModule, u as mergeExtractedMessages, r as modulePathFor, d as pruneLocaleMessages, s as readCatalogueMessages, a as resolveCatalogueSources, o as resolveFallbackChain, c as writeCatalogueMessages } from "../../emit-q78c-G_t.mjs";
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_loader = require("../../loader-XE7SprlF.cjs");
2
+ const require_loader = require("../../loader-V92j1gfD.cjs");
3
3
  exports.resolveConfig = require_loader.resolveConfig;
4
4
  exports.resolveConfigFile = require_loader.resolveConfigFile;
@@ -1,11 +1,8 @@
1
- import { n as Config } from "../../shapes-CRlXtss0.cjs";
2
- //#region src/features/loader/resolve.d.ts
1
+ import { n as Config } from "../../shapes-Dq0aJdsn.cjs";
3
2
  /**
4
3
  * The config file {@link resolveConfig} would load, for callers that need the
5
4
  * path itself rather than its contents, salting a bundler's cache key with it,
6
5
  * for one, since what a catalogue assembles into depends on the config.
7
6
  */
8
- declare function resolveConfigFile(name?: string): string;
9
- declare function resolveConfig(name?: string): Config;
10
- //#endregion
11
- export { resolveConfig, resolveConfigFile };
7
+ export declare function resolveConfigFile(name?: string): string;
8
+ export declare function resolveConfig(name?: string): Config;
@@ -1,11 +1,8 @@
1
- import { n as Config } from "../../shapes-CRlXtss0.mjs";
2
- //#region src/features/loader/resolve.d.ts
1
+ import { n as Config } from "../../shapes-Dq0aJdsn.mjs";
3
2
  /**
4
3
  * The config file {@link resolveConfig} would load, for callers that need the
5
4
  * path itself rather than its contents, salting a bundler's cache key with it,
6
5
  * for one, since what a catalogue assembles into depends on the config.
7
6
  */
8
- declare function resolveConfigFile(name?: string): string;
9
- declare function resolveConfig(name?: string): Config;
10
- //#endregion
11
- export { resolveConfig, resolveConfigFile };
7
+ export declare function resolveConfigFile(name?: string): string;
8
+ export declare function resolveConfig(name?: string): Config;
@@ -1,2 +1 @@
1
- import { n as resolveConfigFile, t as resolveConfig } from "../../loader-C6XxYhMl.mjs";
2
- export { resolveConfig, resolveConfigFile };
1
+ export { t as resolveConfig, n as resolveConfigFile } from "../../loader-1PBbw7yb.mjs";
@@ -1,20 +1,17 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_hash = require("../../hash-51ce8YiG.cjs");
3
- let _messageformat_date_skeleton = require("@messageformat/date-skeleton");
4
- let _messageformat_number_skeleton = require("@messageformat/number-skeleton");
5
- //#region src/features/messages/escape.ts
2
+ const require_compile = require("../../compile-BrwRUqtQ.cjs");
3
+ // src/features/messages/escape.ts
6
4
  function escapeIcuLiteral(text, hash = false) {
7
5
  return text.replace(/'/gu, "''").replace(hash ? /[{}#]+/gu : /[{}]+/gu, (run) => `'${run}'`);
8
6
  }
9
- //#endregion
10
- //#region src/features/messages/types.ts
7
+ // src/features/messages/types.ts
11
8
  var Base = class {
12
9
  toICUString() {
13
10
  return convertMessageToIcu(this);
14
11
  }
15
12
  toHashString() {
16
13
  const context = this instanceof CompositeMessage ? this.descriptor.context : void 0;
17
- return require_hash.generateHash(this.toICUString(), context);
14
+ return require_compile.generateHash(this.toICUString(), context);
18
15
  }
19
16
  };
20
17
  var LiteralMessage = class extends Base {
@@ -78,8 +75,7 @@ var CompositeMessage = class extends Base {
78
75
  this.whitespace = whitespace;
79
76
  }
80
77
  };
81
- //#endregion
82
- //#region src/features/messages/identifier.ts
78
+ // src/features/messages/identifier.ts
83
79
  const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
84
80
  const BRANCH_PATTERN = /^(?:=\d+|[^\p{Pattern_Syntax}\p{Pattern_White_Space}]+)$/u;
85
81
  function getBranchCase(kind, identifier) {
@@ -148,8 +144,7 @@ function collectAssignedIdentifiers(message, equivalent) {
148
144
  for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
149
145
  return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
150
146
  }
151
- //#endregion
152
- //#region src/features/messages/convert.ts
147
+ // src/features/messages/convert.ts
153
148
  function convertMessageToIcu(message) {
154
149
  function internalConvertMessageToIcu(message, hash) {
155
150
  switch (true) {
@@ -182,68 +177,23 @@ function convertMessageToIcu(message) {
182
177
  }
183
178
  return internalConvertMessageToIcu(message, void 0).trim();
184
179
  }
185
- //#endregion
186
- //#region src/features/messages/format.ts
187
- const ARGUMENT_STYLES = {
188
- number: ["integer", "percent"],
189
- date: [
190
- "short",
191
- "medium",
192
- "long",
193
- "full"
194
- ],
195
- time: [
196
- "short",
197
- "medium",
198
- "long",
199
- "full"
200
- ]
201
- };
202
- const ARGUMENT_TYPES = Object.keys(ARGUMENT_STYLES);
203
- function isArgumentType(kind) {
204
- return Object.hasOwn(ARGUMENT_STYLES, kind);
205
- }
206
- const LITERAL_STYLE_PATTERN = /^[^{}\r\n]*[#0][^{}\r\n]*$/;
207
- const SKELETON = "::";
208
- function invalidSkeleton(type, skeleton) {
209
- if (skeleton === "") return "it names no fields";
210
- const errors = [];
211
- if (type === "number") {
212
- (0, _messageformat_number_skeleton.getNumberFormatOptions)((0, _messageformat_number_skeleton.parseNumberSkeleton)(skeleton, (error) => errors.push(String(error))), (stem) => {
213
- if (stem !== "scale") errors.push(`unsupported stem '${stem}'`);
214
- });
215
- return errors[0];
216
- }
217
- const options = (0, _messageformat_date_skeleton.getDateTimeFormatOptions)((0, _messageformat_date_skeleton.parseDateTokens)(skeleton), (_type, message) => errors.push(message));
218
- if (errors.length > 0) return errors[0];
219
- if (Object.keys(options).length === 0) return "it names no fields";
220
- }
221
- function validateArgumentStyle(type, style) {
222
- const named = ARGUMENT_STYLES[type];
223
- if (named.includes(style)) return;
224
- if (style.startsWith(SKELETON)) {
225
- const reason = invalidSkeleton(type, style.slice(2));
226
- if (!reason) return;
227
- throw new Error(`Invalid ${type} skeleton '${style}': ${reason}`);
228
- }
229
- if (type === "number" && LITERAL_STYLE_PATTERN.test(style)) return;
230
- const expected = named.map((s) => `'${s}'`).join(", ");
231
- throw new Error(`Invalid ${type} style '${style}', expected ${expected}, or a skeleton such as ` + (type === "number" ? "::currency/EUR" : "::yyyyMMdd") + (type === "number" ? ", or a literal number pattern such as #,##0.00" : ""));
232
- }
233
- //#endregion
234
- exports.ARGUMENT_STYLES = ARGUMENT_STYLES;
235
- exports.ARGUMENT_TYPES = ARGUMENT_TYPES;
180
+ exports.ARGUMENT_STYLES = require_compile.ARGUMENT_STYLES;
181
+ exports.ARGUMENT_TYPES = require_compile.ARGUMENT_TYPES;
236
182
  exports.AUTO_INCREMENT_IDENTIFIER = AUTO_INCREMENT_IDENTIFIER;
237
183
  exports.ArgumentMessage = ArgumentMessage;
238
184
  exports.ChoiceMessage = ChoiceMessage;
239
185
  exports.CompositeMessage = CompositeMessage;
240
186
  exports.ElementMessage = ElementMessage;
241
187
  exports.LiteralMessage = LiteralMessage;
188
+ exports.StyleError = require_compile.StyleError;
242
189
  exports.assignSequenceIdentifiers = assignSequenceIdentifiers;
190
+ exports.compileMessage = require_compile.compileMessage;
243
191
  exports.convertMessageToIcu = convertMessageToIcu;
192
+ exports.dateTimeStyle = require_compile.dateTimeStyle;
244
193
  exports.escapeIcuLiteral = escapeIcuLiteral;
245
- exports.generateHash = require_hash.generateHash;
194
+ exports.generateHash = require_compile.generateHash;
246
195
  exports.getBranchCase = getBranchCase;
247
- exports.isArgumentType = isArgumentType;
248
- exports.validateArgumentStyle = validateArgumentStyle;
196
+ exports.isArgumentType = require_compile.isArgumentType;
197
+ exports.numberStyle = require_compile.numberStyle;
198
+ exports.validateArgumentStyle = require_compile.validateArgumentStyle;
249
199
  exports.validateBranchIdentifier = validateBranchIdentifier;
@@ -1,41 +1,49 @@
1
- //#region src/features/messages/format.d.ts
2
1
  /**
3
- * The ICU argument types a macro can author, and the named styles each accepts.
4
- *
5
- * A style may also be a skeleton, which is where the formats these names have
6
- * no word for live; see {@link validateArgumentStyle}.
2
+ * What each node in a compiled message is, by the number it starts with.
7
3
  *
8
- * `currency` is deliberately absent from `number`: MF1 has nowhere to write the
9
- * code, so `{price, number, currency}` formats as a bare number. Currency
10
- * belongs to a skeleton, `::currency/EUR`, which the formatter does honour.
11
- *
12
- * `spellout`, RBNF `ordinal` and `choice` are absent by decision: the first two
13
- * are ICU4J/ICU4C rule-based formats with no `Intl` equivalent, and the third
14
- * is deprecated in ICU itself in favour of `plural`.
4
+ * The numbers are the format, so a kind is only ever appended, never renumbered or reused.
15
5
  */
16
- declare const ARGUMENT_STYLES: {
17
- readonly number: readonly ["integer", "percent"];
18
- readonly date: readonly ["short", "medium", "long", "full"];
19
- readonly time: readonly ["short", "medium", "long", "full"];
6
+ declare const Kind: {
7
+ readonly Value: 0;
8
+ readonly Number: 1;
9
+ readonly DateTime: 2;
10
+ readonly Plural: 3;
11
+ readonly Ordinal: 4;
12
+ readonly Select: 5;
13
+ readonly Hash: 6;
20
14
  };
21
- type ArgumentType = keyof typeof ARGUMENT_STYLES;
22
- declare const ARGUMENT_TYPES: ArgumentType[];
23
- declare function isArgumentType(kind: string): kind is ArgumentType;
15
+ type Kind = (typeof Kind)[keyof typeof Kind];
24
16
  /**
25
- * Reject an argument style the formatter cannot honour, while the style is
26
- * still attached to a file and a line.
17
+ * A compiled message.
18
+ *
19
+ * The CLI compiles a catalogue to this: strings and arrays, with styles already resolved to
20
+ * `Intl` options. It is plain JSON, so it can cross a server/client boundary.
27
21
  *
28
- * A style is a bare string in the source and in the catalogue, so nothing
29
- * between here and the runtime has an opinion about it. Left unchecked, a typo
30
- * like `{d, date, meduim}` only misformats once it reaches a user.
22
+ * A node is an array starting with its {@link Kind}; an array starting with anything else is a
23
+ * concatenation. Operands are descriptor keys, never nodes. A message with no placeholders is its
24
+ * own string.
25
+ */
26
+ type Message$1 = string | Message$1[] | [typeof Kind.Value, string] | [typeof Kind.Number, string, Intl.NumberFormatOptions?, number?] | [typeof Kind.DateTime, string, Intl.DateTimeFormatOptions?] | [typeof Kind.Plural, string, Message$1.Cases, number?] | [typeof Kind.Ordinal, string, Message$1.Cases, number?] | [typeof Kind.Select, string, Message$1.Cases] | [typeof Kind.Hash];
27
+ declare namespace Message$1 {
28
+ /**
29
+ * A plural's or a select's branches, by key. A plural's keys are CLDR
30
+ * categories or an exact `=n`, and `other` is the fallback for both.
31
+ */
32
+ type Cases = {
33
+ [key: string]: Message$1;
34
+ };
35
+ /** What a compiled message is called with: the descriptor the transform built. */
36
+ type Values = Record<string, unknown>;
37
+ }
38
+ /**
39
+ * Compile one ICU MessageFormat 1 message.
31
40
  *
32
- * Three forms are accepted: a named style, a `::`-prefixed skeleton, and, for
33
- * a number, a literal pattern such as `#,##0.00`.
41
+ * @param icu The message, in ICU MessageFormat 1 syntax
42
+ * @returns The compiled message
43
+ * @throws If the message is not valid ICU MessageFormat 1
34
44
  */
35
- declare function validateArgumentStyle(type: ArgumentType, style: string): void;
36
- //#endregion
37
- //#region src/features/messages/identifier.d.ts
38
- declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
45
+ export declare function compileMessage(icu: string): Message$1;
46
+ export declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
39
47
  /**
40
48
  * The ICU case a branch is written as.
41
49
  *
@@ -48,7 +56,7 @@ declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
48
56
  * coerce to `=0`, which would pass for a key selecting zero and leave the
49
57
  * author's own key out of the catalogue.
50
58
  */
51
- declare function getBranchCase(kind: string, identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): string;
59
+ export declare function getBranchCase(kind: string, identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): string;
52
60
  /**
53
61
  * Reject a branch key ICU cannot express, while the key is still attached to a
54
62
  * file and a line.
@@ -57,23 +65,77 @@ declare function getBranchCase(kind: string, identifier: string | typeof AUTO_IN
57
65
  * builds, and extracts to a normal-looking catalogue entry, and the only sign
58
66
  * of trouble is a parse error at format time.
59
67
  */
60
- declare function validateBranchIdentifier(kind: string, identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): void;
68
+ export declare function validateBranchIdentifier(kind: string, identifier: string | typeof AUTO_INCREMENT_IDENTIFIER): void;
61
69
  /**
62
70
  * Decides whether two placeholders sharing a name are the same placeholder, and
63
71
  * so may share it. Only the syntax that produced them can answer that, so the
64
72
  * caller supplies the comparison; by default nothing is interchangeable.
65
73
  */
66
- type PlaceholderEquivalence = (a: any, b: any) => boolean;
67
- declare function assignSequenceIdentifiers(message: Message, sequence?: {
74
+ export type PlaceholderEquivalence = (a: any, b: any) => boolean;
75
+ export declare function assignSequenceIdentifiers(message: Message, sequence?: {
68
76
  current: number;
69
77
  }, equivalent?: PlaceholderEquivalence): void;
70
- //#endregion
71
- //#region src/features/messages/types.d.ts
78
+ /**
79
+ * Argument styles: which ones a macro may author, and the `Intl` options each resolves to.
80
+ *
81
+ * Validation and compilation share these functions, so a style the transform accepts is one the
82
+ * compiler honours.
83
+ */
84
+ /**
85
+ * The ICU argument types a macro can author, and the named styles each accepts.
86
+ *
87
+ * `currency` is absent from `number` because MF1 has nowhere to write the code; use
88
+ * `::currency/EUR`.
89
+ * `duration`, `spellout`, RBNF `ordinal` and `choice` are absent too, and compile to the bare
90
+ * value.
91
+ */
92
+ export declare const ARGUMENT_STYLES: {
93
+ readonly number: readonly ['integer', 'percent'];
94
+ readonly date: readonly ['short', 'medium', 'long', 'full'];
95
+ readonly time: readonly ['short', 'medium', 'long', 'full'];
96
+ };
97
+ export type ArgumentType = keyof typeof ARGUMENT_STYLES;
98
+ export declare const ARGUMENT_TYPES: ArgumentType[];
99
+ export declare function isArgumentType(kind: string): kind is ArgumentType;
100
+ /** The extra key a number's bag may carry, which `Intl` has no option for. */
101
+ export type NumberOptions = Intl.NumberFormatOptions & {
102
+ scale?: number;
103
+ };
104
+ /** A style that could not be resolved, with the reason it could not. */
105
+ export declare class StyleError extends Error {}
106
+ /**
107
+ * Turn a `date` or `time` argument style into `Intl.DateTimeFormat` options.
108
+ *
109
+ * A `::`-prefixed style is a skeleton such as `::yyyyMMdd`; an empty style takes MF1's default.
110
+ *
111
+ * @throws {StyleError} If the style names no fields
112
+ */
113
+ export declare function dateTimeStyle(kind: 'date' | 'time', style: string): Intl.DateTimeFormatOptions;
114
+ /**
115
+ * Turn a `number` argument style into `Intl.NumberFormat` options.
116
+ *
117
+ * Accepts MF1's named styles, a `::`-prefixed skeleton, or a literal pattern such as `#,##0.00`.
118
+ * Named styles are expanded here because the pattern parser would read `percent` as literal text.
119
+ *
120
+ * `scale` comes back beside the bag, since `Intl` has no option for it.
121
+ *
122
+ * @throws {StyleError} If the style is not valid, or asks for something `Intl` cannot express
123
+ */
124
+ export declare function numberStyle(style: string): NumberOptions;
125
+ /**
126
+ * Reject an argument style the compiler cannot honour, while it is still attached to a file and
127
+ * line.
128
+ *
129
+ * The compiler falls back to the default format, so an unchecked typo like `{d, date, meduim}` only
130
+ * misformats in production.
131
+ * Skeletons and patterns are checked by resolving them as the compiler will.
132
+ */
133
+ export declare function validateArgumentStyle(type: ArgumentType, style: string): void;
72
134
  declare abstract class Base {
73
135
  toICUString(this: Message): string;
74
136
  toHashString(this: Message): string;
75
137
  }
76
- declare class LiteralMessage extends Base {
138
+ export declare class LiteralMessage extends Base {
77
139
  readonly text: string;
78
140
  constructor(text: string);
79
141
  }
@@ -85,23 +147,23 @@ declare class LiteralMessage extends Base {
85
147
  * options, because the catalogue is the source of truth and only the ICU
86
148
  * spelling round-trips back out of it.
87
149
  */
88
- interface ArgumentFormat {
150
+ export interface ArgumentFormat {
89
151
  type: ArgumentType;
90
152
  style?: string;
91
153
  }
92
- declare class ArgumentMessage extends Base {
154
+ export declare class ArgumentMessage extends Base {
93
155
  identifier: string | typeof AUTO_INCREMENT_IDENTIFIER;
94
156
  readonly expression: any;
95
157
  readonly format?: ArgumentFormat | undefined;
96
158
  constructor(identifier: string | typeof AUTO_INCREMENT_IDENTIFIER, expression: any, format?: ArgumentFormat | undefined);
97
159
  }
98
- declare class ElementMessage extends Base {
160
+ export declare class ElementMessage extends Base {
99
161
  identifier: string | typeof AUTO_INCREMENT_IDENTIFIER;
100
162
  readonly children: Message[];
101
163
  readonly expression: any;
102
164
  constructor(identifier: string | typeof AUTO_INCREMENT_IDENTIFIER, children: Message[], expression: any);
103
165
  }
104
- declare class ChoiceMessage extends Base {
166
+ export declare class ChoiceMessage extends Base {
105
167
  readonly kind: string;
106
168
  identifier: string | typeof AUTO_INCREMENT_IDENTIFIER;
107
169
  readonly branches: {
@@ -126,7 +188,7 @@ declare class ChoiceMessage extends Base {
126
188
  */
127
189
  offset?: number | undefined);
128
190
  }
129
- declare class CompositeMessage extends Base {
191
+ export declare class CompositeMessage extends Base {
130
192
  readonly descriptor: {
131
193
  id?: string;
132
194
  context?: string;
@@ -141,12 +203,8 @@ declare class CompositeMessage extends Base {
141
203
  context?: string;
142
204
  }, comments: string[], references: string[], children: Message[], accessor: any, whitespace?: boolean | undefined);
143
205
  }
144
- type Message = LiteralMessage | ArgumentMessage | ElementMessage | ChoiceMessage | CompositeMessage;
145
- //#endregion
146
- //#region src/features/messages/convert.d.ts
147
- declare function convertMessageToIcu(message: Message): string;
148
- //#endregion
149
- //#region src/features/messages/escape.d.ts
206
+ export type Message = LiteralMessage | ArgumentMessage | ElementMessage | ChoiceMessage | CompositeMessage;
207
+ export declare function convertMessageToIcu(message: Message): string;
150
208
  /**
151
209
  * Quoting for text that has to survive a message format unchanged.
152
210
  *
@@ -167,9 +225,7 @@ declare function convertMessageToIcu(message: Message): string;
167
225
  * @param hash Whether `#` stands for a number here, i.e. whether some `plural`
168
226
  * or `ordinal` encloses this text
169
227
  */
170
- declare function escapeIcuLiteral(text: string, hash?: boolean): string;
171
- //#endregion
172
- //#region src/features/messages/hash.d.ts
228
+ export declare function escapeIcuLiteral(text: string, hash?: boolean): string;
173
229
  /**
174
230
  * Hashed in userland rather than with `node:crypto`, because this runs wherever
175
231
  * a bundler runs it. `createHash` is one of the entry points `unenv` leaves
@@ -178,6 +234,5 @@ declare function escapeIcuLiteral(text: string, hash?: boolean): string;
178
234
  * equivalent, `subtle.digest`, is async, and an id is resolved from a
179
235
  * synchronous extraction pass.
180
236
  */
181
- declare function generateHash(input: string, context?: string): string;
182
- //#endregion
183
- export { ARGUMENT_STYLES, ARGUMENT_TYPES, AUTO_INCREMENT_IDENTIFIER, ArgumentFormat, ArgumentMessage, ArgumentType, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, escapeIcuLiteral, generateHash, getBranchCase, isArgumentType, validateArgumentStyle, validateBranchIdentifier };
237
+ export declare function generateHash(input: string, context?: string): string;
238
+ export {};