@x18n/builtins 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ import { r as indentUnit } from "./shared-C7ceptwi.mjs";
2
+ import { t as editLiteral } from "./literal-gIdB1VGy.mjs";
3
+ import { diffText, errors, pathId } from "@x18n/core";
4
+ import { parseTree, printParseErrorCode } from "jsonc-parser";
5
+ //#region src/formats/shared/json.ts
6
+ function readTree(node, path, ranges) {
7
+ const out = {};
8
+ for (const property of node.children ?? []) {
9
+ const [keyNode, valueNode] = property.children ?? [];
10
+ if (!keyNode || !valueNode || typeof keyNode.value !== "string") continue;
11
+ const key = keyNode.value;
12
+ const childPath = [...path, key];
13
+ ranges.set(pathId(childPath), {
14
+ key: {
15
+ start: keyNode.offset + 1,
16
+ end: keyNode.offset + keyNode.length - 1
17
+ },
18
+ value: {
19
+ start: valueNode.offset,
20
+ end: valueNode.offset + valueNode.length
21
+ }
22
+ });
23
+ if (valueNode.type === "object") out[key] = readTree(valueNode, childPath, ranges);
24
+ else if (valueNode.type === "string" || valueNode.type === "number" || valueNode.type === "boolean" || valueNode.type === "null") out[key] = valueNode.value;
25
+ }
26
+ return out;
27
+ }
28
+ function objectOf(node) {
29
+ const items = [];
30
+ for (const property of node.children ?? []) {
31
+ const [keyNode, valueNode] = property.children ?? [];
32
+ if (!keyNode || !valueNode || typeof keyNode.value !== "string") continue;
33
+ items.push({
34
+ key: keyNode.value,
35
+ range: {
36
+ start: property.offset,
37
+ end: property.offset + property.length
38
+ },
39
+ value: valueNode.type === "object" ? objectOf(valueNode) : {
40
+ kind: "scalar",
41
+ range: {
42
+ start: valueNode.offset,
43
+ end: valueNode.offset + valueNode.length
44
+ },
45
+ quote: void 0
46
+ }
47
+ });
48
+ }
49
+ return {
50
+ kind: "object",
51
+ range: {
52
+ start: node.offset,
53
+ end: node.offset + node.length
54
+ },
55
+ items
56
+ };
57
+ }
58
+ /** The root object, or undefined for an empty file. */
59
+ function parseRoot(text, path, allowComments) {
60
+ const problems = [];
61
+ const root = parseTree(text, problems, {
62
+ allowTrailingComma: true,
63
+ disallowComments: !allowComments
64
+ });
65
+ if (problems.length > 0) {
66
+ const first = problems[0];
67
+ throw errors.X18N2002({
68
+ path,
69
+ reason: `${printParseErrorCode(first.error)} at offset ${first.offset}`
70
+ });
71
+ }
72
+ if (root?.type === "object") return root;
73
+ if (text.trim() === "") return void 0;
74
+ throw errors.X18N2003({ path });
75
+ }
76
+ function createJsonFormat(id, extensions, allowComments, defaultIndent) {
77
+ return {
78
+ id,
79
+ extensions,
80
+ parse(text, ctx) {
81
+ const root = parseRoot(text, ctx.path, allowComments);
82
+ const ranges = /* @__PURE__ */ new Map();
83
+ return {
84
+ tree: root ? readTree(root, [], ranges) : {},
85
+ ranges
86
+ };
87
+ },
88
+ edit(text, ops, ctx) {
89
+ const syntax = {
90
+ open: "{",
91
+ close: "}",
92
+ separator: ": ",
93
+ key: (key) => JSON.stringify(key),
94
+ leaf: (value) => JSON.stringify(value),
95
+ unit: indentUnit(text, ctx.indent ?? defaultIndent, " "),
96
+ trailingComma: false
97
+ };
98
+ let next = text.trim() === "" ? "{}\n" : text;
99
+ for (const op of ops) next = editLiteral(next, objectOf(parseRoot(next, ctx.path, allowComments)), op, syntax);
100
+ return diffText(text, next);
101
+ },
102
+ serialize(tree, ctx) {
103
+ const indent = ctx.indent ?? defaultIndent ?? 2;
104
+ return `${JSON.stringify(tree, null, indent === "tab" ? " " : indent)}\n`;
105
+ }
106
+ };
107
+ }
108
+ //#endregion
109
+ export { createJsonFormat as t };
@@ -0,0 +1,125 @@
1
+ import { a as splice, n as detectEol } from "./shared-C7ceptwi.mjs";
2
+ import { isMessageLeaf } from "@x18n/core";
3
+ //#region src/formats/shared/literal.ts
4
+ /** Prints a value at `depth`. Objects span lines, one entry per line. */
5
+ function literalText(value, syntax, depth = 0) {
6
+ if (isMessageLeaf(value)) return syntax.leaf(value, void 0);
7
+ const entries = Object.entries(value);
8
+ if (entries.length === 0) return `${syntax.open}${syntax.close}`;
9
+ const pad = syntax.unit.repeat(depth + 1);
10
+ const lines = entries.map(([key, child]) => `${pad}${syntax.key(key)}${syntax.separator}${literalText(child, syntax, depth + 1)}`);
11
+ return `${syntax.open}\n${lines.join(",\n")}${syntax.trailingComma ? "," : ""}\n${syntax.unit.repeat(depth)}${syntax.close}`;
12
+ }
13
+ /** Applies one op to the text of `root` and leaves everything else as it is: comments, quotes, order and layout. */
14
+ function editLiteral(text, root, op, syntax) {
15
+ const last = root.items.at(-1);
16
+ const style = last ? {
17
+ ...syntax,
18
+ trailingComma: commaAfter(text, last.range.end) !== void 0
19
+ } : syntax;
20
+ let node = root;
21
+ let depth = 0;
22
+ while (depth < op.path.length && node.kind === "object") {
23
+ const object = node;
24
+ const item = object.items.findLast((i) => i.key === op.path[depth]);
25
+ if (!item) break;
26
+ if (op.type === "delete" && depth === op.path.length - 1) return removeItem(text, object, item);
27
+ node = item.value;
28
+ depth++;
29
+ }
30
+ if (op.type === "delete") return text;
31
+ const rest = op.path.slice(depth);
32
+ if (node.kind === "object" && rest.length > 0) return insertItem(text, node, rest, op.value, style);
33
+ const value = nest(rest, op.value);
34
+ return splice(text, node.range, isMessageLeaf(value) ? style.leaf(value, node.kind === "scalar" ? node.quote : void 0) : reindent(literalText(value, style), indentAt(text, node.range.start), detectEol(text)));
35
+ }
36
+ function nest(path, value) {
37
+ return path.reduceRight((child, segment) => ({ [segment]: child }), value);
38
+ }
39
+ function reindent(text, indent, eol) {
40
+ return text.replace(/\n/g, `${eol}${indent}`);
41
+ }
42
+ function lineStart(text, pos) {
43
+ return text.lastIndexOf("\n", pos - 1) + 1;
44
+ }
45
+ function indentAt(text, pos) {
46
+ return /^[ \t]*/.exec(text.slice(lineStart(text, pos)))[0];
47
+ }
48
+ /** The `,` after a value, past blanks and comments. */
49
+ function commaAfter(text, pos) {
50
+ const at = pos + /^(?:\s|\/\/[^\n]*|#[^\n]*|\/\*[\s\S]*?\*\/)*/.exec(text.slice(pos))[0].length;
51
+ return text[at] === "," ? at : void 0;
52
+ }
53
+ /** The end of the line at `pos`, before the line break, when only blanks and a comment follow. */
54
+ function lineEnd(text, pos) {
55
+ const end = pos + /^[ \t]*(?:(?:\/\/|#).*|\/\*.*?\*\/[ \t]*)?/.exec(text.slice(pos))[0].length;
56
+ return end === text.length || text.startsWith("\n", end) || text.startsWith("\r\n", end) ? end : void 0;
57
+ }
58
+ function insertItem(text, object, path, value, syntax) {
59
+ const eol = detectEol(text);
60
+ const entry = (indent) => `${syntax.key(path[0])}${syntax.separator}${reindent(literalText(nest(path.slice(1), value), syntax), indent, eol)}`;
61
+ const first = object.items[0];
62
+ const last = object.items.at(-1);
63
+ if (!first || !last) {
64
+ const base = indentAt(text, object.range.start);
65
+ const indent = base + syntax.unit;
66
+ const close = object.range.end - 1;
67
+ const blank = /\s*$/.exec(text.slice(object.range.start, close))[0].length;
68
+ return splice(text, {
69
+ start: close - blank,
70
+ end: close
71
+ }, `${eol}${indent}${entry(indent)}${syntax.trailingComma ? "," : ""}${eol}${base}`);
72
+ }
73
+ const comma = commaAfter(text, last.range.end);
74
+ const end = comma === void 0 ? last.range.end : comma + 1;
75
+ if (!text.slice(object.range.start, first.range.start).includes("\n")) {
76
+ const indent = indentAt(text, object.range.start);
77
+ return splice(text, {
78
+ start: end,
79
+ end
80
+ }, comma === void 0 ? `, ${entry(indent)}` : ` ${entry(indent)},`);
81
+ }
82
+ const indent = indentAt(text, first.range.start);
83
+ const at = lineEnd(text, end) ?? end;
84
+ const next = splice(text, {
85
+ start: at,
86
+ end: at
87
+ }, `${eol}${indent}${entry(indent)}${comma === void 0 ? "" : ","}`);
88
+ return comma === void 0 ? splice(next, {
89
+ start: end,
90
+ end
91
+ }, ",") : next;
92
+ }
93
+ function removeItem(text, object, item) {
94
+ const comma = commaAfter(text, item.range.end);
95
+ const end = comma === void 0 ? item.range.end : comma + 1;
96
+ const previous = object.items[object.items.indexOf(item) - 1];
97
+ const before = comma === void 0 && previous ? commaAfter(text, previous.range.end) : void 0;
98
+ const close = lineEnd(text, end);
99
+ const opening = text.slice(object.range.start, item.range.start);
100
+ if (object.items.length === 1 && !/\/\/|\/\*|#/.test(opening) && text.slice(close ?? end, object.range.end - 1).trim() === "") return splice(text, {
101
+ start: object.range.start + opening.trimEnd().length,
102
+ end: object.range.end - 1
103
+ }, "");
104
+ const start = lineStart(text, item.range.start);
105
+ if (close !== void 0 && /^[ \t]*$/.test(text.slice(start, item.range.start))) {
106
+ const next = splice(text, {
107
+ start,
108
+ end: close + (/^\r?\n/.exec(text.slice(close))?.[0].length ?? 0)
109
+ }, "");
110
+ return before === void 0 ? next : splice(next, {
111
+ start: before,
112
+ end: before + 1
113
+ }, "");
114
+ }
115
+ if (before !== void 0) return splice(text, {
116
+ start: before,
117
+ end
118
+ }, "");
119
+ return splice(text, {
120
+ start: item.range.start,
121
+ end: end + /^[ \t]*/.exec(text.slice(end))[0].length
122
+ }, "");
123
+ }
124
+ //#endregion
125
+ export { literalText as n, editLiteral as t };
@@ -0,0 +1,5 @@
1
+ import { Preset } from "@x18n/core";
2
+ //#region src/presets/ruby-i18n-js/index.d.ts
3
+ export declare function rubyI18nJs(): Preset;
4
+ //#endregion
5
+ export { rubyI18nJs as default };
@@ -1,11 +1,11 @@
1
1
  import { percentBraces } from "../placeholders.mjs";
2
2
  import { createLibraryPlugin } from "@x18n/core";
3
- //#region src/presets/i18n-js/index.ts
4
- function i18nJs() {
3
+ //#region src/presets/ruby-i18n-js/index.ts
4
+ function rubyI18nJs() {
5
5
  return {
6
- name: "i18n-js",
6
+ name: "ruby-i18n-js",
7
7
  plugins: [createLibraryPlugin({
8
- name: "x18n:i18n-js",
8
+ name: "x18n:ruby-i18n-js",
9
9
  calls: [{ callee: ["I18n.t", "i18n.t"] }],
10
10
  templates: [{
11
11
  template: "i18n.t('{key}'{args})",
@@ -16,4 +16,4 @@ function i18nJs() {
16
16
  };
17
17
  }
18
18
  //#endregion
19
- export { i18nJs as default, i18nJs };
19
+ export { rubyI18nJs as default, rubyI18nJs };
package/dist/presets.mjs CHANGED
@@ -85,57 +85,51 @@ const entry$31 = {
85
85
  load: () => import("./presets/gravity-ui-i18n.mjs")
86
86
  };
87
87
  //#endregion
88
- //#region src/presets/i18n-js/entry.ts
89
- const entry$30 = {
90
- detect: dependsOn(["i18n-js"]),
91
- load: () => import("./presets/i18n-js.mjs")
92
- };
93
- //#endregion
94
88
  //#region src/presets/i18n-tag/entry.ts
95
- const entry$29 = {
89
+ const entry$30 = {
96
90
  detect: dependsOn(["es2015-i18n-tag"]),
97
91
  load: () => import("./presets/i18n-tag.mjs")
98
92
  };
99
93
  //#endregion
100
94
  //#region src/presets/i18next-shopify/entry.ts
101
- const entry$28 = {
95
+ const entry$29 = {
102
96
  detect: dependsOn(["@shopify/i18next-shopify"]),
103
97
  load: () => import("./presets/i18next-shopify.mjs")
104
98
  };
105
99
  //#endregion
106
100
  //#region src/presets/i18next/entry.ts
107
- const entry$27 = {
101
+ const entry$28 = {
108
102
  detect: dependsOn(["i18next"]),
109
103
  load: () => import("./presets/i18next.mjs")
110
104
  };
111
105
  //#endregion
112
106
  //#region src/presets/i18nice/entry.ts
113
- const entry$26 = {
107
+ const entry$27 = {
114
108
  detect: dependsOn(["i18nice", "python-i18n"]),
115
109
  load: () => import("./presets/i18nice.mjs")
116
110
  };
117
111
  //#endregion
118
112
  //#region src/presets/jekyll/entry.ts
119
- const entry$25 = {
113
+ const entry$26 = {
120
114
  detect: dependsOn(["jekyll-multiple-languages-plugin"]),
121
115
  load: () => import("./presets/jekyll.mjs")
122
116
  };
123
117
  //#endregion
124
118
  //#region src/presets/laravel-vue-i18n/entry.ts
125
- const entry$24 = {
119
+ const entry$25 = {
126
120
  detect: dependsOn(["laravel-vue-i18n"]),
127
121
  load: () => import("./presets/laravel-vue-i18n.mjs")
128
122
  };
129
123
  //#endregion
130
124
  //#region src/presets/laravel/entry.ts
131
- const entry$23 = {
125
+ const entry$24 = {
132
126
  detect: dependsOn(["laravel/framework"]),
133
127
  exclusive: true,
134
128
  load: () => import("./presets/laravel.mjs")
135
129
  };
136
130
  //#endregion
137
131
  //#region src/presets/lingui/entry.ts
138
- const entry$22 = {
132
+ const entry$23 = {
139
133
  detect: dependsOn([
140
134
  "@lingui/core",
141
135
  "@lingui/react",
@@ -145,43 +139,43 @@ const entry$22 = {
145
139
  };
146
140
  //#endregion
147
141
  //#region src/presets/next-international/entry.ts
148
- const entry$21 = {
142
+ const entry$22 = {
149
143
  detect: dependsOn(["next-international"]),
150
144
  load: () => import("./presets/next-international.mjs")
151
145
  };
152
146
  //#endregion
153
147
  //#region src/presets/next-intl/entry.ts
154
- const entry$20 = {
148
+ const entry$21 = {
155
149
  detect: dependsOn(["next-intl", "use-intl"]),
156
150
  load: () => import("./presets/next-intl.mjs")
157
151
  };
158
152
  //#endregion
159
153
  //#region src/presets/next-translate/entry.ts
160
- const entry$19 = {
154
+ const entry$20 = {
161
155
  detect: dependsOn(["next-translate"]),
162
156
  load: () => import("./presets/next-translate.mjs")
163
157
  };
164
158
  //#endregion
165
159
  //#region src/presets/ngx-translate/entry.ts
166
- const entry$18 = {
160
+ const entry$19 = {
167
161
  detect: dependsOn(["@ngx-translate/core"]),
168
162
  load: () => import("./presets/ngx-translate.mjs")
169
163
  };
170
164
  //#endregion
171
165
  //#region src/presets/nuxt-i18n-micro/entry.ts
172
- const entry$17 = {
166
+ const entry$18 = {
173
167
  detect: dependsOn(["nuxt-i18n-micro"]),
174
168
  load: () => import("./presets/nuxt-i18n-micro.mjs")
175
169
  };
176
170
  //#endregion
177
171
  //#region src/presets/nuxt-i18n/entry.ts
178
- const entry$16 = {
172
+ const entry$17 = {
179
173
  detect: dependsOn(["@nuxtjs/i18n", "nuxt-i18n"]),
180
174
  load: () => import("./presets/nuxt-i18n.mjs")
181
175
  };
182
176
  //#endregion
183
177
  //#region src/presets/paraglide/entry.ts
184
- const entry$15 = {
178
+ const entry$16 = {
185
179
  detect: dependsOn([
186
180
  "@inlang/paraglide-js",
187
181
  "@inlang/paraglide-sveltekit",
@@ -193,41 +187,47 @@ const entry$15 = {
193
187
  };
194
188
  //#endregion
195
189
  //#region src/presets/php-gettext/entry.ts
196
- const entry$14 = {
190
+ const entry$15 = {
197
191
  exclusive: true,
198
192
  load: () => import("./presets/php-gettext.mjs")
199
193
  };
200
194
  //#endregion
201
195
  //#region src/presets/php-joomla/entry.ts
202
- const entry$13 = {
196
+ const entry$14 = {
203
197
  detect: dependsOn(["joomla/application", "joomla/cms"]),
204
198
  load: () => import("./presets/php-joomla.mjs")
205
199
  };
206
200
  //#endregion
207
201
  //#region src/presets/polyglot/entry.ts
208
- const entry$12 = {
202
+ const entry$13 = {
209
203
  detect: dependsOn(["node-polyglot"]),
210
204
  load: () => import("./presets/polyglot.mjs")
211
205
  };
212
206
  //#endregion
213
207
  //#region src/presets/python-gettext/entry.ts
214
- const entry$11 = {
208
+ const entry$12 = {
215
209
  detect: dependsOn(["django", "flask-babel"]),
216
210
  load: () => import("./presets/python-gettext.mjs")
217
211
  };
218
212
  //#endregion
219
213
  //#region src/presets/react-i18next/entry.ts
220
- const entry$10 = {
214
+ const entry$11 = {
221
215
  detect: dependsOn(["react-i18next", "next-i18next"]),
222
216
  load: () => import("./presets/react-i18next.mjs")
223
217
  };
224
218
  //#endregion
225
219
  //#region src/presets/react-intl/entry.ts
226
- const entry$9 = {
220
+ const entry$10 = {
227
221
  detect: dependsOn(["react-intl"], ["@formatjs/"]),
228
222
  load: () => import("./presets/react-intl.mjs")
229
223
  };
230
224
  //#endregion
225
+ //#region src/presets/ruby-i18n-js/entry.ts
226
+ const entry$9 = {
227
+ detect: dependsOn(["i18n-js"]),
228
+ load: () => import("./presets/ruby-i18n-js.mjs")
229
+ };
230
+ //#endregion
231
231
  //#region src/presets/ruby-rails/entry.ts
232
232
  const entry$8 = {
233
233
  detect: dependsOn([
@@ -287,8 +287,8 @@ const entry$2 = {
287
287
  * Presets that share plugins (react-i18next, svelte-i18next and i18next) apply them once.
288
288
  */
289
289
  const presets = {
290
- "nuxt-i18n": entry$16,
291
- "nuxt-i18n-micro": entry$17,
290
+ "nuxt-i18n": entry$17,
291
+ "nuxt-i18n-micro": entry$18,
292
292
  "vue-i18n": {
293
293
  detect: dependsOn([
294
294
  "vue-i18n",
@@ -300,44 +300,44 @@ const presets = {
300
300
  },
301
301
  "fluent-vue": entry$36,
302
302
  "fluent-react": entry$37,
303
- "i18next-shopify": entry$28,
304
- "react-i18next": entry$10,
303
+ "i18next-shopify": entry$29,
304
+ "react-i18next": entry$11,
305
305
  "svelte-i18next": entry$5,
306
- "next-translate": entry$19,
307
- "next-international": entry$21,
308
- "i18next": entry$27,
309
- "next-intl": entry$20,
310
- "react-intl": entry$9,
306
+ "next-translate": entry$20,
307
+ "next-international": entry$22,
308
+ "i18next": entry$28,
309
+ "next-intl": entry$21,
310
+ "react-intl": entry$10,
311
311
  "svelte-i18n": entry$6,
312
312
  "solid-primitives-i18n": entry$7,
313
- "paraglide": entry$15,
313
+ "paraglide": entry$16,
314
314
  "gravity-ui-i18n": entry$31,
315
315
  "typesafe-i18n": entry$3,
316
- "ngx-translate": entry$18,
316
+ "ngx-translate": entry$19,
317
317
  "transloco": entry$4,
318
- "lingui": entry$22,
318
+ "lingui": entry$23,
319
319
  "ember-intl": entry$38,
320
- "polyglot": entry$12,
320
+ "polyglot": entry$13,
321
321
  "globalize": entry$32,
322
- "i18n-tag": entry$29,
323
- "i18n-js": entry$30,
322
+ "i18n-tag": entry$30,
323
+ "ruby-i18n-js": entry$9,
324
324
  "ui5": entry$2,
325
325
  "chrome-extension": entry$41,
326
326
  "vscode-extension": {
327
327
  detect: (ctx) => ctx.hasAnyDependency(["vscode", "@types/vscode"]),
328
328
  load: () => import("./presets/vscode-extension.mjs")
329
329
  },
330
- "laravel-vue-i18n": entry$24,
331
- "laravel": entry$23,
332
- "php-joomla": entry$13,
333
- "php-gettext": entry$14,
330
+ "laravel-vue-i18n": entry$25,
331
+ "laravel": entry$24,
332
+ "php-joomla": entry$14,
333
+ "php-gettext": entry$15,
334
334
  "ruby-rails": entry$8,
335
- "jekyll": entry$25,
335
+ "jekyll": entry$26,
336
336
  "flutter": entry$34,
337
337
  "easy-localization": entry$39,
338
338
  "flutter-translate": entry$35,
339
- "python-gettext": entry$11,
340
- "i18nice": entry$26,
339
+ "python-gettext": entry$12,
340
+ "i18nice": entry$27,
341
341
  "cargo-i18n": entry$42,
342
342
  "dotnet-resx": entry$40,
343
343
  "general": entry$33
@@ -0,0 +1,6 @@
1
+ import { Plugin, ReviewStore } from "@x18n/core";
2
+ //#region src/reviews/index.d.ts
3
+ /** Reviews in a YAML file (`.x18n/reviews.yml`), tracked in git so they show up in pull requests. */
4
+ export declare const yamlReviewStore: ReviewStore;
5
+ export declare function reviews(): Plugin;
6
+ //#endregion
@@ -0,0 +1,35 @@
1
+ import { ReviewFileSchema, validate } from "@x18n/core";
2
+ import { parse, stringify } from "yaml";
3
+ //#region src/reviews/index.ts
4
+ const header = "# yaml-language-server: $schema=https://x18n.antfu.dev/schema/reviews.json\n";
5
+ /** Reviews in a YAML file (`.x18n/reviews.yml`), tracked in git so they show up in pull requests. */
6
+ const yamlReviewStore = {
7
+ id: "yaml",
8
+ parse(text) {
9
+ const result = validate(ReviewFileSchema, parse(text) ?? { x18n: 1 });
10
+ if (!result.success) throw new Error(result.issues.map((issue) => `${issue.path || "(root)"}: ${issue.message}`).join("; "));
11
+ return {
12
+ threads: result.output.threads ?? {},
13
+ sources: result.output.sources ?? {}
14
+ };
15
+ },
16
+ serialize(data) {
17
+ const file = {
18
+ x18n: 1,
19
+ ...Object.keys(data.threads).length > 0 && { threads: data.threads },
20
+ ...Object.keys(data.sources).length > 0 && { sources: data.sources }
21
+ };
22
+ return header + stringify(file, {
23
+ lineWidth: 0,
24
+ aliasDuplicateObjects: false
25
+ });
26
+ }
27
+ };
28
+ function reviews() {
29
+ return {
30
+ name: "x18n:reviews",
31
+ reviewStores: [yamlReviewStore]
32
+ };
33
+ }
34
+ //#endregion
35
+ export { reviews, yamlReviewStore };
@@ -1,23 +1,8 @@
1
1
  //#region src/formats/shared/index.ts
2
- /** Indent of the first indented line, so edits keep the file's style. */
3
- function detectIndent(text, fallback) {
4
- if (fallback === "tab") return {
5
- insertSpaces: false,
6
- tabSize: 1
7
- };
8
- if (typeof fallback === "number") return {
9
- insertSpaces: true,
10
- tabSize: fallback
11
- };
12
- const match = /^([ \t]+)\S/m.exec(text);
13
- if (match?.[1]?.startsWith(" ")) return {
14
- insertSpaces: false,
15
- tabSize: 1
16
- };
17
- return {
18
- insertSpaces: true,
19
- tabSize: match?.[1]?.length ?? 2
20
- };
2
+ /** One indent level: the configured one, else the file's first indented line, else `fallback`. */
3
+ function indentUnit(text, indent, fallback) {
4
+ if (indent !== void 0) return indent === "tab" ? " " : " ".repeat(indent);
5
+ return /^([ \t]+)\S/m.exec(text)?.[1] ?? fallback;
21
6
  }
22
7
  function detectEol(text) {
23
8
  return text.includes("\r\n") ? "\r\n" : "\n";
@@ -67,4 +52,4 @@ function withBlankLines(text, range) {
67
52
  };
68
53
  }
69
54
  //#endregion
70
- export { splice as a, withBlankLines as c, leafText as i, detectEol as n, splitLines as o, detectIndent as r, toLeaf as s, appendLines as t };
55
+ export { splice as a, withBlankLines as c, leafText as i, detectEol as n, splitLines as o, indentUnit as r, toLeaf as s, appendLines as t };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@x18n/builtins",
3
3
  "type": "module",
4
- "version": "0.0.14",
4
+ "version": "0.0.15",
5
5
  "description": "Built-in x18n plugins and presets: formats, locale finders, scanners, checks and reporters",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -45,7 +45,6 @@
45
45
  "./presets/general": "./dist/presets/general.mjs",
46
46
  "./presets/globalize": "./dist/presets/globalize.mjs",
47
47
  "./presets/gravity-ui-i18n": "./dist/presets/gravity-ui-i18n.mjs",
48
- "./presets/i18n-js": "./dist/presets/i18n-js.mjs",
49
48
  "./presets/i18n-tag": "./dist/presets/i18n-tag.mjs",
50
49
  "./presets/i18next": "./dist/presets/i18next.mjs",
51
50
  "./presets/i18next-shopify": "./dist/presets/i18next-shopify.mjs",
@@ -67,6 +66,7 @@
67
66
  "./presets/python-gettext": "./dist/presets/python-gettext.mjs",
68
67
  "./presets/react-i18next": "./dist/presets/react-i18next.mjs",
69
68
  "./presets/react-intl": "./dist/presets/react-intl.mjs",
69
+ "./presets/ruby-i18n-js": "./dist/presets/ruby-i18n-js.mjs",
70
70
  "./presets/ruby-rails": "./dist/presets/ruby-rails.mjs",
71
71
  "./presets/solid-primitives-i18n": "./dist/presets/solid-primitives-i18n.mjs",
72
72
  "./presets/svelte-i18n": "./dist/presets/svelte-i18n.mjs",
@@ -82,6 +82,7 @@
82
82
  "./reporters/markdown": "./dist/reporters/markdown.mjs",
83
83
  "./reporters/pretty": "./dist/reporters/pretty.mjs",
84
84
  "./reporters/sarif": "./dist/reporters/sarif.mjs",
85
+ "./reviews": "./dist/reviews.mjs",
85
86
  "./scanners": "./dist/scanners.mjs",
86
87
  "./scanners/astro": "./dist/scanners/astro.mjs",
87
88
  "./scanners/js": "./dist/scanners/js.mjs",
@@ -97,7 +98,7 @@
97
98
  ],
98
99
  "dependencies": {
99
100
  "@vue/compiler-sfc": "^3.5.44",
100
- "@x18n/core": "0.0.14",
101
+ "@x18n/core": "0.0.15",
101
102
  "json5": "^2.2.3",
102
103
  "jsonc-parser": "^3.3.1",
103
104
  "oxc-parser": "^0.155.0",