@saykit/config 0.4.1 → 0.6.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.
- package/dist/commands/index.cjs +6 -5
- package/dist/commands/index.d.cts +1 -1
- package/dist/commands/index.d.mts +1 -1
- package/dist/commands/index.mjs +6 -4
- package/dist/features/catalogue/index.cjs +3 -4
- package/dist/features/catalogue/index.d.cts +1 -2
- package/dist/features/catalogue/index.d.mts +1 -2
- package/dist/features/catalogue/index.mjs +3 -3
- package/dist/features/loader/index.cjs +1 -1
- package/dist/features/loader/index.d.cts +1 -2
- package/dist/features/loader/index.d.mts +1 -2
- package/dist/features/loader/index.mjs +1 -1
- package/dist/features/messages/index.cjs +61 -8
- package/dist/features/messages/index.d.cts +8 -2
- package/dist/features/messages/index.d.mts +8 -2
- package/dist/features/messages/index.mjs +61 -8
- package/dist/{hash-CxBlj5Dz.cjs → hash-51ce8YiG.cjs} +0 -1
- package/dist/index.cjs +53 -3
- package/dist/index.d.cts +11 -5
- package/dist/index.d.mts +11 -5
- package/dist/index.mjs +29 -0
- package/dist/loader-A1uS7qkK.cjs +92 -0
- package/dist/loader-DLyuZzF2.mjs +87 -0
- package/dist/{shapes-Ba3xS10n.d.cts → shapes-CRlXtss0.d.cts} +48 -2
- package/dist/{shapes-NPfwlInG.d.mts → shapes-CRlXtss0.d.mts} +48 -2
- package/dist/{storage-CqKPYfCR.mjs → storage-B6mn0s3V.mjs} +1 -1
- package/dist/{storage-wS6e6qWM.cjs → storage-DqhzA5H8.cjs} +1 -2
- package/package.json +6 -11
- package/dist/chunk-CKQMccvm.cjs +0 -28
- package/dist/loader-BuAqYtfl.mjs +0 -191
- package/dist/loader-DATEQsXj.cjs +0 -198
- /package/dist/{hash-DyC8GzMa.mjs → hash-DvzpieJD.mjs} +0 -0
package/dist/commands/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
require("../
|
|
3
|
-
const
|
|
4
|
-
const require_loader = require("../loader-DATEQsXj.cjs");
|
|
2
|
+
const require_storage = require("../storage-DqhzA5H8.cjs");
|
|
3
|
+
const require_loader = require("../loader-A1uS7qkK.cjs");
|
|
5
4
|
let _commander_js_extra_typings = require("@commander-js/extra-typings");
|
|
6
5
|
let node_fs_promises = require("node:fs/promises");
|
|
7
6
|
let node_path = require("node:path");
|
|
@@ -145,7 +144,7 @@ function exists(path) {
|
|
|
145
144
|
var BucketExtractWorker = class extends BucketWorker {
|
|
146
145
|
#indexedMessagesByPath = /* @__PURE__ */ new Map();
|
|
147
146
|
get #indexedMessages() {
|
|
148
|
-
return Array.from(this.#indexedMessagesByPath.values()).flat();
|
|
147
|
+
return [...this.bucket.messages, ...Array.from(this.#indexedMessagesByPath.values()).flat()];
|
|
149
148
|
}
|
|
150
149
|
async #indexPath(path) {
|
|
151
150
|
const relativePath = normalisePathForLogs(path);
|
|
@@ -167,8 +166,10 @@ var BucketExtractWorker = class extends BucketWorker {
|
|
|
167
166
|
this.logger.info(`Scanning bucket: ${this.bucket.include}`);
|
|
168
167
|
const paths = await globBucket(this.bucket);
|
|
169
168
|
this.logger.step(`Found ${paths.length} file(s)`);
|
|
169
|
+
if (this.bucket.messages.length) this.logger.step(`Including ${this.bucket.messages.length} message(s) declared in the config`);
|
|
170
170
|
await Promise.all(paths.map((p) => this.#indexPath(p)));
|
|
171
|
-
|
|
171
|
+
const extracted = Array.from(this.#indexedMessagesByPath.values()).flat().length;
|
|
172
|
+
this.logger.info(`Total extracted messages: ${extracted}`);
|
|
172
173
|
}
|
|
173
174
|
async write() {
|
|
174
175
|
const mergedMessages = require_storage.mergeExtractedMessages(this.#indexedMessages);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
package/dist/commands/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, t as readCatalogueMessages } from "../storage-
|
|
3
|
-
import { t as resolveConfig } from "../loader-
|
|
2
|
+
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, t as readCatalogueMessages } from "../storage-B6mn0s3V.mjs";
|
|
3
|
+
import { t as resolveConfig } from "../loader-DLyuZzF2.mjs";
|
|
4
4
|
import { Command, program } from "@commander-js/extra-typings";
|
|
5
5
|
import { access, glob, readFile, stat, watch } from "node:fs/promises";
|
|
6
6
|
import { join, relative } from "node:path";
|
|
@@ -144,7 +144,7 @@ function exists(path) {
|
|
|
144
144
|
var BucketExtractWorker = class extends BucketWorker {
|
|
145
145
|
#indexedMessagesByPath = /* @__PURE__ */ new Map();
|
|
146
146
|
get #indexedMessages() {
|
|
147
|
-
return Array.from(this.#indexedMessagesByPath.values()).flat();
|
|
147
|
+
return [...this.bucket.messages, ...Array.from(this.#indexedMessagesByPath.values()).flat()];
|
|
148
148
|
}
|
|
149
149
|
async #indexPath(path) {
|
|
150
150
|
const relativePath = normalisePathForLogs(path);
|
|
@@ -166,8 +166,10 @@ var BucketExtractWorker = class extends BucketWorker {
|
|
|
166
166
|
this.logger.info(`Scanning bucket: ${this.bucket.include}`);
|
|
167
167
|
const paths = await globBucket(this.bucket);
|
|
168
168
|
this.logger.step(`Found ${paths.length} file(s)`);
|
|
169
|
+
if (this.bucket.messages.length) this.logger.step(`Including ${this.bucket.messages.length} message(s) declared in the config`);
|
|
169
170
|
await Promise.all(paths.map((p) => this.#indexPath(p)));
|
|
170
|
-
|
|
171
|
+
const extracted = Array.from(this.#indexedMessagesByPath.values()).flat().length;
|
|
172
|
+
this.logger.info(`Total extracted messages: ${extracted}`);
|
|
171
173
|
}
|
|
172
174
|
async write() {
|
|
173
175
|
const mergedMessages = mergeExtractedMessages(this.#indexedMessages);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("../../
|
|
3
|
-
const
|
|
4
|
-
const require_storage = require("../../storage-wS6e6qWM.cjs");
|
|
2
|
+
const require_hash = require("../../hash-51ce8YiG.cjs");
|
|
3
|
+
const require_storage = require("../../storage-DqhzA5H8.cjs");
|
|
5
4
|
let node_path = require("node:path");
|
|
6
5
|
//#region src/features/catalogue/record.ts
|
|
7
6
|
/**
|
|
@@ -13,7 +12,7 @@ function resolveFallbackChain(config, locale) {
|
|
|
13
12
|
const source = config.locales[0];
|
|
14
13
|
const configured = config.fallbackLocales?.[locale];
|
|
15
14
|
const fallbacks = configured ? Array.isArray(configured) ? configured : [configured] : [];
|
|
16
|
-
return Array.from(new Set([
|
|
15
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
17
16
|
locale,
|
|
18
17
|
...fallbacks,
|
|
19
18
|
source
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { a as Message, n as Config, t as Bucket } from "../../shapes-CRlXtss0.cjs";
|
|
3
2
|
//#region src/features/catalogue/merge.d.ts
|
|
4
3
|
declare function mergeExtractedMessages(messages: Message[]): {
|
|
5
4
|
message: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { a as Message, n as Config, t as Bucket } from "../../shapes-CRlXtss0.mjs";
|
|
3
2
|
//#region src/features/catalogue/merge.d.ts
|
|
4
3
|
declare function mergeExtractedMessages(messages: Message[]): {
|
|
5
4
|
message: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as generateHash } from "../../hash-
|
|
2
|
-
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, r as declarationPathFor, t as readCatalogueMessages } from "../../storage-
|
|
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-B6mn0s3V.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
//#region src/features/catalogue/record.ts
|
|
5
5
|
/**
|
|
@@ -11,7 +11,7 @@ function resolveFallbackChain(config, locale) {
|
|
|
11
11
|
const source = config.locales[0];
|
|
12
12
|
const configured = config.fallbackLocales?.[locale];
|
|
13
13
|
const fallbacks = configured ? Array.isArray(configured) ? configured : [configured] : [];
|
|
14
|
-
return Array.from(new Set([
|
|
14
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
15
15
|
locale,
|
|
16
16
|
...fallbacks,
|
|
17
17
|
source
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as resolveConfig } from "../../loader-
|
|
1
|
+
import { t as resolveConfig } from "../../loader-DLyuZzF2.mjs";
|
|
2
2
|
export { resolveConfig };
|
|
@@ -1,16 +1,52 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_hash = require("../../hash-
|
|
2
|
+
const require_hash = require("../../hash-51ce8YiG.cjs");
|
|
3
3
|
//#region src/features/messages/identifier.ts
|
|
4
4
|
const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
|
|
5
|
-
function assignSequenceIdentifiers(message, sequence = { current: 0 }) {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalent = () => false) {
|
|
6
|
+
const reserved = collectAssignedIdentifiers(message, equivalent);
|
|
7
|
+
function next() {
|
|
8
|
+
let identifier = `${sequence.current++}`;
|
|
9
|
+
while (reserved.has(identifier)) identifier = `${sequence.current++}`;
|
|
10
|
+
return identifier;
|
|
8
11
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
function walk(message) {
|
|
13
|
+
if (message instanceof ArgumentMessage || message instanceof ElementMessage || message instanceof ChoiceMessage) {
|
|
14
|
+
if (message.identifier === AUTO_INCREMENT_IDENTIFIER) message.identifier = next();
|
|
15
|
+
}
|
|
16
|
+
if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
|
|
17
|
+
if (message instanceof ChoiceMessage) for (const branch of message.branches) {
|
|
18
|
+
if (branch.identifier === AUTO_INCREMENT_IDENTIFIER) branch.identifier = next();
|
|
19
|
+
walk(branch.value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
walk(message);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Collect the identifiers already assigned before this pass runs, so generated
|
|
26
|
+
* sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
|
|
27
|
+
*
|
|
28
|
+
* A name is claimed by what produced it, not by the name alone. Two that differ
|
|
29
|
+
* each compile to their own prop, and a translator moving them around a sentence
|
|
30
|
+
* has to be able to tell them apart, so they are a build error. Repeats are fine
|
|
31
|
+
* when nothing distinguishes them: the same variable interpolated twice is one
|
|
32
|
+
* value, and two identical elements are one tag.
|
|
33
|
+
*/
|
|
34
|
+
function collectAssignedIdentifiers(message, equivalent) {
|
|
35
|
+
const tags = /* @__PURE__ */ new Map();
|
|
36
|
+
const values = /* @__PURE__ */ new Map();
|
|
37
|
+
function claim(claimed, identifier, expression, conflict) {
|
|
38
|
+
if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
|
|
39
|
+
claimed.set(identifier, expression);
|
|
40
|
+
}
|
|
41
|
+
function walk(message) {
|
|
42
|
+
if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
|
|
43
|
+
if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
|
|
44
|
+
if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
|
|
45
|
+
if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
|
|
13
46
|
}
|
|
47
|
+
walk(message);
|
|
48
|
+
for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
|
|
49
|
+
return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
|
|
14
50
|
}
|
|
15
51
|
//#endregion
|
|
16
52
|
//#region src/features/messages/types.ts
|
|
@@ -24,12 +60,15 @@ var Base = class {
|
|
|
24
60
|
}
|
|
25
61
|
};
|
|
26
62
|
var LiteralMessage = class extends Base {
|
|
63
|
+
text;
|
|
27
64
|
constructor(text) {
|
|
28
65
|
super();
|
|
29
66
|
this.text = text;
|
|
30
67
|
}
|
|
31
68
|
};
|
|
32
69
|
var ArgumentMessage = class extends Base {
|
|
70
|
+
identifier;
|
|
71
|
+
expression;
|
|
33
72
|
constructor(identifier, expression) {
|
|
34
73
|
super();
|
|
35
74
|
this.identifier = identifier;
|
|
@@ -37,6 +76,9 @@ var ArgumentMessage = class extends Base {
|
|
|
37
76
|
}
|
|
38
77
|
};
|
|
39
78
|
var ElementMessage = class extends Base {
|
|
79
|
+
identifier;
|
|
80
|
+
children;
|
|
81
|
+
expression;
|
|
40
82
|
constructor(identifier, children, expression) {
|
|
41
83
|
super();
|
|
42
84
|
this.identifier = identifier;
|
|
@@ -45,6 +87,10 @@ var ElementMessage = class extends Base {
|
|
|
45
87
|
}
|
|
46
88
|
};
|
|
47
89
|
var ChoiceMessage = class extends Base {
|
|
90
|
+
kind;
|
|
91
|
+
identifier;
|
|
92
|
+
branches;
|
|
93
|
+
expression;
|
|
48
94
|
constructor(kind, identifier, branches, expression) {
|
|
49
95
|
super();
|
|
50
96
|
this.kind = kind;
|
|
@@ -54,6 +100,12 @@ var ChoiceMessage = class extends Base {
|
|
|
54
100
|
}
|
|
55
101
|
};
|
|
56
102
|
var CompositeMessage = class extends Base {
|
|
103
|
+
descriptor;
|
|
104
|
+
comments;
|
|
105
|
+
references;
|
|
106
|
+
children;
|
|
107
|
+
accessor;
|
|
108
|
+
whitespace;
|
|
57
109
|
constructor(descriptor, comments, references, children, accessor, whitespace) {
|
|
58
110
|
super();
|
|
59
111
|
this.descriptor = descriptor;
|
|
@@ -72,6 +124,7 @@ function convertMessageToIcu(message) {
|
|
|
72
124
|
case message instanceof LiteralMessage: return String(message.text);
|
|
73
125
|
case message instanceof ArgumentMessage: return `{${String(message.identifier)}}`;
|
|
74
126
|
case message instanceof ElementMessage: {
|
|
127
|
+
if (message.children.length === 0) return `<${String(message.identifier)}/>`;
|
|
75
128
|
const children = message.children.map((m) => internalConvertMessageToIcu(m)).join("");
|
|
76
129
|
return `<${String(message.identifier)}>${children}</${String(message.identifier)}>`;
|
|
77
130
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
//#region src/features/messages/identifier.d.ts
|
|
2
2
|
declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* Decides whether two placeholders sharing a name are the same placeholder, and
|
|
5
|
+
* so may share it. Only the syntax that produced them can answer that, so the
|
|
6
|
+
* caller supplies the comparison; by default nothing is interchangeable.
|
|
7
|
+
*/
|
|
8
|
+
type PlaceholderEquivalence = (a: any, b: any) => boolean;
|
|
3
9
|
declare function assignSequenceIdentifiers(message: Message, sequence?: {
|
|
4
10
|
current: number;
|
|
5
|
-
}): void;
|
|
11
|
+
}, equivalent?: PlaceholderEquivalence): void;
|
|
6
12
|
//#endregion
|
|
7
13
|
//#region src/features/messages/types.d.ts
|
|
8
14
|
declare abstract class Base {
|
|
@@ -60,4 +66,4 @@ declare function convertMessageToIcu(message: Message): string;
|
|
|
60
66
|
//#region src/features/messages/hash.d.ts
|
|
61
67
|
declare function generateHash(input: string, context?: string): string;
|
|
62
68
|
//#endregion
|
|
63
|
-
export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
|
|
69
|
+
export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
//#region src/features/messages/identifier.d.ts
|
|
2
2
|
declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* Decides whether two placeholders sharing a name are the same placeholder, and
|
|
5
|
+
* so may share it. Only the syntax that produced them can answer that, so the
|
|
6
|
+
* caller supplies the comparison; by default nothing is interchangeable.
|
|
7
|
+
*/
|
|
8
|
+
type PlaceholderEquivalence = (a: any, b: any) => boolean;
|
|
3
9
|
declare function assignSequenceIdentifiers(message: Message, sequence?: {
|
|
4
10
|
current: number;
|
|
5
|
-
}): void;
|
|
11
|
+
}, equivalent?: PlaceholderEquivalence): void;
|
|
6
12
|
//#endregion
|
|
7
13
|
//#region src/features/messages/types.d.ts
|
|
8
14
|
declare abstract class Base {
|
|
@@ -60,4 +66,4 @@ declare function convertMessageToIcu(message: Message): string;
|
|
|
60
66
|
//#region src/features/messages/hash.d.ts
|
|
61
67
|
declare function generateHash(input: string, context?: string): string;
|
|
62
68
|
//#endregion
|
|
63
|
-
export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
|
|
69
|
+
export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
|
|
@@ -1,15 +1,51 @@
|
|
|
1
|
-
import { t as generateHash } from "../../hash-
|
|
1
|
+
import { t as generateHash } from "../../hash-DvzpieJD.mjs";
|
|
2
2
|
//#region src/features/messages/identifier.ts
|
|
3
3
|
const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
|
|
4
|
-
function assignSequenceIdentifiers(message, sequence = { current: 0 }) {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalent = () => false) {
|
|
5
|
+
const reserved = collectAssignedIdentifiers(message, equivalent);
|
|
6
|
+
function next() {
|
|
7
|
+
let identifier = `${sequence.current++}`;
|
|
8
|
+
while (reserved.has(identifier)) identifier = `${sequence.current++}`;
|
|
9
|
+
return identifier;
|
|
7
10
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
function walk(message) {
|
|
12
|
+
if (message instanceof ArgumentMessage || message instanceof ElementMessage || message instanceof ChoiceMessage) {
|
|
13
|
+
if (message.identifier === AUTO_INCREMENT_IDENTIFIER) message.identifier = next();
|
|
14
|
+
}
|
|
15
|
+
if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
|
|
16
|
+
if (message instanceof ChoiceMessage) for (const branch of message.branches) {
|
|
17
|
+
if (branch.identifier === AUTO_INCREMENT_IDENTIFIER) branch.identifier = next();
|
|
18
|
+
walk(branch.value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
walk(message);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Collect the identifiers already assigned before this pass runs, so generated
|
|
25
|
+
* sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
|
|
26
|
+
*
|
|
27
|
+
* A name is claimed by what produced it, not by the name alone. Two that differ
|
|
28
|
+
* each compile to their own prop, and a translator moving them around a sentence
|
|
29
|
+
* has to be able to tell them apart, so they are a build error. Repeats are fine
|
|
30
|
+
* when nothing distinguishes them: the same variable interpolated twice is one
|
|
31
|
+
* value, and two identical elements are one tag.
|
|
32
|
+
*/
|
|
33
|
+
function collectAssignedIdentifiers(message, equivalent) {
|
|
34
|
+
const tags = /* @__PURE__ */ new Map();
|
|
35
|
+
const values = /* @__PURE__ */ new Map();
|
|
36
|
+
function claim(claimed, identifier, expression, conflict) {
|
|
37
|
+
if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
|
|
38
|
+
claimed.set(identifier, expression);
|
|
39
|
+
}
|
|
40
|
+
function walk(message) {
|
|
41
|
+
if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
|
|
42
|
+
if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
|
|
43
|
+
if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
|
|
44
|
+
if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
|
|
12
45
|
}
|
|
46
|
+
walk(message);
|
|
47
|
+
for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
|
|
48
|
+
return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
|
|
13
49
|
}
|
|
14
50
|
//#endregion
|
|
15
51
|
//#region src/features/messages/types.ts
|
|
@@ -23,12 +59,15 @@ var Base = class {
|
|
|
23
59
|
}
|
|
24
60
|
};
|
|
25
61
|
var LiteralMessage = class extends Base {
|
|
62
|
+
text;
|
|
26
63
|
constructor(text) {
|
|
27
64
|
super();
|
|
28
65
|
this.text = text;
|
|
29
66
|
}
|
|
30
67
|
};
|
|
31
68
|
var ArgumentMessage = class extends Base {
|
|
69
|
+
identifier;
|
|
70
|
+
expression;
|
|
32
71
|
constructor(identifier, expression) {
|
|
33
72
|
super();
|
|
34
73
|
this.identifier = identifier;
|
|
@@ -36,6 +75,9 @@ var ArgumentMessage = class extends Base {
|
|
|
36
75
|
}
|
|
37
76
|
};
|
|
38
77
|
var ElementMessage = class extends Base {
|
|
78
|
+
identifier;
|
|
79
|
+
children;
|
|
80
|
+
expression;
|
|
39
81
|
constructor(identifier, children, expression) {
|
|
40
82
|
super();
|
|
41
83
|
this.identifier = identifier;
|
|
@@ -44,6 +86,10 @@ var ElementMessage = class extends Base {
|
|
|
44
86
|
}
|
|
45
87
|
};
|
|
46
88
|
var ChoiceMessage = class extends Base {
|
|
89
|
+
kind;
|
|
90
|
+
identifier;
|
|
91
|
+
branches;
|
|
92
|
+
expression;
|
|
47
93
|
constructor(kind, identifier, branches, expression) {
|
|
48
94
|
super();
|
|
49
95
|
this.kind = kind;
|
|
@@ -53,6 +99,12 @@ var ChoiceMessage = class extends Base {
|
|
|
53
99
|
}
|
|
54
100
|
};
|
|
55
101
|
var CompositeMessage = class extends Base {
|
|
102
|
+
descriptor;
|
|
103
|
+
comments;
|
|
104
|
+
references;
|
|
105
|
+
children;
|
|
106
|
+
accessor;
|
|
107
|
+
whitespace;
|
|
56
108
|
constructor(descriptor, comments, references, children, accessor, whitespace) {
|
|
57
109
|
super();
|
|
58
110
|
this.descriptor = descriptor;
|
|
@@ -71,6 +123,7 @@ function convertMessageToIcu(message) {
|
|
|
71
123
|
case message instanceof LiteralMessage: return String(message.text);
|
|
72
124
|
case message instanceof ArgumentMessage: return `{${String(message.identifier)}}`;
|
|
73
125
|
case message instanceof ElementMessage: {
|
|
126
|
+
if (message.children.length === 0) return `<${String(message.identifier)}/>`;
|
|
74
127
|
const children = message.children.map((m) => internalConvertMessageToIcu(m)).join("");
|
|
75
128
|
return `<${String(message.identifier)}>${children}</${String(message.identifier)}>`;
|
|
76
129
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
3
24
|
let picomatch = require("picomatch");
|
|
4
|
-
picomatch =
|
|
25
|
+
picomatch = __toESM(picomatch, 1);
|
|
5
26
|
let zod = require("zod");
|
|
6
|
-
zod =
|
|
27
|
+
zod = __toESM(zod, 1);
|
|
7
28
|
zod.object({
|
|
8
29
|
message: zod.string(),
|
|
9
30
|
translation: zod.string().optional(),
|
|
@@ -22,6 +43,16 @@ const Transformer = zod.object({
|
|
|
22
43
|
extract: zod.custom((v) => typeof v === "function"),
|
|
23
44
|
transform: zod.custom((v) => typeof v === "function")
|
|
24
45
|
});
|
|
46
|
+
/**
|
|
47
|
+
* A message declared in the config rather than found in source. The shorthand
|
|
48
|
+
* is the source string; the object form adds the metadata a descriptor would
|
|
49
|
+
* otherwise carry.
|
|
50
|
+
*/
|
|
51
|
+
const DeclaredMessage = zod.string().or(zod.object({
|
|
52
|
+
message: zod.string(),
|
|
53
|
+
context: zod.string().optional(),
|
|
54
|
+
comments: zod.string().array().optional()
|
|
55
|
+
}));
|
|
25
56
|
const Bucket = zod.object({
|
|
26
57
|
include: zod.string().array(),
|
|
27
58
|
exclude: zod.string().array().optional(),
|
|
@@ -31,6 +62,14 @@ const Bucket = zod.object({
|
|
|
31
62
|
zod.string(),
|
|
32
63
|
".{extension}"
|
|
33
64
|
]),
|
|
65
|
+
/**
|
|
66
|
+
* Messages that belong in the catalogue but have no call site to extract
|
|
67
|
+
* them from — strings owned by a non-JavaScript artefact such as a manifest,
|
|
68
|
+
* a store listing, or an email subject. Keyed by id, so the id is stable and
|
|
69
|
+
* hand-written by definition, and merged into every extraction alongside
|
|
70
|
+
* whatever the transformers find.
|
|
71
|
+
*/
|
|
72
|
+
messages: zod.record(zod.string(), DeclaredMessage).optional(),
|
|
34
73
|
formatter: Formatter,
|
|
35
74
|
transformer: Transformer.transform((t) => [t]).or(Transformer.array()).transform((t) => ({
|
|
36
75
|
match: (id) => t.some((t) => t.match(id)),
|
|
@@ -39,6 +78,17 @@ const Bucket = zod.object({
|
|
|
39
78
|
}))
|
|
40
79
|
}).transform((v) => ({
|
|
41
80
|
...v,
|
|
81
|
+
messages: Object.entries(v.messages ?? {}).map(([id, declared]) => {
|
|
82
|
+
const entry = typeof declared === "string" ? { message: declared } : declared;
|
|
83
|
+
return {
|
|
84
|
+
id,
|
|
85
|
+
message: entry.message,
|
|
86
|
+
translation: entry.message,
|
|
87
|
+
context: "context" in entry ? entry.context : void 0,
|
|
88
|
+
comments: ("comments" in entry ? entry.comments : void 0) ?? [],
|
|
89
|
+
references: []
|
|
90
|
+
};
|
|
91
|
+
}),
|
|
42
92
|
match: (0, picomatch.default)(v.include, { ignore: v.exclude }),
|
|
43
93
|
output: Object.assign(v.output, { match: (0, picomatch.default)(v.output.replace("{locale}", "*").replace("{extension}", v.formatter.extension.slice(1))) })
|
|
44
94
|
}));
|
package/dist/index.d.cts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as Message, i as Formatter, n as Config, o as Transformer, r as DeclaredMessage, t as Bucket } from "./shapes-CRlXtss0.cjs";
|
|
2
2
|
import { input } from "zod";
|
|
3
|
-
import * as _$picomatch_lib_picomatch_js0 from "picomatch/lib/picomatch.js";
|
|
4
|
-
|
|
5
3
|
//#region src/index.d.ts
|
|
6
4
|
declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
7
5
|
locales: [string, ...string[]];
|
|
8
6
|
buckets: {
|
|
7
|
+
messages: {
|
|
8
|
+
message: string;
|
|
9
|
+
comments: string[];
|
|
10
|
+
references: string[];
|
|
11
|
+
translation?: string | undefined;
|
|
12
|
+
id?: string | undefined;
|
|
13
|
+
context?: string | undefined;
|
|
14
|
+
}[];
|
|
9
15
|
match: (id: string) => boolean;
|
|
10
16
|
output: `${string}{locale}${string}.{extension}` & {
|
|
11
|
-
match:
|
|
17
|
+
match: import("picomatch/lib/picomatch.js").Matcher;
|
|
12
18
|
};
|
|
13
19
|
include: string[];
|
|
14
20
|
formatter: {
|
|
@@ -36,4 +42,4 @@ declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
|
36
42
|
fallbackLocales?: Record<string, string | string[]> | undefined;
|
|
37
43
|
};
|
|
38
44
|
//#endregion
|
|
39
|
-
export { Bucket, Config, Formatter, Message, Transformer, defineConfig };
|
|
45
|
+
export { type Bucket, type Config, type DeclaredMessage, type Formatter, type Message, type Transformer, defineConfig };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as Message, i as Formatter, n as Config, o as Transformer, r as DeclaredMessage, t as Bucket } from "./shapes-CRlXtss0.mjs";
|
|
2
2
|
import { input } from "zod";
|
|
3
|
-
import * as _$picomatch_lib_picomatch_js0 from "picomatch/lib/picomatch.js";
|
|
4
|
-
|
|
5
3
|
//#region src/index.d.ts
|
|
6
4
|
declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
7
5
|
locales: [string, ...string[]];
|
|
8
6
|
buckets: {
|
|
7
|
+
messages: {
|
|
8
|
+
message: string;
|
|
9
|
+
comments: string[];
|
|
10
|
+
references: string[];
|
|
11
|
+
translation?: string | undefined;
|
|
12
|
+
id?: string | undefined;
|
|
13
|
+
context?: string | undefined;
|
|
14
|
+
}[];
|
|
9
15
|
match: (id: string) => boolean;
|
|
10
16
|
output: `${string}{locale}${string}.{extension}` & {
|
|
11
|
-
match:
|
|
17
|
+
match: import("picomatch/lib/picomatch.js").Matcher;
|
|
12
18
|
};
|
|
13
19
|
include: string[];
|
|
14
20
|
formatter: {
|
|
@@ -36,4 +42,4 @@ declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
|
36
42
|
fallbackLocales?: Record<string, string | string[]> | undefined;
|
|
37
43
|
};
|
|
38
44
|
//#endregion
|
|
39
|
-
export { Bucket, Config, Formatter, Message, Transformer, defineConfig };
|
|
45
|
+
export { type Bucket, type Config, type DeclaredMessage, type Formatter, type Message, type Transformer, defineConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -18,6 +18,16 @@ const Transformer = z.object({
|
|
|
18
18
|
extract: z.custom((v) => typeof v === "function"),
|
|
19
19
|
transform: z.custom((v) => typeof v === "function")
|
|
20
20
|
});
|
|
21
|
+
/**
|
|
22
|
+
* A message declared in the config rather than found in source. The shorthand
|
|
23
|
+
* is the source string; the object form adds the metadata a descriptor would
|
|
24
|
+
* otherwise carry.
|
|
25
|
+
*/
|
|
26
|
+
const DeclaredMessage = z.string().or(z.object({
|
|
27
|
+
message: z.string(),
|
|
28
|
+
context: z.string().optional(),
|
|
29
|
+
comments: z.string().array().optional()
|
|
30
|
+
}));
|
|
21
31
|
const Bucket = z.object({
|
|
22
32
|
include: z.string().array(),
|
|
23
33
|
exclude: z.string().array().optional(),
|
|
@@ -27,6 +37,14 @@ const Bucket = z.object({
|
|
|
27
37
|
z.string(),
|
|
28
38
|
".{extension}"
|
|
29
39
|
]),
|
|
40
|
+
/**
|
|
41
|
+
* Messages that belong in the catalogue but have no call site to extract
|
|
42
|
+
* them from — strings owned by a non-JavaScript artefact such as a manifest,
|
|
43
|
+
* a store listing, or an email subject. Keyed by id, so the id is stable and
|
|
44
|
+
* hand-written by definition, and merged into every extraction alongside
|
|
45
|
+
* whatever the transformers find.
|
|
46
|
+
*/
|
|
47
|
+
messages: z.record(z.string(), DeclaredMessage).optional(),
|
|
30
48
|
formatter: Formatter,
|
|
31
49
|
transformer: Transformer.transform((t) => [t]).or(Transformer.array()).transform((t) => ({
|
|
32
50
|
match: (id) => t.some((t) => t.match(id)),
|
|
@@ -35,6 +53,17 @@ const Bucket = z.object({
|
|
|
35
53
|
}))
|
|
36
54
|
}).transform((v) => ({
|
|
37
55
|
...v,
|
|
56
|
+
messages: Object.entries(v.messages ?? {}).map(([id, declared]) => {
|
|
57
|
+
const entry = typeof declared === "string" ? { message: declared } : declared;
|
|
58
|
+
return {
|
|
59
|
+
id,
|
|
60
|
+
message: entry.message,
|
|
61
|
+
translation: entry.message,
|
|
62
|
+
context: "context" in entry ? entry.context : void 0,
|
|
63
|
+
comments: ("comments" in entry ? entry.comments : void 0) ?? [],
|
|
64
|
+
references: []
|
|
65
|
+
};
|
|
66
|
+
}),
|
|
38
67
|
match: picomatch(v.include, { ignore: v.exclude }),
|
|
39
68
|
output: Object.assign(v.output, { match: picomatch(v.output.replace("{locale}", "*").replace("{extension}", v.formatter.extension.slice(1))) })
|
|
40
69
|
}));
|