recipe-tmlanguage 0.3.4 → 0.3.5
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/bin/{recipe-tmlang.mjs → cli.mjs} +65 -27
- package/bin/{recipe-tmlang.ts → cli.ts} +7 -4
- package/bin/commands/generate.ts +3 -4
- package/bin/commands/verify.ts +5 -10
- package/bin/lib/utils.ts +29 -0
- package/package.json +12 -9
- package/src/deps/oniguruma.ts +35 -0
- package/src/deps/textmate.ts +8 -0
- package/src/grammar.ts +2 -0
- package/src/verifier.ts +6 -15
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
+
import { cli, command, flag } from "@kjanat/dreamcli";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
3
6
|
import { COUNTERS, NUMBER_WORDS, PERIODS, PERIOD_PLURALS } from "tree-sitter-recipe/grammar/dutch";
|
|
4
7
|
import { COMPOUNDING, COMPOUNDING_MULTIWORD, CONDITIONAL, CONDITIONAL_MULTIWORD, DISPENSING, DISPENSING_MULTIWORD, FORMS, FORMS_MULTIWORD, FREQUENCY, ROUTE, ROUTE_MULTIWORD, TIMING, TIMING_MULTIWORD, WARNING } from "tree-sitter-recipe/grammar/latin";
|
|
5
8
|
import { UNITS } from "tree-sitter-recipe/grammar/units";
|
|
6
|
-
import { cli, command, flag } from "@kjanat/dreamcli";
|
|
7
9
|
import { mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
8
|
-
import { dirname, resolve } from "node:path";
|
|
9
10
|
import { cwd, exit } from "node:process";
|
|
11
|
+
import { readFile } from "node:fs/promises";
|
|
12
|
+
//#region bin/lib/utils.ts
|
|
13
|
+
const require$1 = createRequire(import.meta.url);
|
|
14
|
+
const toPath = (resolved) => resolved.startsWith("file:") ? fileURLToPath(resolved) : resolved;
|
|
15
|
+
function packageDir(specifier) {
|
|
16
|
+
return resolve(dirname(toPath(require$1.resolve(specifier))));
|
|
17
|
+
}
|
|
18
|
+
function resolveImportMeta(specifier) {
|
|
19
|
+
return toPath(import.meta.resolve(specifier));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Default path of the generated grammar: `recipe.tmLanguage.json` at the
|
|
23
|
+
* package root. Anchored on `#pkg` (package.json / deno.json — always present)
|
|
24
|
+
* rather than `#tmLang`, because the grammar is generated + gitignored and may
|
|
25
|
+
* not exist yet on a fresh checkout, and `import.meta.resolve` throws on a
|
|
26
|
+
* missing target. Existence is enforced later, where the file is actually read.
|
|
27
|
+
*/
|
|
28
|
+
function defaultGrammarPath() {
|
|
29
|
+
return resolve(dirname(resolveImportMeta("#pkg")), "recipe.tmLanguage.json");
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
10
32
|
//#region src/grammar.ts
|
|
11
33
|
/**
|
|
12
34
|
* @file Pure grammar builder — imports the tree-sitter-recipe vocabulary and
|
|
@@ -15,6 +37,8 @@ import { cwd, exit } from "node:process";
|
|
|
15
37
|
*
|
|
16
38
|
* Scopes are standard TextMate names with a `.recipe` suffix so themes paint
|
|
17
39
|
* recipe blocks without a custom theme shipment.
|
|
40
|
+
*
|
|
41
|
+
* @module recipe-tmlanguage/src/grammar
|
|
18
42
|
*/
|
|
19
43
|
const SCOPE = {
|
|
20
44
|
rxMarker: "keyword.control.directive.rx.recipe",
|
|
@@ -268,7 +292,7 @@ function serializeGrammar(g, indent) {
|
|
|
268
292
|
//#endregion
|
|
269
293
|
//#region bin/commands/generate.ts
|
|
270
294
|
const indentOf = (raw) => raw === "tab" ? "tab" : Number(raw);
|
|
271
|
-
const DEFAULT_OUT$1 =
|
|
295
|
+
const DEFAULT_OUT$1 = defaultGrammarPath();
|
|
272
296
|
const generateCmd = command("generate").description("Build the TextMate grammar from the tree-sitter-recipe vocabulary").flag("out", flag.string().alias("o").default(DEFAULT_OUT$1).describe("Output JSON path")).flag("indent", flag.enum([
|
|
273
297
|
"tab",
|
|
274
298
|
"2",
|
|
@@ -296,6 +320,31 @@ const generateCmd = command("generate").description("Build the TextMate grammar
|
|
|
296
320
|
log(` vocab: ${v.frequency} frequency · ${v.timing.single}+${v.timing.multi} timing · ${v.route.single}+${v.route.multi} route · ${v.dispensing.single}+${v.dispensing.multi} dispensing · ${v.forms.single}+${v.forms.multi} forms · ${v.compounding.single}+${v.compounding.multi} compounding · ${v.conditional.single}+${v.conditional.multi} conditional · ${v.warning} warning · ${v.units} units`);
|
|
297
321
|
});
|
|
298
322
|
//#endregion
|
|
323
|
+
//#region src/deps/oniguruma.ts
|
|
324
|
+
const require = createRequire(import.meta.url);
|
|
325
|
+
const oniguruma = require("vscode-oniguruma");
|
|
326
|
+
let loadPromise;
|
|
327
|
+
function loadOniguruma() {
|
|
328
|
+
loadPromise ??= (async () => {
|
|
329
|
+
const wasm = await readFile(require.resolve("vscode-oniguruma/release/onig.wasm"));
|
|
330
|
+
await oniguruma.loadWASM(wasm);
|
|
331
|
+
})();
|
|
332
|
+
return loadPromise;
|
|
333
|
+
}
|
|
334
|
+
async function createOnigLib() {
|
|
335
|
+
await loadOniguruma();
|
|
336
|
+
return {
|
|
337
|
+
createOnigScanner(patterns) {
|
|
338
|
+
return oniguruma.createOnigScanner(patterns);
|
|
339
|
+
},
|
|
340
|
+
createOnigString(string) {
|
|
341
|
+
return oniguruma.createOnigString(string);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const { loadWASM, createOnigScanner, createOnigString, OnigScanner, OnigString } = oniguruma;
|
|
346
|
+
const { parseRawGrammar, Registry, INITIAL } = createRequire(import.meta.url)("vscode-textmate");
|
|
347
|
+
//#endregion
|
|
299
348
|
//#region src/verifier.ts
|
|
300
349
|
/**
|
|
301
350
|
* @file Pure verifier — tokenizes tree-sitter-recipe's own highlight fixtures
|
|
@@ -304,10 +353,9 @@ const generateCmd = command("generate").description("Build the TextMate grammar
|
|
|
304
353
|
*
|
|
305
354
|
* No CLI concerns here; the caller supplies paths and decides how to present
|
|
306
355
|
* the result (text table / JSON / exit code).
|
|
356
|
+
*
|
|
357
|
+
* @module recipe-tmlanguage/src/verifier
|
|
307
358
|
*/
|
|
308
|
-
const require$1 = createRequire(import.meta.url);
|
|
309
|
-
const oniguruma = require$1("vscode-oniguruma");
|
|
310
|
-
const { parseRawGrammar, Registry } = require$1("vscode-textmate");
|
|
311
359
|
const CAPTURE_EXPECTS = {
|
|
312
360
|
"keyword.directive": "keyword.control.directive",
|
|
313
361
|
"keyword.repeat": "keyword.other.frequency",
|
|
@@ -360,12 +408,7 @@ function parseFixture(content, name) {
|
|
|
360
408
|
};
|
|
361
409
|
}
|
|
362
410
|
async function verify(opts) {
|
|
363
|
-
const
|
|
364
|
-
await oniguruma.loadWASM(wasmBin.buffer);
|
|
365
|
-
const onigLib = Promise.resolve({
|
|
366
|
-
createOnigScanner: (patterns) => new oniguruma.OnigScanner(patterns),
|
|
367
|
-
createOnigString: (s) => new oniguruma.OnigString(s)
|
|
368
|
-
});
|
|
411
|
+
const onigLib = createOnigLib();
|
|
369
412
|
const rawGrammar = parseRawGrammar(readFileSync(opts.grammarPath, "utf-8"), opts.grammarPath);
|
|
370
413
|
const grammar = await new Registry({
|
|
371
414
|
onigLib,
|
|
@@ -410,15 +453,12 @@ async function verify(opts) {
|
|
|
410
453
|
}
|
|
411
454
|
//#endregion
|
|
412
455
|
//#region bin/commands/verify.ts
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
const
|
|
416
|
-
const DEFAULT_OUT = `${dirname(require.resolve("#pkg"))}/recipe.tmLanguage.json`;
|
|
417
|
-
const verifyCmd = command("verify").description("Tokenize tree-sitter-recipe highlight fixtures and assert scope matches").flag("grammar", flag.string().alias("g").default(DEFAULT_OUT).describe("Path to .tmLanguage.json")).flag("fixtures", flag.string().alias("f").default(DEFAULT_FIXTURES_DIR).describe("Directory of .recipe fixtures")).flag("onig-wasm", flag.string().default(DEFAULT_ONIG_WASM).describe("Path to oniguruma WASM")).flag("max-failures", flag.number().default(40).describe("Max failures to print (0 = all)")).action(async ({ flags, out }) => {
|
|
456
|
+
const DEFAULT_FIXTURES_DIR = resolve(packageDir("tree-sitter-recipe/package.json"), "test/highlight");
|
|
457
|
+
const DEFAULT_OUT = defaultGrammarPath();
|
|
458
|
+
const verifyCmd = command("verify").description("Tokenize tree-sitter-recipe highlight fixtures and assert scope matches").flag("grammar", flag.string().alias("g").default(DEFAULT_OUT).describe("Path to .tmLanguage.json")).flag("fixtures", flag.string().alias("f").default(DEFAULT_FIXTURES_DIR).describe("Directory of .recipe fixtures")).flag("max-failures", flag.number().default(40).describe("Max failures to print (0 = all)")).action(async ({ flags, out }) => {
|
|
418
459
|
const result = await verify({
|
|
419
460
|
grammarPath: resolve(cwd(), flags.grammar),
|
|
420
|
-
fixturesDir: resolve(cwd(), flags.fixtures)
|
|
421
|
-
onigWasmPath: resolve(cwd(), flags["onig-wasm"])
|
|
461
|
+
fixturesDir: resolve(cwd(), flags.fixtures)
|
|
422
462
|
});
|
|
423
463
|
const failuresLen = result.failures.length;
|
|
424
464
|
const { json, jsonMode, setExitCode, log } = out;
|
|
@@ -443,7 +483,7 @@ const verifyCmd = command("verify").description("Tokenize tree-sitter-recipe hig
|
|
|
443
483
|
setExitCode(1);
|
|
444
484
|
});
|
|
445
485
|
//#endregion
|
|
446
|
-
//#region bin/
|
|
486
|
+
//#region bin/cli.ts
|
|
447
487
|
/**
|
|
448
488
|
* recipe-tmlang — TextMate grammar generator & verifier for recipe-tmlanguage.
|
|
449
489
|
*
|
|
@@ -454,14 +494,12 @@ const verifyCmd = command("verify").description("Tokenize tree-sitter-recipe hig
|
|
|
454
494
|
* Zero manual argparse — argument parsing, help, and completions all come from
|
|
455
495
|
* {@link https://github.com/kjanat/dreamcli | DreamCLI}. `--json` is a DreamCLI built-in;
|
|
456
496
|
* we branch on {@linkcode out.jsonMode | https://dreamcli.kjanat.com/reference/symbols/main/Out#jsonmode}.
|
|
497
|
+
*
|
|
498
|
+
* @module recipe-tmlanguage/bin
|
|
457
499
|
*/
|
|
458
|
-
const app = cli("recipe-tmlanguage").
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
"url": "git+https://github.com/kjanat/recipe-tmlanguage.git"
|
|
462
|
-
},
|
|
463
|
-
homepage: "https://github.com/kjanat/recipe-tmlanguage#recipe-tmlanguage",
|
|
464
|
-
version: "0.3.4"
|
|
500
|
+
const app = cli("recipe-tmlanguage").manifest({
|
|
501
|
+
from: import.meta.url,
|
|
502
|
+
files: ["package.json", "deno.json"]
|
|
465
503
|
}).links().description("TextMate grammar generator & verifier for the recipe DSL").command(generateCmd).command(verifyCmd).completions();
|
|
466
504
|
if (import.meta.main) app.run();
|
|
467
505
|
//#endregion
|
|
@@ -9,13 +9,16 @@
|
|
|
9
9
|
* Zero manual argparse — argument parsing, help, and completions all come from
|
|
10
10
|
* {@link https://github.com/kjanat/dreamcli | DreamCLI}. `--json` is a DreamCLI built-in;
|
|
11
11
|
* we branch on {@linkcode out.jsonMode | https://dreamcli.kjanat.com/reference/symbols/main/Out#jsonmode}.
|
|
12
|
+
*
|
|
13
|
+
* @module recipe-tmlanguage/bin
|
|
12
14
|
*/
|
|
13
|
-
import { generateCmd } from "#bin/commands/generate";
|
|
14
|
-
import { verifyCmd } from "#bin/commands/verify";
|
|
15
|
-
import { homepage, name, repository, version } from "#pkg" with { type: "json" };
|
|
16
15
|
import { cli } from "@kjanat/dreamcli";
|
|
16
|
+
import { generateCmd } from "./commands/generate.ts";
|
|
17
|
+
import { verifyCmd } from "./commands/verify.ts";
|
|
17
18
|
|
|
18
|
-
const app = cli(
|
|
19
|
+
const app = cli("recipe-tmlanguage")
|
|
20
|
+
.manifest({ from: import.meta.url, files: ["package.json", "deno.json"] })
|
|
21
|
+
.links()
|
|
19
22
|
.description("TextMate grammar generator & verifier for the recipe DSL")
|
|
20
23
|
.command(generateCmd)
|
|
21
24
|
.command(verifyCmd)
|
package/bin/commands/generate.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defaultGrammarPath } from "#bin/lib/utils.ts";
|
|
2
|
+
import { buildGrammar, serializeGrammar } from "#src/grammar.ts";
|
|
2
3
|
import { command, flag } from "@kjanat/dreamcli";
|
|
3
4
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { createRequire } from "node:module";
|
|
5
5
|
import { dirname, resolve } from "node:path";
|
|
6
6
|
import { cwd } from "node:process";
|
|
7
7
|
|
|
8
8
|
const indentOf = (raw: string): "tab" | number => (raw === "tab" ? "tab" : Number(raw));
|
|
9
|
-
const
|
|
10
|
-
const DEFAULT_OUT = `${dirname(require.resolve("#pkg"))}/recipe.tmLanguage.json`;
|
|
9
|
+
const DEFAULT_OUT = defaultGrammarPath();
|
|
11
10
|
|
|
12
11
|
export const generateCmd = command("generate")
|
|
13
12
|
.description("Build the TextMate grammar from the tree-sitter-recipe vocabulary")
|
package/bin/commands/verify.ts
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defaultGrammarPath, packageDir } from "#bin/lib/utils.ts";
|
|
2
|
+
import { verify } from "#src/verifier.ts";
|
|
2
3
|
import { command, flag } from "@kjanat/dreamcli";
|
|
3
|
-
import {
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
5
|
import { cwd, exit } from "node:process";
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const DEFAULT_FIXTURES_DIR = resolve(TS_RX_DIR, "test/highlight");
|
|
10
|
-
const DEFAULT_ONIG_WASM = require.resolve("vscode-oniguruma/release/onig.wasm");
|
|
11
|
-
const DEFAULT_OUT = `${dirname(require.resolve("#pkg"))}/recipe.tmLanguage.json`;
|
|
7
|
+
const DEFAULT_FIXTURES_DIR = resolve(packageDir("tree-sitter-recipe/package.json"), "test/highlight");
|
|
8
|
+
const DEFAULT_OUT = defaultGrammarPath();
|
|
12
9
|
|
|
13
10
|
export const verifyCmd = command("verify")
|
|
14
11
|
.description("Tokenize tree-sitter-recipe highlight fixtures and assert scope matches")
|
|
15
12
|
.flag("grammar", flag.string().alias("g").default(DEFAULT_OUT).describe("Path to .tmLanguage.json"))
|
|
16
13
|
.flag("fixtures", flag.string().alias("f").default(DEFAULT_FIXTURES_DIR).describe("Directory of .recipe fixtures"))
|
|
17
|
-
.flag("onig-wasm", flag.string().default(DEFAULT_ONIG_WASM).describe("Path to oniguruma WASM"))
|
|
18
14
|
.flag("max-failures", flag.number().default(40).describe("Max failures to print (0 = all)"))
|
|
19
15
|
.action(async ({ flags, out }) => {
|
|
20
16
|
const result = await verify({
|
|
21
17
|
grammarPath: resolve(cwd(), flags.grammar),
|
|
22
18
|
fixturesDir: resolve(cwd(), flags.fixtures),
|
|
23
|
-
onigWasmPath: resolve(cwd(), flags["onig-wasm"]),
|
|
24
19
|
});
|
|
25
20
|
const failuresLen = result.failures.length;
|
|
26
21
|
const { json, jsonMode, setExitCode, log } = out;
|
package/bin/lib/utils.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
|
|
7
|
+
const toPath = (resolved: string) =>
|
|
8
|
+
resolved.startsWith("file:")
|
|
9
|
+
? fileURLToPath(resolved)
|
|
10
|
+
: resolved;
|
|
11
|
+
|
|
12
|
+
export function packageDir(specifier: string): string {
|
|
13
|
+
return resolve(dirname(toPath(require.resolve(specifier))));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function resolveImportMeta(specifier: string): string {
|
|
17
|
+
return toPath(import.meta.resolve(specifier));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Default path of the generated grammar: `recipe.tmLanguage.json` at the
|
|
22
|
+
* package root. Anchored on `#pkg` (package.json / deno.json — always present)
|
|
23
|
+
* rather than `#tmLang`, because the grammar is generated + gitignored and may
|
|
24
|
+
* not exist yet on a fresh checkout, and `import.meta.resolve` throws on a
|
|
25
|
+
* missing target. Existence is enforced later, where the file is actually read.
|
|
26
|
+
*/
|
|
27
|
+
export function defaultGrammarPath(): string {
|
|
28
|
+
return resolve(dirname(resolveImportMeta("#pkg")), "recipe.tmLanguage.json");
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "recipe-tmlanguage",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "TextMate grammar for the recipe (.recipe) pharmacological notation language.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dreamcli",
|
|
@@ -21,18 +21,20 @@
|
|
|
21
21
|
},
|
|
22
22
|
"type": "module",
|
|
23
23
|
"imports": {
|
|
24
|
-
"#bin/*": "./bin
|
|
24
|
+
"#bin/*": "./bin/*",
|
|
25
|
+
"#src/*": "./src/*",
|
|
26
|
+
"#deps/*": "./src/deps/*",
|
|
25
27
|
"#pkg": "./package.json",
|
|
26
|
-
"#
|
|
27
|
-
"#verifier": "./src/verifier.ts"
|
|
28
|
+
"#tmLang": "./recipe.tmLanguage.json"
|
|
28
29
|
},
|
|
29
30
|
"exports": {
|
|
30
31
|
".": "./recipe.tmLanguage.json",
|
|
32
|
+
"./bin": "./bin/cli.mjs",
|
|
31
33
|
"./package.json": "./package.json"
|
|
32
34
|
},
|
|
33
35
|
"main": "./recipe.tmLanguage.json",
|
|
34
36
|
"module": "./recipe.tmLanguage.json",
|
|
35
|
-
"bin": "bin/
|
|
37
|
+
"bin": "bin/cli.mjs",
|
|
36
38
|
"directories": {
|
|
37
39
|
"lib": "/src",
|
|
38
40
|
"bin": "/bin"
|
|
@@ -53,16 +55,17 @@
|
|
|
53
55
|
"generate": "run recipe-tmlang generate",
|
|
54
56
|
"lint": "biome lint",
|
|
55
57
|
"prepack": "bun run generate && bun run bundle",
|
|
56
|
-
"recipe-tmlang": "bun bin/
|
|
58
|
+
"recipe-tmlang": "bun bin/cli.ts",
|
|
57
59
|
"test": "bun test",
|
|
58
60
|
"typecheck": "tsc --noEmit",
|
|
59
|
-
"verify": "run recipe-tmlang verify"
|
|
61
|
+
"verify": "run recipe-tmlang verify",
|
|
62
|
+
"version": "node bin/cli.mjs --version"
|
|
60
63
|
},
|
|
61
64
|
"dependencies": {
|
|
62
|
-
"@kjanat/dreamcli": "^2.
|
|
65
|
+
"@kjanat/dreamcli": "^2.5.0",
|
|
63
66
|
"tree-sitter-recipe": "^0.3.1",
|
|
64
67
|
"vscode-oniguruma": "^2.0.1",
|
|
65
|
-
"vscode-textmate": "^9.2
|
|
68
|
+
"vscode-textmate": "^9.3.2"
|
|
66
69
|
},
|
|
67
70
|
"devDependencies": {
|
|
68
71
|
"@biomejs/biome": "^2.5.1",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/deps/oniguruma.ts
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import type { IOnigLib } from "./textmate.ts";
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const oniguruma: typeof import("vscode-oniguruma") = require("vscode-oniguruma");
|
|
8
|
+
|
|
9
|
+
let loadPromise: Promise<void> | undefined;
|
|
10
|
+
|
|
11
|
+
export function loadOniguruma(): Promise<void> {
|
|
12
|
+
loadPromise ??= (async () => {
|
|
13
|
+
const wasmPath = require.resolve("vscode-oniguruma/release/onig.wasm");
|
|
14
|
+
const wasm = await readFile(wasmPath);
|
|
15
|
+
|
|
16
|
+
await oniguruma.loadWASM(wasm);
|
|
17
|
+
})();
|
|
18
|
+
|
|
19
|
+
return loadPromise;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function createOnigLib(): Promise<IOnigLib> {
|
|
23
|
+
await loadOniguruma();
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
createOnigScanner(patterns) {
|
|
27
|
+
return oniguruma.createOnigScanner(patterns);
|
|
28
|
+
},
|
|
29
|
+
createOnigString(string) {
|
|
30
|
+
return oniguruma.createOnigString(string);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const { loadWASM, createOnigScanner, createOnigString, OnigScanner, OnigString } = oniguruma;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
export type { IOnigLib, StateStack } from "vscode-textmate";
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
const textmate: typeof import("vscode-textmate") = require("vscode-textmate");
|
|
7
|
+
|
|
8
|
+
export const { parseRawGrammar, Registry, INITIAL } = textmate;
|
package/src/grammar.ts
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Scopes are standard TextMate names with a `.recipe` suffix so themes paint
|
|
7
7
|
* recipe blocks without a custom theme shipment.
|
|
8
|
+
*
|
|
9
|
+
* @module recipe-tmlanguage/src/grammar
|
|
8
10
|
*/
|
|
9
11
|
import { COUNTERS, NUMBER_WORDS, PERIOD_PLURALS, PERIODS } from "tree-sitter-recipe/grammar/dutch";
|
|
10
12
|
import {
|
package/src/verifier.ts
CHANGED
|
@@ -5,17 +5,15 @@
|
|
|
5
5
|
*
|
|
6
6
|
* No CLI concerns here; the caller supplies paths and decides how to present
|
|
7
7
|
* the result (text table / JSON / exit code).
|
|
8
|
+
*
|
|
9
|
+
* @module recipe-tmlanguage/src/verifier
|
|
8
10
|
*/
|
|
9
11
|
import { readdirSync, readFileSync } from "node:fs";
|
|
10
|
-
import { createRequire } from "node:module";
|
|
11
12
|
import { resolve } from "node:path";
|
|
12
13
|
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const oniguruma: typeof import("vscode-oniguruma") = require("vscode-oniguruma");
|
|
17
|
-
const textmate: typeof import("vscode-textmate") = require("vscode-textmate");
|
|
18
|
-
const { parseRawGrammar, Registry } = textmate;
|
|
14
|
+
import { createOnigLib } from "#deps/oniguruma.ts";
|
|
15
|
+
import type { StateStack } from "#deps/textmate.ts";
|
|
16
|
+
import { parseRawGrammar, Registry } from "#deps/textmate.ts";
|
|
19
17
|
|
|
20
18
|
// ── capture → scope mapping (inverse of grammar.ts SCOPE) ───────────────────
|
|
21
19
|
// Fixtures speak tree-sitter capture names; the tokenizer speaks TextMate
|
|
@@ -57,7 +55,6 @@ export type VerifyResult = {
|
|
|
57
55
|
export type VerifyOptions = {
|
|
58
56
|
grammarPath: string;
|
|
59
57
|
fixturesDir: string;
|
|
60
|
-
onigWasmPath: string;
|
|
61
58
|
};
|
|
62
59
|
|
|
63
60
|
// ── fixture parser ──────────────────────────────────────────────────────────
|
|
@@ -105,13 +102,7 @@ function parseFixture(content: string, name: string): { source: string; asserts:
|
|
|
105
102
|
|
|
106
103
|
// ── main ────────────────────────────────────────────────────────────────────
|
|
107
104
|
export async function verify(opts: VerifyOptions): Promise<VerifyResult> {
|
|
108
|
-
const
|
|
109
|
-
await oniguruma.loadWASM(wasmBin.buffer as ArrayBuffer);
|
|
110
|
-
|
|
111
|
-
const onigLib = Promise.resolve({
|
|
112
|
-
createOnigScanner: (patterns: string[]) => new oniguruma.OnigScanner(patterns),
|
|
113
|
-
createOnigString: (s: string) => new oniguruma.OnigString(s),
|
|
114
|
-
});
|
|
105
|
+
const onigLib = createOnigLib();
|
|
115
106
|
|
|
116
107
|
const rawGrammar = parseRawGrammar(
|
|
117
108
|
readFileSync(opts.grammarPath, "utf-8"),
|