@x18n/builtins 0.0.13 → 0.0.14
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/angular-templates-DqIOGfzT.mjs +8 -0
- package/dist/extractors.mjs +7 -3
- package/dist/finders.d.mts +4 -1
- package/dist/finders.mjs +1 -1
- package/dist/formats/ecmascript.d.mts +5 -0
- package/dist/formats/ecmascript.mjs +211 -0
- package/dist/formats/ftl.d.mts +5 -0
- package/dist/formats/ftl.mjs +234 -0
- package/dist/formats/ini.d.mts +5 -0
- package/dist/formats/ini.mjs +158 -0
- package/dist/formats/json.d.mts +6 -0
- package/dist/formats/json.mjs +10 -0
- package/dist/formats/json5.d.mts +5 -0
- package/dist/formats/json5.mjs +30 -0
- package/dist/formats/jsonc.d.mts +6 -0
- package/dist/formats/jsonc.mjs +10 -0
- package/dist/formats/php.d.mts +5 -0
- package/dist/formats/php.mjs +200 -0
- package/dist/formats/po.d.mts +5 -0
- package/dist/formats/po.mjs +177 -0
- package/dist/formats/properties.d.mts +5 -0
- package/dist/formats/properties.mjs +123 -0
- package/dist/formats/resx.d.mts +6 -0
- package/dist/formats/resx.mjs +202 -0
- package/dist/formats/yaml.d.mts +5 -0
- package/dist/formats/yaml.mjs +113 -0
- package/dist/formats.d.mts +10 -34
- package/dist/formats.mjs +61 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +28 -22
- package/dist/{vue-CF4pe-Yr.mjs → js-CV-ECNJG.mjs} +67 -222
- package/dist/json-CyjI8bjp.d.mts +8 -0
- package/dist/json-Db-8qSbE.mjs +73 -0
- package/dist/jsx-templates-B1J0no3i.mjs +17 -0
- package/dist/locale-root-C_rch3IQ.mjs +15 -0
- package/dist/manifests.d.mts +8 -0
- package/dist/manifests.mjs +66 -2
- package/dist/placeholders.d.mts +11 -0
- package/dist/placeholders.mjs +28 -1
- package/dist/plugin-Cb1b0axD.mjs +83 -0
- package/dist/plural-forms-B7_QX4nG.mjs +12 -0
- package/dist/presets/cargo-i18n.d.mts +6 -0
- package/dist/presets/cargo-i18n.mjs +28 -0
- package/dist/presets/chrome-extension.d.mts +6 -0
- package/dist/presets/chrome-extension.mjs +52 -0
- package/dist/presets/dotnet-resx.d.mts +6 -0
- package/dist/presets/dotnet-resx.mjs +64 -0
- package/dist/presets/easy-localization.d.mts +6 -0
- package/dist/presets/easy-localization.mjs +36 -0
- package/dist/presets/ember-intl.d.mts +5 -0
- package/dist/presets/ember-intl.mjs +31 -0
- package/dist/presets/fluent-react.d.mts +5 -0
- package/dist/presets/fluent-react.mjs +46 -0
- package/dist/presets/fluent-vue.d.mts +5 -0
- package/dist/presets/fluent-vue.mjs +51 -0
- package/dist/presets/flutter-translate.d.mts +6 -0
- package/dist/presets/flutter-translate.mjs +30 -0
- package/dist/presets/flutter.d.mts +6 -0
- package/dist/presets/flutter.mjs +21 -0
- package/dist/presets/general.d.mts +6 -0
- package/dist/presets/general.mjs +17 -0
- package/dist/presets/globalize.d.mts +5 -0
- package/dist/presets/globalize.mjs +25 -0
- package/dist/presets/gravity-ui-i18n.d.mts +6 -0
- package/dist/presets/gravity-ui-i18n.mjs +41 -0
- package/dist/presets/i18n-js.d.mts +5 -0
- package/dist/presets/i18n-js.mjs +19 -0
- package/dist/presets/i18n-tag.d.mts +5 -0
- package/dist/presets/i18n-tag.mjs +21 -0
- package/dist/presets/i18next-shopify.d.mts +6 -0
- package/dist/presets/i18next-shopify.mjs +23 -0
- package/dist/presets/i18next.d.mts +5 -0
- package/dist/presets/i18next.mjs +10 -0
- package/dist/presets/i18nice.d.mts +6 -0
- package/dist/presets/i18nice.mjs +29 -0
- package/dist/presets/jekyll.d.mts +5 -0
- package/dist/presets/jekyll.mjs +23 -0
- package/dist/presets/laravel-vue-i18n.d.mts +6 -0
- package/dist/presets/laravel-vue-i18n.mjs +54 -0
- package/dist/presets/laravel.d.mts +6 -0
- package/dist/presets/laravel.mjs +23 -0
- package/dist/presets/lingui.d.mts +5 -0
- package/dist/presets/lingui.mjs +61 -0
- package/dist/presets/next-international.d.mts +5 -0
- package/dist/presets/next-international.mjs +27 -0
- package/dist/presets/next-intl.d.mts +5 -0
- package/dist/presets/next-intl.mjs +55 -0
- package/dist/presets/next-translate.d.mts +5 -0
- package/dist/presets/next-translate.mjs +53 -0
- package/dist/presets/ngx-translate.d.mts +5 -0
- package/dist/presets/ngx-translate.mjs +41 -0
- package/dist/presets/nuxt-i18n-micro.d.mts +5 -0
- package/dist/presets/nuxt-i18n-micro.mjs +81 -0
- package/dist/presets/nuxt-i18n.d.mts +5 -0
- package/dist/presets/nuxt-i18n.mjs +23 -0
- package/dist/presets/paraglide.d.mts +5 -0
- package/dist/presets/paraglide.mjs +38 -0
- package/dist/presets/php-gettext.d.mts +6 -0
- package/dist/presets/php-gettext.mjs +27 -0
- package/dist/presets/php-joomla.d.mts +6 -0
- package/dist/presets/php-joomla.mjs +22 -0
- package/dist/presets/polyglot.d.mts +5 -0
- package/dist/presets/polyglot.mjs +23 -0
- package/dist/presets/python-gettext.d.mts +6 -0
- package/dist/presets/python-gettext.mjs +44 -0
- package/dist/presets/react-i18next.d.mts +5 -0
- package/dist/presets/react-i18next.mjs +67 -0
- package/dist/presets/react-intl.d.mts +5 -0
- package/dist/presets/react-intl.mjs +47 -0
- package/dist/presets/ruby-rails.d.mts +7 -0
- package/dist/presets/ruby-rails.mjs +44 -0
- package/dist/presets/solid-primitives-i18n.d.mts +5 -0
- package/dist/presets/solid-primitives-i18n.mjs +29 -0
- package/dist/presets/svelte-i18n.d.mts +5 -0
- package/dist/presets/svelte-i18n.mjs +33 -0
- package/dist/presets/svelte-i18next.d.mts +5 -0
- package/dist/presets/svelte-i18next.mjs +27 -0
- package/dist/presets/transloco.d.mts +5 -0
- package/dist/presets/transloco.mjs +44 -0
- package/dist/presets/typesafe-i18n.d.mts +6 -0
- package/dist/presets/typesafe-i18n.mjs +61 -0
- package/dist/presets/ui5.d.mts +5 -0
- package/dist/presets/ui5.mjs +35 -0
- package/dist/presets/vscode-extension.d.mts +5 -0
- package/dist/presets/vscode-extension.mjs +53 -0
- package/dist/presets/vue-i18n.d.mts +5 -0
- package/dist/presets/vue-i18n.mjs +59 -0
- package/dist/presets.d.mts +7 -54
- package/dist/presets.mjs +346 -1
- package/dist/reporters/github.d.mts +6 -0
- package/dist/reporters/github.mjs +27 -0
- package/dist/reporters/json.d.mts +6 -0
- package/dist/reporters/json.mjs +24 -0
- package/dist/reporters/markdown.d.mts +6 -0
- package/dist/reporters/markdown.mjs +37 -0
- package/dist/reporters/pretty.d.mts +6 -0
- package/dist/reporters/pretty.mjs +64 -0
- package/dist/reporters/sarif.d.mts +6 -0
- package/dist/reporters/sarif.mjs +48 -0
- package/dist/reporters.d.mts +5 -12
- package/dist/reporters.mjs +8 -218
- package/dist/scanners/astro.d.mts +6 -0
- package/dist/scanners/astro.mjs +256 -0
- package/dist/scanners/js.d.mts +6 -0
- package/dist/scanners/js.mjs +33 -0
- package/dist/scanners/regex-scopes.d.mts +14 -0
- package/dist/scanners/regex-scopes.mjs +41 -0
- package/dist/scanners/regex.d.mts +9 -0
- package/dist/{regex-AYVhuSb6.mjs → scanners/regex.mjs} +2 -40
- package/dist/scanners/svelte.d.mts +6 -0
- package/dist/{scanners-DhnnVp7s.mjs → scanners/svelte.mjs} +3 -3
- package/dist/scanners/vue.d.mts +6 -0
- package/dist/scanners/vue.mjs +172 -0
- package/dist/scanners.d.mts +9 -50
- package/dist/scanners.mjs +36 -4
- package/dist/sfc-blocks-DaGKDZsb.mjs +213 -0
- package/dist/shared-BWaXUmwA.mjs +70 -0
- package/dist/shared-D-tbsYmc.mjs +30 -0
- package/dist/shared-D4NJBKEP.mjs +17 -0
- package/dist/shared-Tq06G0gp.mjs +6 -0
- package/dist/shared-meYeVckh.mjs +11 -0
- package/dist/vue-compiler-0sfLIiiL.mjs +8 -0
- package/package.json +67 -3
- package/dist/formats-CFkM5co0.mjs +0 -1370
- package/dist/presets-Co5SlnKr.mjs +0 -1187
- package/dist/sfc-blocks-BqQ8m9rX.mjs +0 -161
- package/dist/yaml-plugin.d.mts +0 -8
- package/dist/yaml-plugin.mjs +0 -68
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { a as splice, i as leafText, n as detectEol } from "../shared-BWaXUmwA.mjs";
|
|
2
|
+
import { diffText, errors, pathId, walkLeaves } from "@x18n/core";
|
|
3
|
+
//#region src/formats/resx/index.ts
|
|
4
|
+
const entities = {
|
|
5
|
+
lt: "<",
|
|
6
|
+
gt: ">",
|
|
7
|
+
amp: "&",
|
|
8
|
+
quot: "\"",
|
|
9
|
+
apos: "'"
|
|
10
|
+
};
|
|
11
|
+
function decode(raw) {
|
|
12
|
+
return raw.replace(/\r\n?/g, "\n").replace(/<!\[CDATA\[([\s\S]*?)\]\]>|&(#x[\da-f]+|#\d+|\w+);/gi, (match, cdata, name) => {
|
|
13
|
+
if (name === void 0) return cdata ?? match;
|
|
14
|
+
if (name.startsWith("#")) {
|
|
15
|
+
const code = name[1] === "x" ? Number.parseInt(name.slice(2), 16) : Number.parseInt(name.slice(1), 10);
|
|
16
|
+
return code <= 1114111 ? String.fromCodePoint(code) : match;
|
|
17
|
+
}
|
|
18
|
+
return entities[name] ?? match;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const escapeText = (text) => text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
22
|
+
const escapeAttribute = (text) => escapeText(text).replace(/"/g, """);
|
|
23
|
+
const isSpace = (char) => char === " " || char === " ";
|
|
24
|
+
/** The range with its indent and line break when it stands on a line of its own. */
|
|
25
|
+
function lineOf(text, range) {
|
|
26
|
+
let start = range.start;
|
|
27
|
+
while (isSpace(text[start - 1])) start--;
|
|
28
|
+
let end = range.end;
|
|
29
|
+
while (isSpace(text[end])) end++;
|
|
30
|
+
if (text[end] === "\r") end++;
|
|
31
|
+
if (text[end] === "\n") end++;
|
|
32
|
+
return (start === 0 || text[start - 1] === "\n") && (end === text.length || text[end - 1] === "\n") ? {
|
|
33
|
+
start,
|
|
34
|
+
end
|
|
35
|
+
} : range;
|
|
36
|
+
}
|
|
37
|
+
/** Comments and CDATA are skipped so the schema sample in the standard header is not read as data. */
|
|
38
|
+
const tokens = /<!--[\s\S]*?-->|<!\[CDATA\[[\s\S]*?\]\]>|<data\b((?:[^>"']|"[^"]*"|'[^']*')*)>/g;
|
|
39
|
+
/** The `<value>` inside a `<data>` whose content starts at `offset`. */
|
|
40
|
+
function valueIn(inner, offset) {
|
|
41
|
+
const match = /<value\s*\/>|<value\s*>([\s\S]*?)<\/value\s*>/d.exec(inner);
|
|
42
|
+
if (!match) return {
|
|
43
|
+
value: "",
|
|
44
|
+
body: void 0,
|
|
45
|
+
emptyValue: void 0
|
|
46
|
+
};
|
|
47
|
+
const [start, end] = match.indices[0];
|
|
48
|
+
const body = match.indices[1];
|
|
49
|
+
if (!body) return {
|
|
50
|
+
value: "",
|
|
51
|
+
body: void 0,
|
|
52
|
+
emptyValue: {
|
|
53
|
+
start: offset + start,
|
|
54
|
+
end: offset + end
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
value: decode(match[1]),
|
|
59
|
+
body: {
|
|
60
|
+
start: offset + body[0],
|
|
61
|
+
end: offset + body[1]
|
|
62
|
+
},
|
|
63
|
+
emptyValue: void 0
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function read(text, path) {
|
|
67
|
+
const entries = [];
|
|
68
|
+
const objects = /* @__PURE__ */ new Set();
|
|
69
|
+
const closing = /<\/data\s*>/g;
|
|
70
|
+
tokens.lastIndex = 0;
|
|
71
|
+
for (let match = tokens.exec(text); match; match = tokens.exec(text)) {
|
|
72
|
+
const attributes = match[1];
|
|
73
|
+
if (attributes === void 0) continue;
|
|
74
|
+
const start = match.index;
|
|
75
|
+
const open = start + match[0].length;
|
|
76
|
+
const selfClosing = attributes.endsWith("/");
|
|
77
|
+
closing.lastIndex = open;
|
|
78
|
+
const close = selfClosing ? void 0 : closing.exec(text);
|
|
79
|
+
if (close === null) throw errors.X18N2002({
|
|
80
|
+
path,
|
|
81
|
+
reason: "unclosed <data> element"
|
|
82
|
+
});
|
|
83
|
+
const end = close ? close.index + close[0].length : open;
|
|
84
|
+
tokens.lastIndex = end;
|
|
85
|
+
const name = /\sname\s*=\s*(?:"([^"]*)"|'([^']*)')/d.exec(attributes);
|
|
86
|
+
if (!name) continue;
|
|
87
|
+
const key = decode(name[1] ?? name[2]);
|
|
88
|
+
if (/\s(?:type|mimetype)\s*=/.test(attributes)) {
|
|
89
|
+
objects.add(key);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const nameAt = name.indices[1] ?? name.indices[2];
|
|
93
|
+
const inner = close ? text.slice(open, close.index) : "";
|
|
94
|
+
const { value, body, emptyValue } = valueIn(inner, open);
|
|
95
|
+
const line = lineOf(text, {
|
|
96
|
+
start,
|
|
97
|
+
end
|
|
98
|
+
});
|
|
99
|
+
const keyOffset = start + 5;
|
|
100
|
+
entries.push({
|
|
101
|
+
key,
|
|
102
|
+
value,
|
|
103
|
+
range: {
|
|
104
|
+
key: {
|
|
105
|
+
start: keyOffset + nameAt[0],
|
|
106
|
+
end: keyOffset + nameAt[1]
|
|
107
|
+
},
|
|
108
|
+
value: body ?? emptyValue ?? {
|
|
109
|
+
start: open,
|
|
110
|
+
end: open
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
body,
|
|
114
|
+
emptyValue,
|
|
115
|
+
content: close && inner.trim() ? {
|
|
116
|
+
start: open,
|
|
117
|
+
end: close.index
|
|
118
|
+
} : void 0,
|
|
119
|
+
element: {
|
|
120
|
+
start,
|
|
121
|
+
end
|
|
122
|
+
},
|
|
123
|
+
line,
|
|
124
|
+
indent: line.start < start ? text.slice(line.start, start) : ""
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
entries,
|
|
129
|
+
objects
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function dataElement(key, value, indent, eol) {
|
|
133
|
+
return `<data name="${escapeAttribute(key)}" xml:space="preserve">${eol}${indent.repeat(2)}<value>${value}</value>${eol}${indent}</data>`;
|
|
134
|
+
}
|
|
135
|
+
function applyOp(text, op, path) {
|
|
136
|
+
const key = op.path.join(".");
|
|
137
|
+
const { entries, objects } = read(text, path);
|
|
138
|
+
const entry = entries.findLast((e) => e.key === key);
|
|
139
|
+
if (op.type === "delete") return entry ? splice(text, entry.line, "") : text;
|
|
140
|
+
if (!entry && objects.has(key)) throw errors.X18N4008({ reason: `"${key}" in ${path} holds a file or object, not a string` });
|
|
141
|
+
const eol = detectEol(text);
|
|
142
|
+
const value = escapeText(leafText(op.value)).replace(/\n/g, eol);
|
|
143
|
+
if (entry?.body) return splice(text, entry.body, value);
|
|
144
|
+
if (entry?.emptyValue) return splice(text, entry.emptyValue, `<value>${value}</value>`);
|
|
145
|
+
if (entry?.content) {
|
|
146
|
+
const lead = /^\s*/.exec(text.slice(entry.content.start, entry.content.end))[0];
|
|
147
|
+
return splice(text, {
|
|
148
|
+
start: entry.content.start,
|
|
149
|
+
end: entry.content.start
|
|
150
|
+
}, `${lead}<value>${value}</value>`);
|
|
151
|
+
}
|
|
152
|
+
if (entry) return splice(text, entry.element, dataElement(key, value, entry.indent, eol));
|
|
153
|
+
const root = text.lastIndexOf("</root>");
|
|
154
|
+
if (root === -1) throw errors.X18N2002({
|
|
155
|
+
path,
|
|
156
|
+
reason: "missing </root>"
|
|
157
|
+
});
|
|
158
|
+
const indent = entries.at(-1)?.indent ?? [...text.matchAll(/^([ \t]*)<resheader\b/gm)].at(-1)?.[1] ?? " ";
|
|
159
|
+
let at = root;
|
|
160
|
+
while (isSpace(text[at - 1])) at--;
|
|
161
|
+
const lead = at === 0 || text[at - 1] === "\n" ? "" : eol;
|
|
162
|
+
return splice(text, {
|
|
163
|
+
start: at,
|
|
164
|
+
end: at
|
|
165
|
+
}, `${lead}${indent}${dataElement(key, value, indent, eol)}${eol}`);
|
|
166
|
+
}
|
|
167
|
+
const head = `<?xml version="1.0" encoding="utf-8"?>\n<root>\n${[
|
|
168
|
+
["resmimetype", "text/microsoft-resx"],
|
|
169
|
+
["version", "2.0"],
|
|
170
|
+
["reader", "System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"],
|
|
171
|
+
["writer", "System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"]
|
|
172
|
+
].map(([name, value]) => ` <resheader name="${name}">\n <value>${value}</value>\n </resheader>\n`).join("")}`;
|
|
173
|
+
/** .NET `.resx` files: `<data name="key"><value>text</value></data>` inside `<root>`. */
|
|
174
|
+
function resx() {
|
|
175
|
+
return {
|
|
176
|
+
name: "x18n:format-resx",
|
|
177
|
+
formats: [{
|
|
178
|
+
id: "resx",
|
|
179
|
+
extensions: ["resx"],
|
|
180
|
+
parse(text, ctx) {
|
|
181
|
+
const tree = {};
|
|
182
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
183
|
+
for (const entry of read(text, ctx.path).entries) {
|
|
184
|
+
tree[entry.key] = entry.value;
|
|
185
|
+
ranges.set(pathId([entry.key]), entry.range);
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
tree,
|
|
189
|
+
ranges
|
|
190
|
+
};
|
|
191
|
+
},
|
|
192
|
+
edit(text, ops, ctx) {
|
|
193
|
+
let next = text;
|
|
194
|
+
for (const op of ops) next = applyOp(next, op, ctx.path);
|
|
195
|
+
return diffText(text, next);
|
|
196
|
+
},
|
|
197
|
+
serialize: (tree) => `${head}${[...walkLeaves(tree)].map((leaf) => ` ${dataElement(leaf.path.join("."), escapeText(leafText(leaf.value)), " ", "\n")}\n`).join("")}</root>\n`
|
|
198
|
+
}]
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
export { resx as default, resx };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { s as toLeaf } from "../shared-BWaXUmwA.mjs";
|
|
2
|
+
import { applyTextEdits, diffText, errors, pathId } from "@x18n/core";
|
|
3
|
+
import { Document, Scalar, isMap, isNode, isScalar, parseDocument, stringify } from "yaml";
|
|
4
|
+
//#region src/formats/yaml/index.ts
|
|
5
|
+
function scalarTextRange(node) {
|
|
6
|
+
const range = node.range;
|
|
7
|
+
if (!range) return void 0;
|
|
8
|
+
if (isScalar(node) && (node.type === Scalar.QUOTE_DOUBLE || node.type === Scalar.QUOTE_SINGLE)) return {
|
|
9
|
+
start: range[0] + 1,
|
|
10
|
+
end: range[1] - 1
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
start: range[0],
|
|
14
|
+
end: range[1]
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function readMap(node, path, ranges) {
|
|
18
|
+
const out = {};
|
|
19
|
+
if (!isMap(node)) return out;
|
|
20
|
+
for (const pair of node.items) {
|
|
21
|
+
const keyNode = pair.key;
|
|
22
|
+
if (!isScalar(keyNode)) continue;
|
|
23
|
+
const key = String(keyNode.value);
|
|
24
|
+
const childPath = [...path, key];
|
|
25
|
+
const keyRange = scalarTextRange(keyNode);
|
|
26
|
+
const value = isNode(pair.value) ? pair.value : void 0;
|
|
27
|
+
const valueRange = value && value.range ? {
|
|
28
|
+
start: value.range[0],
|
|
29
|
+
end: value.range[1]
|
|
30
|
+
} : void 0;
|
|
31
|
+
if (keyRange) ranges.set(pathId(childPath), {
|
|
32
|
+
key: keyRange,
|
|
33
|
+
value: valueRange ?? keyRange
|
|
34
|
+
});
|
|
35
|
+
if (value === void 0) out[key] = null;
|
|
36
|
+
else if (isMap(value)) out[key] = readMap(value, childPath, ranges);
|
|
37
|
+
else if (isScalar(value)) {
|
|
38
|
+
const leaf = toLeaf(value.value);
|
|
39
|
+
if (leaf !== void 0) out[key] = leaf;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
function parse$1(text, path) {
|
|
45
|
+
const doc = parseDocument(text, {
|
|
46
|
+
keepSourceTokens: true,
|
|
47
|
+
uniqueKeys: false
|
|
48
|
+
});
|
|
49
|
+
if (doc.errors.length > 0) throw errors.X18N2002({
|
|
50
|
+
path,
|
|
51
|
+
reason: doc.errors[0].message
|
|
52
|
+
});
|
|
53
|
+
return doc;
|
|
54
|
+
}
|
|
55
|
+
function scalarText(value, type) {
|
|
56
|
+
if (typeof value !== "string") return stringify(value).trimEnd();
|
|
57
|
+
if (type === Scalar.QUOTE_DOUBLE) return JSON.stringify(value);
|
|
58
|
+
if (type === Scalar.QUOTE_SINGLE) return `'${value.replace(/'/g, "''")}'`;
|
|
59
|
+
return stringify(value, { lineWidth: 0 }).trimEnd();
|
|
60
|
+
}
|
|
61
|
+
function indentOf(text) {
|
|
62
|
+
return /^( +)\S/m.exec(text)?.[1]?.length ?? 2;
|
|
63
|
+
}
|
|
64
|
+
function yaml() {
|
|
65
|
+
return {
|
|
66
|
+
name: "x18n:format-yaml",
|
|
67
|
+
formats: [{
|
|
68
|
+
id: "yaml",
|
|
69
|
+
extensions: ["yml", "yaml"],
|
|
70
|
+
parse(text, ctx) {
|
|
71
|
+
const doc = parse$1(text, ctx.path);
|
|
72
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
73
|
+
if (doc.contents === null) return {
|
|
74
|
+
tree: {},
|
|
75
|
+
ranges
|
|
76
|
+
};
|
|
77
|
+
if (!isMap(doc.contents)) throw errors.X18N2003({ path: ctx.path });
|
|
78
|
+
return {
|
|
79
|
+
tree: readMap(doc.contents, [], ranges),
|
|
80
|
+
ranges
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
edit(text, ops, ctx) {
|
|
84
|
+
let next = text;
|
|
85
|
+
for (const op of ops) {
|
|
86
|
+
let doc = parse$1(next, ctx.path);
|
|
87
|
+
const current = doc.getIn(op.path, true);
|
|
88
|
+
if (op.type === "set" && isScalar(current) && current.range && current.type !== Scalar.BLOCK_FOLDED && current.type !== Scalar.BLOCK_LITERAL) {
|
|
89
|
+
next = applyTextEdits(next, [{
|
|
90
|
+
range: {
|
|
91
|
+
start: current.range[0],
|
|
92
|
+
end: current.range[1]
|
|
93
|
+
},
|
|
94
|
+
text: scalarText(op.value, current.type)
|
|
95
|
+
}]);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (doc.contents === null) doc = new Document({});
|
|
99
|
+
if (op.type === "set") doc.setIn(op.path, op.value);
|
|
100
|
+
else doc.deleteIn(op.path);
|
|
101
|
+
next = doc.toString({
|
|
102
|
+
indent: indentOf(text),
|
|
103
|
+
lineWidth: 0
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return diffText(text, next);
|
|
107
|
+
},
|
|
108
|
+
serialize: (tree) => Object.keys(tree).length === 0 ? "{}\n" : stringify(tree, { lineWidth: 0 })
|
|
109
|
+
}]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { yaml as default, yaml };
|
package/dist/formats.d.mts
CHANGED
|
@@ -1,34 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region src/formats/
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/formats/json.d.ts
|
|
12
|
-
interface JsonOptions {
|
|
13
|
-
/** Spaces per level for new files. Existing files keep their indent. */
|
|
14
|
-
readonly indent?: number;
|
|
15
|
-
}
|
|
16
|
-
export declare function json(options?: JsonOptions): Plugin;
|
|
17
|
-
export declare function jsonc(options?: JsonOptions): Plugin;
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/formats/json5.d.ts
|
|
20
|
-
export declare function json5(): Plugin;
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/formats/php.d.ts
|
|
23
|
-
export declare function php(): Plugin;
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region src/formats/po.d.ts
|
|
26
|
-
export declare function po(): Plugin;
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/formats/properties.d.ts
|
|
29
|
-
export declare function properties(): Plugin;
|
|
30
|
-
//#endregion
|
|
31
|
-
//#region src/formats/yaml.d.ts
|
|
32
|
-
export declare function yaml(): Plugin;
|
|
33
|
-
//#endregion
|
|
34
|
-
export type { JsonOptions };
|
|
1
|
+
import { FormatEntry } from "@x18n/core";
|
|
2
|
+
//#region src/formats/index.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Built-in formats by id, in claim order. A format is a folder: `<name>/entry.ts` holds its extensions and a
|
|
5
|
+
* `load` for `<name>/index.ts`, the format itself, which is imported when a file of that format is first read.
|
|
6
|
+
*/
|
|
7
|
+
export declare const formats: {
|
|
8
|
+
readonly [id: string]: FormatEntry;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
package/dist/formats.mjs
CHANGED
|
@@ -1 +1,61 @@
|
|
|
1
|
-
|
|
1
|
+
//#endregion
|
|
2
|
+
//#region src/formats/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Built-in formats by id, in claim order. A format is a folder: `<name>/entry.ts` holds its extensions and a
|
|
5
|
+
* `load` for `<name>/index.ts`, the format itself, which is imported when a file of that format is first read.
|
|
6
|
+
*/
|
|
7
|
+
const formats = {
|
|
8
|
+
json: {
|
|
9
|
+
extensions: ["json"],
|
|
10
|
+
load: () => import("./formats/json.mjs")
|
|
11
|
+
},
|
|
12
|
+
jsonc: {
|
|
13
|
+
extensions: ["jsonc"],
|
|
14
|
+
load: () => import("./formats/jsonc.mjs")
|
|
15
|
+
},
|
|
16
|
+
json5: {
|
|
17
|
+
extensions: ["json5"],
|
|
18
|
+
load: () => import("./formats/json5.mjs")
|
|
19
|
+
},
|
|
20
|
+
yaml: {
|
|
21
|
+
extensions: ["yml", "yaml"],
|
|
22
|
+
load: () => import("./formats/yaml.mjs")
|
|
23
|
+
},
|
|
24
|
+
po: {
|
|
25
|
+
extensions: ["po", "pot"],
|
|
26
|
+
load: () => import("./formats/po.mjs")
|
|
27
|
+
},
|
|
28
|
+
properties: {
|
|
29
|
+
extensions: ["properties"],
|
|
30
|
+
load: () => import("./formats/properties.mjs")
|
|
31
|
+
},
|
|
32
|
+
resx: {
|
|
33
|
+
extensions: ["resx"],
|
|
34
|
+
load: () => import("./formats/resx.mjs")
|
|
35
|
+
},
|
|
36
|
+
ftl: {
|
|
37
|
+
extensions: ["ftl"],
|
|
38
|
+
load: () => import("./formats/ftl.mjs")
|
|
39
|
+
},
|
|
40
|
+
ini: {
|
|
41
|
+
extensions: ["ini"],
|
|
42
|
+
load: () => import("./formats/ini.mjs")
|
|
43
|
+
},
|
|
44
|
+
php: {
|
|
45
|
+
extensions: ["php"],
|
|
46
|
+
load: () => import("./formats/php.mjs")
|
|
47
|
+
},
|
|
48
|
+
js: {
|
|
49
|
+
extensions: [
|
|
50
|
+
"js",
|
|
51
|
+
"mjs",
|
|
52
|
+
"cjs",
|
|
53
|
+
"ts",
|
|
54
|
+
"mts",
|
|
55
|
+
"cts"
|
|
56
|
+
],
|
|
57
|
+
load: () => import("./formats/ecmascript.mjs")
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { formats };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Builtins } from "@x18n/core";
|
|
2
2
|
//#region src/index.d.ts
|
|
3
|
-
/** Plugins that are always on, and the presets that `'auto'` detects. */
|
|
4
|
-
export declare function createBuiltins(): Builtins
|
|
3
|
+
/** Plugins that are always on, and the presets that `'auto'` detects. Formats, scanners and presets load on demand; `regex` and the reporters are always loaded. */
|
|
4
|
+
export declare function createBuiltins(): Promise<Builtins>;
|
|
5
5
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
1
1
|
import { recommended } from "./checks.mjs";
|
|
2
2
|
import { i as pattern } from "./finders-CqTGh4OJ.mjs";
|
|
3
|
-
import { a as json5, c as ini, i as php, l as ftl, n as properties, o as json, r as po, s as jsonc, t as yaml, u as ecmascript } from "./formats-CFkM5co0.mjs";
|
|
4
|
-
import { a as js, n as vue } from "./vue-CF4pe-Yr.mjs";
|
|
5
3
|
import { manifests } from "./manifests.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { reporters } from "
|
|
9
|
-
import {
|
|
4
|
+
import { formats } from "@x18n/builtins/formats";
|
|
5
|
+
import { presets } from "@x18n/builtins/presets";
|
|
6
|
+
import { reporters } from "@x18n/builtins/reporters";
|
|
7
|
+
import { scanners } from "@x18n/builtins/scanners";
|
|
8
|
+
import regex from "@x18n/builtins/scanners/regex";
|
|
10
9
|
//#region src/index.ts
|
|
11
|
-
/** Plugins that are always on, and the presets that `'auto'` detects. */
|
|
12
|
-
function createBuiltins() {
|
|
10
|
+
/** Plugins that are always on, and the presets that `'auto'` detects. Formats, scanners and presets load on demand; `regex` and the reporters are always loaded. */
|
|
11
|
+
async function createBuiltins() {
|
|
12
|
+
const formatPlugins = Object.entries(formats).map(([id, entry]) => ({
|
|
13
|
+
name: `x18n:format-${id}`,
|
|
14
|
+
lazyFormats: [{
|
|
15
|
+
id,
|
|
16
|
+
...entry
|
|
17
|
+
}]
|
|
18
|
+
}));
|
|
19
|
+
const scannerPlugins = Object.entries(scanners).map(([id, entry]) => ({
|
|
20
|
+
name: `x18n:scanner-${id}`,
|
|
21
|
+
lazyScanners: [{
|
|
22
|
+
id,
|
|
23
|
+
...entry
|
|
24
|
+
}]
|
|
25
|
+
}));
|
|
26
|
+
const reporterPlugin = {
|
|
27
|
+
name: "x18n:reporters",
|
|
28
|
+
reporters: await Promise.all(Object.values(reporters).map(async (load) => (await load()).default))
|
|
29
|
+
};
|
|
13
30
|
return {
|
|
14
31
|
plugins: [
|
|
15
32
|
manifests(),
|
|
16
|
-
|
|
17
|
-
jsonc(),
|
|
18
|
-
json5(),
|
|
19
|
-
yaml(),
|
|
20
|
-
po(),
|
|
21
|
-
properties(),
|
|
22
|
-
ftl(),
|
|
23
|
-
ini(),
|
|
24
|
-
php(),
|
|
25
|
-
ecmascript(),
|
|
33
|
+
...formatPlugins,
|
|
26
34
|
pattern(),
|
|
27
|
-
|
|
28
|
-
vue(),
|
|
29
|
-
svelte(),
|
|
35
|
+
...scannerPlugins,
|
|
30
36
|
regex(),
|
|
31
37
|
recommended(),
|
|
32
|
-
|
|
38
|
+
reporterPlugin
|
|
33
39
|
],
|
|
34
40
|
presets
|
|
35
41
|
};
|