@akira-tl/forgerelay 0.5.6 → 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/CHANGELOG.md +43 -0
- package/README.md +7 -3
- package/capabilities/host-integration/GUIDE.md +15 -9
- package/dist/activity/host-turn-store.js +9 -7
- package/dist/activity/lifecycle.js +1 -1
- package/dist/activity/mcp-query-tools.js +110 -18
- package/dist/activity/query-service.js +4 -4
- package/dist/activity/ui/contract.js +2 -0
- package/dist/cli.js +47 -32
- package/dist/config.js +31 -3
- package/dist/db/migrations.js +30 -0
- package/dist/db/schema.js +2 -0
- package/dist/logger.js +6 -5
- package/dist/lsp/test-support/server-fixture.js +1 -1
- package/dist/mcp/server-instructions.js +7 -6
- package/dist/mcp-app-template.js +108 -12
- package/dist/oauth/public-url.js +14 -0
- package/dist/oauth/router.js +49 -0
- package/dist/process-sessions.js +2 -1
- package/dist/request-meta.js +4 -0
- package/dist/server.js +250 -84
- package/dist/skills.js +58 -1
- package/dist/ui/.vite/manifest.json +360 -312
- package/dist/ui/activity-panel-app.html +17 -0
- package/dist/ui/assets/activity-panel-app-CjZVvVNc.js +2 -0
- package/dist/ui/assets/angular-html-BkgDQl-G.js +1 -0
- package/dist/ui/assets/{angular-ts-BwPE8YDt.js → angular-ts-Bxh4-O1-.js} +1 -1
- package/dist/ui/assets/{apl-CGbONVvU.js → apl-BmYHKQ6m.js} +1 -1
- package/dist/ui/assets/{astro-DIAPy7cj.js → astro-C51vqDKq.js} +1 -1
- package/dist/ui/assets/{blade-Cgtd19Ky.js → blade-CdhVsmwq.js} +1 -1
- package/dist/ui/assets/c-IBzBpxAO.js +1 -0
- package/dist/ui/assets/chunk-EyZ2wyi3.js +1 -0
- package/dist/ui/assets/{cobol-G-7HLVKW.js → cobol-Cf6azoN_.js} +1 -1
- package/dist/ui/assets/{coffee-DQFyKxEB.js → coffee-vVdGzlmt.js} +1 -1
- package/dist/ui/assets/cpp-CVHeO-Jk.js +1 -0
- package/dist/ui/assets/{crystal-DuiWhEO3.js → crystal-5UZy6KIX.js} +1 -1
- package/dist/ui/assets/css-DEfus9J5.js +1 -0
- package/dist/ui/assets/{edge-COkalhFi.js → edge-CESgo4ia.js} +1 -1
- package/dist/ui/assets/{elixir-cdlzbYR1.js → elixir-9FKfw4cJ.js} +1 -1
- package/dist/ui/assets/{elm-ZwDYuYpb.js → elm-Dv7A0aLa.js} +1 -1
- package/dist/ui/assets/{erb-C8WG9TtC.js → erb-DHFmDvM0.js} +1 -1
- package/dist/ui/assets/{git-rebase-CMlDVJBT.js → git-rebase-utbU6CzV.js} +1 -1
- package/dist/ui/assets/{glimmer-js-DeLOQlol.js → glimmer-js-t2kiCkyB.js} +1 -1
- package/dist/ui/assets/{glimmer-ts-DTEM04TK.js → glimmer-ts-F0Jv5okV.js} +1 -1
- package/dist/ui/assets/glsl-_ooCjaeB.js +1 -0
- package/dist/ui/assets/graphql-B9LqP-cY.js +1 -0
- package/dist/ui/assets/{hack-C14sh6Lh.js → hack-8yjdbaSA.js} +1 -1
- package/dist/ui/assets/haml-BU5EoZBn.js +1 -0
- package/dist/ui/assets/{handlebars-eS-J0O-M.js → handlebars-BBFEg4Lo.js} +1 -1
- package/dist/ui/assets/{heavy-payload-BKB0QDOI.js → heavy-payload-vGgBRvNX.js} +1 -1
- package/dist/ui/assets/html-D-C6YZk4.js +1 -0
- package/dist/ui/assets/{html-derivative-BlVZU2id.js → html-derivative-DJAQcZyc.js} +1 -1
- package/dist/ui/assets/{http-BmbZzA5x.js → http-Dg5LSYRK.js} +1 -1
- package/dist/ui/assets/{hurl-Dnd_YpOD.js → hurl-Y5uYzMZR.js} +1 -1
- package/dist/ui/assets/java-ppHvycj5.js +1 -0
- package/dist/ui/assets/javascript-DDTjKLlQ.js +1 -0
- package/dist/ui/assets/{jinja-DTvkZdHA.js → jinja-Bt30h8Ik.js} +1 -1
- package/dist/ui/assets/{jison-DUJG-tmh.js → jison-D5uZ1Nyo.js} +1 -1
- package/dist/ui/assets/json-Cw91r8h1.js +1 -0
- package/dist/ui/assets/jsx-04X2FT_1.js +1 -0
- package/dist/ui/assets/{julia-P5B4pHFa.js → julia-76hRaaGz.js} +1 -1
- package/dist/ui/assets/{just-DYaoh7C6.js → just-CDE7W0vW.js} +1 -1
- package/dist/ui/assets/{latex-CI5lnkWV.js → latex-CVO2Byab.js} +1 -1
- package/dist/ui/assets/{liquid-D3LnAs_z.js → liquid-CA-AS3EX.js} +1 -1
- package/dist/ui/assets/lua-CiyBp52Y.js +1 -0
- package/dist/ui/assets/{marko-CRDrjqfS.js → marko-_BWrPfny.js} +1 -1
- package/dist/ui/assets/{mdc-ZzwgmJVn.js → mdc-PyJv85eS.js} +1 -1
- package/dist/ui/assets/{nginx-BAvFXGSV.js → nginx-DAWVw8yu.js} +1 -1
- package/dist/ui/assets/{nim-BHIFawe9.js → nim-CKE1dzpU.js} +1 -1
- package/dist/ui/assets/{perl-C_f5AnLa.js → perl-BBhWva19.js} +1 -1
- package/dist/ui/assets/{php-DDqpegL5.js → php-ChIeaAoF.js} +1 -1
- package/dist/ui/assets/{pug-CSaAZXyd.js → pug-CMgI5afi.js} +1 -1
- package/dist/ui/assets/{qml-CNHvRs_z.js → qml-CjxTkcFH.js} +1 -1
- package/dist/ui/assets/r-DfFga4si.js +1 -0
- package/dist/ui/assets/{razor-BDfAPy7I.js → razor-i4DbHr8p.js} +1 -1
- package/dist/ui/assets/regexp-iC9_nbSI.js +1 -0
- package/dist/ui/assets/{review-payload-D7GIdYDj.js → review-payload-4erWKckt.js} +1 -1
- package/dist/ui/assets/{rst-BzPP2gle.js → rst-oy_97Kl4.js} +1 -1
- package/dist/ui/assets/{ruby-CQjzokzX.js → ruby-C5zYZIyl.js} +1 -1
- package/dist/ui/assets/{sas-Bp37KGr7.js → sas-BnMEh2S3.js} +1 -1
- package/dist/ui/assets/{scrollbar-HUMBdLLK.js → scrollbar-CaOPzUJd.js} +6 -6
- package/dist/ui/assets/scss-BfZXsAWQ.js +1 -0
- package/dist/ui/assets/shellscript-BC2srNaB.js +1 -0
- package/dist/ui/assets/{shellsession-CNc62UhY.js → shellsession-BpE5o7_3.js} +1 -1
- package/dist/ui/assets/{soy-CF44SpBo.js → soy-COesmhTY.js} +1 -1
- package/dist/ui/assets/sql-Ccv_yeUm.js +1 -0
- package/dist/ui/assets/{stata-DVeMA68W.js → stata-CGQEuSZq.js} +1 -1
- package/dist/ui/assets/{surrealql-52sF96Yv.js → surrealql-Bz4JbU-9.js} +1 -1
- package/dist/ui/assets/{svelte-ydwT7UbF.js → svelte-1jM2ejXj.js} +1 -1
- package/dist/ui/assets/{templ-BXcoVoGh.js → templ-C-VwELcp.js} +1 -1
- package/dist/ui/assets/{tex-COsYFp7O.js → tex-t1rUiQCm.js} +1 -1
- package/dist/ui/assets/{ts-tags-CF--LE1s.js → ts-tags-Bewoa6pS.js} +1 -1
- package/dist/ui/assets/tsx-CTXzrBkN.js +1 -0
- package/dist/ui/assets/{twig-YoM-DiI5.js → twig-DVg-vELl.js} +1 -1
- package/dist/ui/assets/typescript--ElHoFkw.js +1 -0
- package/dist/ui/assets/{vue-html-CPdGGk4T.js → vue-html-BHtJ8geX.js} +1 -1
- package/dist/ui/assets/{vue-vine-B5bjgk0a.js → vue-vine-CNSGAWwc.js} +1 -1
- package/dist/ui/assets/{vue-B5LDEy4l.js → vue-wPQ7UlMy.js} +1 -1
- package/dist/ui/assets/workspace-app-CcrHAUIn.css +1 -0
- package/dist/ui/assets/workspace-app-DJmkPYJC.js +1 -0
- package/dist/ui/assets/workspace-app-DkAiSl_0.js +111 -0
- package/dist/ui/assets/workspace-app-QyauBrJX.js +5 -0
- package/dist/ui/assets/workspace-lifecycle-app-BIXEo53I.js +1 -0
- package/dist/ui/assets/xml-JnmX6vyS.js +1 -0
- package/dist/ui/assets/{xsl-wls_CEK_.js → xsl-3_vJ27aE.js} +1 -1
- package/dist/ui/assets/yaml-OAcZkP-w.js +1 -0
- package/dist/ui/workspace-app.html +5 -2
- package/dist/ui/workspace-lifecycle-app.html +18 -0
- package/dist/workspaces.js +11 -0
- package/docs/configuration.md +36 -4
- package/docs/debugging.md +75 -17
- package/docs/gotchas.md +15 -9
- package/docs/setup.md +24 -10
- package/package.json +4 -3
- package/scripts/debug/accept.mjs +79 -27
- package/scripts/debug/host/run.sh +180 -0
- package/scripts/debug/host/serve.mjs +64 -0
- package/scripts/debug/runtime.mjs +57 -2
- package/scripts/debug/runtime.test.mjs +74 -0
- package/scripts/debug/serve.mjs +4 -5
- package/scripts/dev-server.mjs +32 -3
- package/scripts/release/release-gate.test.mjs +43 -0
- package/scripts/release/release-version.test.mjs +107 -0
- package/scripts/release-parity.mjs +70 -46
- package/scripts/release-proof.mjs +2 -2
- package/scripts/release-proof.test.mjs +18 -0
- package/scripts/release-version.mjs +17 -8
- package/dist/ui/assets/angular-html-BT2Z6jee.js +0 -1
- package/dist/ui/assets/c-acnvZ8tm.js +0 -1
- package/dist/ui/assets/cpp-UyrmHXan.js +0 -1
- package/dist/ui/assets/css-D_WCbY6m.js +0 -1
- package/dist/ui/assets/glsl-IJV4SB-M.js +0 -1
- package/dist/ui/assets/graphql-PM-WDnoB.js +0 -1
- package/dist/ui/assets/haml-B_5nS6Kx.js +0 -1
- package/dist/ui/assets/html-C3TPjrC5.js +0 -1
- package/dist/ui/assets/java-ne9HdIVn.js +0 -1
- package/dist/ui/assets/javascript-DpHT58rr.js +0 -1
- package/dist/ui/assets/json-DJmnBdxW.js +0 -1
- package/dist/ui/assets/jsx-BclJnZnN.js +0 -1
- package/dist/ui/assets/lua-dZC7ZQIY.js +0 -1
- package/dist/ui/assets/r-CAfoQND2.js +0 -1
- package/dist/ui/assets/regexp-Mug5jltQ.js +0 -1
- package/dist/ui/assets/scss-C_Z1DYnw.js +0 -1
- package/dist/ui/assets/shellscript-CLfJpn3I.js +0 -1
- package/dist/ui/assets/sql-CYnzfiQ1.js +0 -1
- package/dist/ui/assets/tsx-DLBt2-2f.js +0 -1
- package/dist/ui/assets/typescript-Ce9JGkNI.js +0 -1
- package/dist/ui/assets/workspace-app-Cm9EX5x4.js +0 -117
- package/dist/ui/assets/workspace-app-DHvE2ojW.css +0 -1
- package/dist/ui/assets/xml-Cun8xb0T.js +0 -1
- package/dist/ui/assets/yaml-BxuXn9OL.js +0 -1
- package/scripts/release/tag-local-ci.mjs +0 -144
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
8
|
+
|
|
9
|
+
async function readJson(relativePath) {
|
|
10
|
+
return JSON.parse(await readFile(resolve(repoRoot, relativePath), "utf8"));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
test("release tag Hook is a fast proof gate, not a multi-minute CI runner", async () => {
|
|
14
|
+
const hook = await readJson(".forgerelay/hooks/release-tag-local-ci.json");
|
|
15
|
+
assert.equal(hook.event, "BeforeTool");
|
|
16
|
+
assert.equal(hook.command, "node scripts/release-proof.mjs check-hook");
|
|
17
|
+
assert.ok(hook.timeoutSeconds <= 30);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("release:verify records proof only after the cloud-equivalent parity gate", async () => {
|
|
21
|
+
const pkg = await readJson("package.json");
|
|
22
|
+
assert.equal(
|
|
23
|
+
pkg.scripts["release:verify"],
|
|
24
|
+
"npm run release:parity && node scripts/release-proof.mjs write",
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("release parity mirrors the cloud CI command surface on Node 22.19 and npm 10.9", async () => {
|
|
29
|
+
const source = await readFile(resolve(repoRoot, "scripts/release-parity.mjs"), "utf8");
|
|
30
|
+
assert.match(source, /const NODE_VERSION = "22\.19\.0"/);
|
|
31
|
+
assert.match(source, /const NPM_VERSION = "10\.9\.3"/);
|
|
32
|
+
for (const command of [
|
|
33
|
+
'["npm", "ci", "--no-audit", "--no-fund"]',
|
|
34
|
+
'["npm", "run", "release:check"]',
|
|
35
|
+
'["npm", "run", "typecheck"]',
|
|
36
|
+
'["npm", "test"]',
|
|
37
|
+
'["npm", "run", "build"]',
|
|
38
|
+
'["npm", "run", "lsp:interop"]',
|
|
39
|
+
'["dist/cli.js", "doctor"]',
|
|
40
|
+
]) {
|
|
41
|
+
assert.ok(source.includes(command), `release parity is missing ${command}`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { cp, mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { promisify } from "node:util";
|
|
9
|
+
|
|
10
|
+
const execFileAsync = promisify(execFile);
|
|
11
|
+
const sourceScript = fileURLToPath(new URL("../release-version.mjs", import.meta.url));
|
|
12
|
+
|
|
13
|
+
async function createFixture(t) {
|
|
14
|
+
const root = await mkdtemp(join(tmpdir(), "forgerelay-release-version-"));
|
|
15
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
16
|
+
await mkdir(join(root, "scripts"), { recursive: true });
|
|
17
|
+
await cp(sourceScript, join(root, "scripts", "release-version.mjs"));
|
|
18
|
+
|
|
19
|
+
const pkg = {
|
|
20
|
+
name: "@akira-tl/forgerelay",
|
|
21
|
+
version: "0.5.7",
|
|
22
|
+
repository: { type: "git", url: "git+https://github.com/Akira-TL/forgerelay.git" },
|
|
23
|
+
homepage: "https://github.com/Akira-TL/forgerelay#readme",
|
|
24
|
+
bugs: { url: "https://github.com/Akira-TL/forgerelay/issues" },
|
|
25
|
+
publishConfig: { access: "public", tag: "latest" },
|
|
26
|
+
bin: { forgerelay: "dist/cli.js" },
|
|
27
|
+
files: ["NOTICE.md"],
|
|
28
|
+
};
|
|
29
|
+
const lock = {
|
|
30
|
+
name: pkg.name,
|
|
31
|
+
version: pkg.version,
|
|
32
|
+
lockfileVersion: 3,
|
|
33
|
+
packages: {
|
|
34
|
+
"": {
|
|
35
|
+
name: pkg.name,
|
|
36
|
+
version: pkg.version,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
await Promise.all([
|
|
42
|
+
writeFile(join(root, "package.json"), `${JSON.stringify(pkg, null, 2)}\n`),
|
|
43
|
+
writeFile(join(root, "package-lock.json"), `${JSON.stringify(lock, null, 2)}\n`),
|
|
44
|
+
writeFile(join(root, "CHANGELOG.md"), [
|
|
45
|
+
"# Changelog",
|
|
46
|
+
"",
|
|
47
|
+
"## [Unreleased]",
|
|
48
|
+
"",
|
|
49
|
+
"### Added",
|
|
50
|
+
"",
|
|
51
|
+
"- Release candidate behavior.",
|
|
52
|
+
"",
|
|
53
|
+
"## [0.5.7] - 2026-08-19",
|
|
54
|
+
"",
|
|
55
|
+
"### Fixed",
|
|
56
|
+
"",
|
|
57
|
+
"- Previous release.",
|
|
58
|
+
"",
|
|
59
|
+
].join("\n")),
|
|
60
|
+
writeFile(join(root, "NOTICE.md"), "https://github.com/Waishnav/devspace\nindependently maintained by Akira-TL\n"),
|
|
61
|
+
writeFile(join(root, "LICENSE"), "Copyright (c) 2026 Waishnav\nCopyright (c) 2026 Akira-TL, modifications\n"),
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
return root;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function runRelease(root, ...args) {
|
|
68
|
+
return execFileAsync(process.execPath, [join(root, "scripts", "release-version.mjs"), ...args], {
|
|
69
|
+
cwd: root,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
test("release version tooling prepares and validates an rc release", async (t) => {
|
|
74
|
+
const root = await createFixture(t);
|
|
75
|
+
|
|
76
|
+
const prepared = await runRelease(root, "prepare", "0.6.0-rc.1");
|
|
77
|
+
assert.match(prepared.stdout, /0\.5\.7 -> 0\.6\.0-rc\.1/);
|
|
78
|
+
|
|
79
|
+
const pkg = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
|
|
80
|
+
const lock = JSON.parse(await readFile(join(root, "package-lock.json"), "utf8"));
|
|
81
|
+
const changelog = await readFile(join(root, "CHANGELOG.md"), "utf8");
|
|
82
|
+
assert.equal(pkg.version, "0.6.0-rc.1");
|
|
83
|
+
assert.equal(lock.version, "0.6.0-rc.1");
|
|
84
|
+
assert.equal(lock.packages[""].version, "0.6.0-rc.1");
|
|
85
|
+
assert.match(changelog, /## \[0\.6\.0-rc\.1\] - \d{4}-\d{2}-\d{2}/);
|
|
86
|
+
assert.match(changelog, /### Added\n\n- Release candidate behavior\./);
|
|
87
|
+
|
|
88
|
+
const checked = await runRelease(root, "check");
|
|
89
|
+
assert.match(checked.stdout, /release metadata is consistent at 0\.6\.0-rc\.1/);
|
|
90
|
+
|
|
91
|
+
const tagged = await runRelease(root, "tag", "v0.6.0-rc.1");
|
|
92
|
+
assert.match(tagged.stdout, /release tag v0\.6\.0-rc\.1 matches package version and changelog/);
|
|
93
|
+
|
|
94
|
+
const notes = await runRelease(root, "notes", "v0.6.0-rc.1");
|
|
95
|
+
assert.match(notes.stdout, /Release candidate behavior/);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("release version tooling rejects unsupported prerelease identifiers", async (t) => {
|
|
99
|
+
const root = await createFixture(t);
|
|
100
|
+
await assert.rejects(
|
|
101
|
+
() => runRelease(root, "prepare", "0.6.0-beta.1"),
|
|
102
|
+
(error) => {
|
|
103
|
+
assert.match(String(error.stderr ?? error), /prepare X\.Y\.Z\[-rc\.N\]/);
|
|
104
|
+
return true;
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
});
|
|
@@ -1,52 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
2
4
|
import { cpSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
|
3
5
|
import { dirname, join, resolve } from "node:path";
|
|
4
6
|
import { fileURLToPath } from "node:url";
|
|
5
7
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
+
const NODE_VERSION = "22.19.0";
|
|
9
|
+
const NPM_VERSION = "10.9.3";
|
|
8
10
|
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
11
|
const debugRoot = join(repoRoot, ".forgerelay-debug");
|
|
10
12
|
const sandbox = mkdtempSync(join(ensureDirectory(debugRoot), "release-parity-node22-"));
|
|
11
13
|
const npx = process.platform === "win32" ? "npx.cmd" : "npx";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"src/lsp/language-server-config.test.ts",
|
|
15
|
-
"src/lsp/runtime/semantic-requests.test.ts",
|
|
16
|
-
"src/lsp/operations/request-hardening.server.test.ts",
|
|
17
|
-
"src/lsp/operations/recovery.server.test.ts",
|
|
18
|
-
"src/lsp/operations/lifecycle.server.test.ts",
|
|
19
|
-
];
|
|
14
|
+
|
|
15
|
+
assertCleanReleaseHead();
|
|
20
16
|
|
|
21
17
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
copyTrackedTree(sandbox);
|
|
19
|
+
const env = {
|
|
20
|
+
...process.env,
|
|
21
|
+
FORGERELAY_ALLOWED_ROOTS: sandbox,
|
|
22
|
+
FORGERELAY_OAUTH_OWNER_TOKEN: "ci-owner-token-that-is-long-enough",
|
|
23
|
+
FORGERELAY_PUBLIC_BASE_URL: "http://127.0.0.1:7676",
|
|
24
|
+
};
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
["--yes", "-p", `node@${minimumNode}`, "-p", `npm@${npmVersion}`, "--", "npm", "ci", "--no-audit", "--no-fund"],
|
|
31
|
-
`Node ${minimumNode} isolated npm ci`,
|
|
26
|
+
runNodeNpm(
|
|
32
27
|
sandbox,
|
|
28
|
+
env,
|
|
29
|
+
["npm", "ci", "--no-audit", "--no-fund"],
|
|
30
|
+
`Node ${NODE_VERSION} / npm ${NPM_VERSION} install`,
|
|
33
31
|
);
|
|
32
|
+
runNodeNpm(sandbox, env, ["npm", "run", "release:check"], "Release metadata");
|
|
33
|
+
runNodeNpm(sandbox, env, ["npm", "run", "typecheck"], "Typecheck");
|
|
34
|
+
runNodeNpm(sandbox, env, ["npm", "test"], "Full test suite");
|
|
35
|
+
runNodeNpm(sandbox, env, ["npm", "run", "build"], "Build");
|
|
36
|
+
runNodeNpm(sandbox, env, ["npm", "run", "lsp:interop"], "Optional LSP interoperability");
|
|
37
|
+
runNode(sandbox, env, ["dist/cli.js", "doctor"], "Doctor");
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"--yes",
|
|
38
|
-
`node@${minimumNode}`,
|
|
39
|
-
"--import",
|
|
40
|
-
"tsx",
|
|
41
|
-
"--test",
|
|
42
|
-
"--test-concurrency=1",
|
|
43
|
-
...highRiskTests,
|
|
44
|
-
],
|
|
45
|
-
`Node ${minimumNode} high-risk parity tests`,
|
|
46
|
-
sandbox,
|
|
39
|
+
console.log(
|
|
40
|
+
`Release parity passed with the cloud CI command surface on Node ${NODE_VERSION} / npm ${NPM_VERSION}.`,
|
|
47
41
|
);
|
|
48
|
-
|
|
49
|
-
console.log(`Release parity passed in an isolated Node ${minimumNode} sandbox.`);
|
|
50
42
|
} finally {
|
|
51
43
|
rmSync(sandbox, {
|
|
52
44
|
recursive: true,
|
|
@@ -56,30 +48,62 @@ try {
|
|
|
56
48
|
});
|
|
57
49
|
}
|
|
58
50
|
|
|
51
|
+
function git(args) {
|
|
52
|
+
return execFileSync("git", args, {
|
|
53
|
+
cwd: repoRoot,
|
|
54
|
+
encoding: "utf8",
|
|
55
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
56
|
+
}).trim();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function assertCleanReleaseHead() {
|
|
60
|
+
const status = git(["status", "--porcelain", "--untracked-files=all"]);
|
|
61
|
+
if (status) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
"release parity requires a clean committed release HEAD; commit or remove every release input first",
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
59
68
|
function ensureDirectory(path) {
|
|
60
69
|
mkdirSync(path, { recursive: true });
|
|
61
70
|
return `${path}/`;
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
73
|
+
function copyTrackedTree(destinationRoot) {
|
|
74
|
+
const files = execFileSync("git", ["ls-files", "-z"], {
|
|
75
|
+
cwd: repoRoot,
|
|
76
|
+
encoding: "utf8",
|
|
77
|
+
}).split("\0").filter(Boolean);
|
|
78
|
+
for (const relativePath of files) {
|
|
79
|
+
const source = join(repoRoot, relativePath);
|
|
80
|
+
const destination = join(destinationRoot, relativePath);
|
|
81
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
82
|
+
cpSync(source, destination, { recursive: true, force: true });
|
|
83
|
+
}
|
|
69
84
|
}
|
|
70
85
|
|
|
71
|
-
function
|
|
86
|
+
function runNodeNpm(cwd, env, command, label) {
|
|
87
|
+
run(
|
|
88
|
+
cwd,
|
|
89
|
+
env,
|
|
90
|
+
["--yes", "-p", `node@${NODE_VERSION}`, "-p", `npm@${NPM_VERSION}`, "--", ...command],
|
|
91
|
+
label,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function runNode(cwd, env, args, label) {
|
|
96
|
+
run(cwd, env, ["--yes", `node@${NODE_VERSION}`, ...args], label);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function run(cwd, env, args, label) {
|
|
72
100
|
console.log(`\n== ${label} ==`);
|
|
73
101
|
const result = spawnSync(npx, args, {
|
|
74
102
|
cwd,
|
|
75
|
-
env
|
|
103
|
+
env,
|
|
76
104
|
stdio: "inherit",
|
|
77
105
|
windowsHide: true,
|
|
78
106
|
});
|
|
79
107
|
if (result.error) throw result.error;
|
|
80
|
-
if (result.status !== 0) {
|
|
81
|
-
console.error(`${label} failed with exit ${result.status ?? "unknown"}.`);
|
|
82
|
-
process.exitCode = result.status ?? 1;
|
|
83
|
-
throw new Error(`${label} failed.`);
|
|
84
|
-
}
|
|
108
|
+
if (result.status !== 0) throw new Error(`${label} failed with exit ${result.status ?? "unknown"}`);
|
|
85
109
|
}
|
|
@@ -91,9 +91,9 @@ function hookTag() {
|
|
|
91
91
|
throw new Error("FORGERELAY_HOOK_PAYLOAD is not valid JSON");
|
|
92
92
|
}
|
|
93
93
|
const command = typeof payload.command === "string" ? payload.command : "";
|
|
94
|
-
const match = /git\s+push\s+origin\s+(v\d+\.\d+\.\d+)/.exec(command);
|
|
94
|
+
const match = /git\s+push\s+origin\s+(v\d+\.\d+\.\d+(?:-rc\.\d+)?)/.exec(command);
|
|
95
95
|
if (!match?.[1]) {
|
|
96
|
-
throw new Error("release Hook payload does not contain a
|
|
96
|
+
throw new Error("release Hook payload does not contain a release tag push");
|
|
97
97
|
}
|
|
98
98
|
return match[1];
|
|
99
99
|
}
|
|
@@ -77,6 +77,24 @@ test("release proof binds a successful local verification to the exact tag HEAD"
|
|
|
77
77
|
);
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
+
test("release proof accepts an rc tag for the verified package version", async (t) => {
|
|
81
|
+
const root = await mkdtemp(join(tmpdir(), "forgerelay-release-proof-"));
|
|
82
|
+
t.after(() => rm(root, { recursive: true, force: true }));
|
|
83
|
+
await writeFile(join(root, "package.json"), JSON.stringify({ version: "0.6.0-rc.1" }) + "\n");
|
|
84
|
+
await git(root, ["init"]);
|
|
85
|
+
await git(root, ["config", "user.email", "proof@example.com"]);
|
|
86
|
+
await git(root, ["config", "user.name", "Release Proof Test"]);
|
|
87
|
+
await git(root, ["add", "."]);
|
|
88
|
+
await git(root, ["commit", "-m", "release 0.6.0-rc.1"]);
|
|
89
|
+
await runProof(root, "write");
|
|
90
|
+
await git(root, ["tag", "v0.6.0-rc.1"]);
|
|
91
|
+
|
|
92
|
+
const checked = await runProof(root, "check-hook", {
|
|
93
|
+
FORGERELAY_HOOK_PAYLOAD: JSON.stringify({ command: "git push origin v0.6.0-rc.1" }),
|
|
94
|
+
});
|
|
95
|
+
assert.match(checked.stdout, /Release proof OK: v0\.6\.0-rc\.1/);
|
|
96
|
+
});
|
|
97
|
+
|
|
80
98
|
test("release proof rejects a mismatched tag without invoking a remote", async (t) => {
|
|
81
99
|
const root = await mkdtemp(join(tmpdir(), "forgerelay-release-proof-"));
|
|
82
100
|
t.after(() => rm(root, { recursive: true, force: true }));
|
|
@@ -9,6 +9,7 @@ const changelogPath = resolve(repoRoot, "CHANGELOG.md");
|
|
|
9
9
|
const noticePath = resolve(repoRoot, "NOTICE.md");
|
|
10
10
|
const licensePath = resolve(repoRoot, "LICENSE");
|
|
11
11
|
const stableVersionPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
12
|
+
const releaseVersionPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-rc\.(0|[1-9]\d*))?$/;
|
|
12
13
|
const expectedPackageName = "@akira-tl/forgerelay";
|
|
13
14
|
const expectedRepositoryUrl = "git+https://github.com/Akira-TL/forgerelay.git";
|
|
14
15
|
const expectedHomepage = "https://github.com/Akira-TL/forgerelay#readme";
|
|
@@ -26,7 +27,7 @@ switch (command) {
|
|
|
26
27
|
break;
|
|
27
28
|
case "tag": {
|
|
28
29
|
checkState(state);
|
|
29
|
-
if (!value) fail("usage: node scripts/release-version.mjs tag vX.Y.Z");
|
|
30
|
+
if (!value) fail("usage: node scripts/release-version.mjs tag vX.Y.Z[-rc.N]");
|
|
30
31
|
if (getUnreleasedBody(state.changelog)) {
|
|
31
32
|
fail("CHANGELOG.md still has Unreleased changes; prepare the next version before creating a release tag");
|
|
32
33
|
}
|
|
@@ -37,6 +38,14 @@ switch (command) {
|
|
|
37
38
|
console.log(`release tag ${value} matches package version and changelog`);
|
|
38
39
|
break;
|
|
39
40
|
}
|
|
41
|
+
case "prepare": {
|
|
42
|
+
checkState(state);
|
|
43
|
+
if (!value || !releaseVersionPattern.test(value)) {
|
|
44
|
+
fail("usage: node scripts/release-version.mjs prepare X.Y.Z[-rc.N] [--dry-run]");
|
|
45
|
+
}
|
|
46
|
+
await prepareRelease(state, value, dryRun);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
40
49
|
case "next": {
|
|
41
50
|
checkState(state);
|
|
42
51
|
const bump = value ?? "patch";
|
|
@@ -48,10 +57,10 @@ switch (command) {
|
|
|
48
57
|
}
|
|
49
58
|
case "notes": {
|
|
50
59
|
checkState(state);
|
|
51
|
-
if (!value) fail("usage: node scripts/release-version.mjs notes vX.Y.Z");
|
|
60
|
+
if (!value) fail("usage: node scripts/release-version.mjs notes vX.Y.Z[-rc.N]");
|
|
52
61
|
const version = value.startsWith("v") ? value.slice(1) : value;
|
|
53
|
-
if (!
|
|
54
|
-
fail(`release notes version ${JSON.stringify(value)} must be vX.Y.Z or X.Y.Z`);
|
|
62
|
+
if (!releaseVersionPattern.test(version)) {
|
|
63
|
+
fail(`release notes version ${JSON.stringify(value)} must be vX.Y.Z[-rc.N] or X.Y.Z[-rc.N]`);
|
|
55
64
|
}
|
|
56
65
|
const body = getReleaseBody(state.changelog, version);
|
|
57
66
|
if (!body) fail(`CHANGELOG.md has no release notes for ${version}`);
|
|
@@ -59,7 +68,7 @@ switch (command) {
|
|
|
59
68
|
break;
|
|
60
69
|
}
|
|
61
70
|
default:
|
|
62
|
-
fail(`unknown release command ${JSON.stringify(command)}; expected check, tag, next, or notes`);
|
|
71
|
+
fail(`unknown release command ${JSON.stringify(command)}; expected check, tag, prepare, next, or notes`);
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
async function readState() {
|
|
@@ -87,8 +96,8 @@ function checkState(state) {
|
|
|
87
96
|
if (state.pkg.name !== expectedPackageName) {
|
|
88
97
|
fail(`unexpected package name ${JSON.stringify(state.pkg.name)}; expected ${expectedPackageName}`);
|
|
89
98
|
}
|
|
90
|
-
if (typeof version !== "string" || !
|
|
91
|
-
fail(`package version ${JSON.stringify(version)} must be
|
|
99
|
+
if (typeof version !== "string" || !releaseVersionPattern.test(version)) {
|
|
100
|
+
fail(`package version ${JSON.stringify(version)} must be X.Y.Z or X.Y.Z-rc.N`);
|
|
92
101
|
}
|
|
93
102
|
if (state.pkg.repository?.url !== expectedRepositoryUrl) {
|
|
94
103
|
fail(`package repository.url must be ${expectedRepositoryUrl} for GitHub/npm trusted publishing`);
|
|
@@ -162,7 +171,7 @@ async function prepareRelease(state, nextVersion, dryRun) {
|
|
|
162
171
|
|
|
163
172
|
console.log(`${state.pkg.version} -> ${nextVersion}`);
|
|
164
173
|
console.log("updated package.json, package-lock.json, and CHANGELOG.md");
|
|
165
|
-
console.log("next: review the diff, commit the release-ready tree, run npm run release:verify on that clean HEAD, then push the matching
|
|
174
|
+
console.log("next: review the diff, commit the release-ready tree, run npm run release:verify on that clean HEAD, then push the matching release tag");
|
|
166
175
|
}
|
|
167
176
|
|
|
168
177
|
function promoteUnreleased(changelog, nextVersion) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as e}from"./workspace-app-Cm9EX5x4.js";import{t}from"./html-C3TPjrC5.js";var n=[Object.freeze(JSON.parse('{"injectionSelector":"L:text.html -comment","name":"angular-expression","patterns":[{"include":"#ngExpression"}],"repository":{"arrayLiteral":{"begin":"\\\\[","beginCaptures":{"0":{"name":"meta.brace.square.ts"}},"end":"]","endCaptures":{"0":{"name":"meta.brace.square.ts"}},"name":"meta.array.literal.ts","patterns":[{"include":"#ngExpression"},{"include":"#punctuationComma"}]},"booleanLiteral":{"patterns":[{"match":"(?<![$.])\\\\btrue\\\\b(?!\\\\$)","name":"constant.language.boolean.true.ts"},{"match":"(?<![$.])\\\\bfalse\\\\b(?!\\\\$)","name":"constant.language.boolean.false.ts"}]},"expressionOperator":{"patterns":[{"captures":{"1":{"name":"keyword.operator.logical.ts"},"2":{"name":"entity.name.function.pipe.ng"}},"match":"((?<!\\\\|)\\\\|(?!\\\\|))\\\\s?([-$0-9A-Z_a-z]*)"},{"match":"(?<![$.])\\\\b(let)\\\\b(?!\\\\$)","name":"storage.type.ts"},{"match":"(?<![$.])\\\\b(await)\\\\b(?!\\\\$)","name":"keyword.control.flow.ts"},{"match":"(?<![$.])\\\\bdelete\\\\b(?!\\\\$)","name":"keyword.operator.expression.delete.ts"},{"match":"(?<![$.])\\\\bin\\\\b(?!\\\\$)","name":"keyword.operator.expression.in.ts"},{"match":"(?<![$.])\\\\bof\\\\b(?!\\\\$)","name":"keyword.operator.expression.of.ts"},{"match":"(?<![$.])\\\\bif\\\\b(?!\\\\$)","name":"keyword.control.if.ts"},{"match":"(?<![$.])\\\\belse\\\\b(?!\\\\$)","name":"keyword.control.else.ts"},{"match":"(?<![$.])\\\\bthen\\\\b(?!\\\\$)","name":"keyword.control.then.ts"},{"match":"(?<![$.])\\\\binstanceof\\\\b(?!\\\\$)","name":"keyword.operator.expression.instanceof.ts"},{"match":"(?<![$.])\\\\bnew\\\\b(?!\\\\$)","name":"keyword.operator.new.ts"},{"match":"(?<![$.])\\\\bvoid\\\\b(?!\\\\$)","name":"keyword.operator.expression.void.ts"},{"begin":"(?<![$.])\\\\bas\\\\b(?!\\\\$)","beginCaptures":{"0":{"name":"storage.type.as.ts"}},"end":"(?=$|[]\\"\'),:;}])","patterns":[{"include":"#type"}]},{"match":"(?:\\\\*|(?<!\\\\()/|[-%+])=","name":"keyword.operator.assignment.compound.ts"},{"match":"(?:[\\\\&^]|<<|>>>??|\\\\|)=","name":"keyword.operator.assignment.compound.bitwise.ts"},{"match":"<<|>>>?","name":"keyword.operator.bitwise.shift.ts"},{"match":"[!=]==?","name":"keyword.operator.comparison.ts"},{"match":"<=|>=|<>|[<>]","name":"keyword.operator.relational.ts"},{"match":"!|&&|\\\\?\\\\?|\\\\|\\\\|","name":"keyword.operator.logical.ts"},{"match":"[\\\\&^|~]","name":"keyword.operator.bitwise.ts"},{"match":"=","name":"keyword.operator.assignment.ts"},{"match":"--","name":"keyword.operator.decrement.ts"},{"match":"\\\\+\\\\+","name":"keyword.operator.increment.ts"},{"match":"[-%*+/]","name":"keyword.operator.arithmetic.ts"},{"captures":{"1":{"name":"keyword.operator.arithmetic.ts"}},"match":"(?<=[$_[:alnum:]])\\\\s*(/)(?![*/])"},{"include":"#typeofOperator"}]},"functionCall":{"begin":"(?=(\\\\??\\\\.\\\\s*)?([$_[:alpha:]][$_[:alnum:]]*)\\\\s*(<([^<>]|<[^<>]+>)+>\\\\s*)?\\\\()","end":"(?<=\\\\))(?!(\\\\??\\\\.\\\\s*)?([$_[:alpha:]][$_[:alnum:]]*)\\\\s*(<([^<>]|<[^<>]+>)+>\\\\s*)?\\\\()","patterns":[{"match":"\\\\?","name":"punctuation.accessor.ts"},{"match":"\\\\.","name":"punctuation.accessor.ts"},{"match":"([$_[:alpha:]][$_[:alnum:]]*)","name":"entity.name.function.ts"},{"begin":"<","beginCaptures":{"0":{"name":"punctuation.definition.typeparameters.begin.ts"}},"end":">","endCaptures":{"0":{"name":"punctuation.definition.typeparameters.end.ts"}},"name":"meta.type.parameters.ts","patterns":[{"include":"#type"},{"include":"#punctuationComma"}]},{"include":"#parenExpression"}]},"functionParameters":{"begin":"\\\\(","beginCaptures":{"0":{"name":"punctuation.definition.parameters.begin.ts"}},"end":"\\\\)","endCaptures":{"0":{"name":"punctuation.definition.parameters.end.ts"}},"name":"meta.parameters.ts","patterns":[{"include":"#decorator"},{"include":"#parameterName"},{"include":"#variableInitializer"},{"match":",","name":"punctuation.separator.parameter.ts"}]},"identifiers":{"patterns":[{"match":"([$_[:alpha:]][$_[:alnum:]]*)(?=\\\\s*\\\\.\\\\s*prototype\\\\b(?!\\\\$))","name":"support.class.ts"},{"captures":{"1":{"name":"punctuation.accessor.ts"},"2":{"name":"constant.other.object.property.ts"},"3":{"name":"variable.other.object.property.ts"}},"match":"([!?]?\\\\.)\\\\s*(?:(\\\\p{upper}[$_\\\\d[:upper:]]*)|([$_[:alpha:]][$_[:alnum:]]*))(?=\\\\s*\\\\.\\\\s*[$_[:alpha:]][$_[:alnum:]]*)"},{"captures":{"1":{"name":"punctuation.accessor.ts"},"2":{"name":"entity.name.function.ts"}},"match":"(?:([!?]?\\\\.)\\\\s*)?([$_[:alpha:]][$_[:alnum:]]*)(?=\\\\s*=\\\\s*((async\\\\s+)|(function\\\\s*[(<])|(function\\\\s+)|([$_[:alpha:]][$_[:alnum:]]*\\\\s*=>)|((<([^<>]|<[^<>]+>)+>\\\\s*)?\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)(\\\\s*:\\\\s*(.)*)?\\\\s*=>)))"},{"captures":{"1":{"name":"punctuation.accessor.ts"},"2":{"name":"constant.other.property.ts"}},"match":"([!?]?\\\\.)\\\\s*(\\\\p{upper}[$_\\\\d[:upper:]]*)(?![$_[:alnum:]])"},{"captures":{"1":{"name":"punctuation.accessor.ts"},"2":{"name":"variable.other.property.ts"}},"match":"([!?]?\\\\.)\\\\s*([$_[:alpha:]][$_[:alnum:]]*)"},{"captures":{"1":{"name":"constant.other.object.ts"},"2":{"name":"variable.other.object.ts"}},"match":"(?:(\\\\p{upper}[$_\\\\d[:upper:]]*)|([$_[:alpha:]][$_[:alnum:]]*))(?=\\\\s*\\\\.\\\\s*[$_[:alpha:]][$_[:alnum:]]*)"},{"match":"(\\\\p{upper}[$_\\\\d[:upper:]]*)(?![$_[:alnum:]])","name":"constant.character.other"},{"match":"[$_[:alpha:]][$_[:alnum:]]*","name":"variable.other.readwrite.ts"}]},"literal":{"name":"literal.ts","patterns":[{"include":"#numericLiteral"},{"include":"#booleanLiteral"},{"include":"#nullLiteral"},{"include":"#undefinedLiteral"},{"include":"#numericConstantLiteral"},{"include":"#arrayLiteral"},{"include":"#thisLiteral"}]},"ngExpression":{"name":"meta.expression.ng","patterns":[{"include":"#string"},{"include":"#literal"},{"include":"#ternaryExpression"},{"include":"#expressionOperator"},{"include":"#functionCall"},{"include":"#identifiers"},{"include":"#parenExpression"},{"include":"#punctuationComma"},{"include":"#punctuationSemicolon"},{"include":"#punctuationAccessor"}]},"nullLiteral":{"match":"(?<![$.])\\\\bnull\\\\b(?!\\\\$)","name":"constant.language.null.ts"},"numericConstantLiteral":{"patterns":[{"match":"(?<![$.])\\\\bNaN\\\\b(?!\\\\$)","name":"constant.language.nan.ts"},{"match":"(?<![$.])\\\\bInfinity\\\\b(?!\\\\$)","name":"constant.language.infinity.ts"}]},"numericLiteral":{"patterns":[{"match":"\\\\b(?<!\\\\$)0([Xx])\\\\h+\\\\b(?!\\\\$)","name":"constant.numeric.hex.ts"},{"match":"\\\\b(?<!\\\\$)0([Bb])[01]+\\\\b(?!\\\\$)","name":"constant.numeric.binary.ts"},{"match":"\\\\\\\\b(?<!\\\\$)0([Oo])?[0-7]+\\\\b(?!\\\\$)","name":"constant.numeric.octal.ts"},{"captures":{"0":{"name":"constant.numeric.decimal.ts"},"1":{"name":"meta.delimiter.decimal.period.ts"},"2":{"name":"meta.delimiter.decimal.period.ts"},"3":{"name":"meta.delimiter.decimal.period.ts"},"4":{"name":"meta.delimiter.decimal.period.ts"},"5":{"name":"meta.delimiter.decimal.period.ts"},"6":{"name":"meta.delimiter.decimal.period.ts"}},"match":"(?<!\\\\$)(?:\\\\b[0-9]+(\\\\.)[0-9]+[Ee][-+]?[0-9]+\\\\b|\\\\b[0-9]+(\\\\.)[Ee][-+]?[0-9]+\\\\b|\\\\B(\\\\.)[0-9]+[Ee][-+]?[0-9]+\\\\b|\\\\b[0-9]+[Ee][-+]?[0-9]+\\\\b|\\\\b[0-9]+(\\\\.)\\\\B|\\\\B(\\\\.)[0-9]+\\\\b|\\\\b[0-9]+\\\\b(?!\\\\.))(?!\\\\$)"}]},"parameterName":{"patterns":[{"captures":{"1":{"name":"storage.modifier.ts"},"2":{"name":"storage.modifier.ts"},"3":{"name":"keyword.operator.rest.ts"},"4":{"name":"entity.name.function.ts"},"5":{"name":"keyword.operator.optional.ts"}},"match":"(?:\\\\s*\\\\b(readonly)\\\\s+)?(?:\\\\s*\\\\b(p(?:ublic|rivate|rotected))\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<![:=])([$_[:alpha:]][$_[:alnum:]]*)\\\\s*(\\\\??)(?=\\\\s*(=\\\\s*((async\\\\s+)|(function\\\\s*[(<])|(function\\\\s+)|([$_[:alpha:]][$_[:alnum:]]*\\\\s*=>)|((<([^<>]|<[^<>]+>)+>\\\\s*)?\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)(\\\\s*:\\\\s*(.)*)?\\\\s*=>)))|(:\\\\s*((<)|(\\\\(\\\\s*((\\\\))|(\\\\.\\\\.\\\\.)|([$_[:alnum:]]+\\\\s*(([,:=?])|(\\\\)\\\\s*=>))))))))"},{"captures":{"1":{"name":"storage.modifier.ts"},"2":{"name":"storage.modifier.ts"},"3":{"name":"keyword.operator.rest.ts"},"4":{"name":"variable.parameter.ts"},"5":{"name":"keyword.operator.optional.ts"}},"match":"(?:\\\\s*\\\\b(readonly)\\\\s+)?(?:\\\\s*\\\\b(p(?:ublic|rivate|rotected))\\\\s+)?(\\\\.\\\\.\\\\.)?\\\\s*(?<![:=])([$_[:alpha:]][$_[:alnum:]]*)\\\\s*(\\\\??)"}]},"parenExpression":{"begin":"\\\\(","beginCaptures":{"0":{"name":"meta.brace.round.ts"}},"end":"\\\\)","endCaptures":{"0":{"name":"meta.brace.round.ts"}},"patterns":[{"include":"#ngExpression"},{"include":"#punctuationComma"}]},"punctuationAccessor":{"match":"(?:\\\\?|!?)\\\\.","name":"punctuation.accessor.ts"},"punctuationComma":{"match":",","name":"punctuation.separator.comma.ts"},"punctuationSemicolon":{"match":";","name":"punctuation.terminator.statement.ts"},"qstringDouble":{"begin":"\\"","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.ts"}},"end":"(\\")|([^\\\\n\\\\\\\\])$","endCaptures":{"1":{"name":"punctuation.definition.string.end.ts"},"2":{"name":"invalid.illegal.newline.ts"}},"name":"string.quoted.double.ts","patterns":[{"include":"#stringCharacterEscape"}]},"qstringSingle":{"begin":"\'","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.ts"}},"end":"(\')|([^\\\\n\\\\\\\\])$","endCaptures":{"1":{"name":"punctuation.definition.string.end.ts"},"2":{"name":"invalid.illegal.newline.ts"}},"name":"string.quoted.single.ts","patterns":[{"include":"#stringCharacterEscape"}]},"string":{"patterns":[{"include":"#qstringSingle"},{"include":"#qstringDouble"},{"include":"#templateLiteral"}]},"stringCharacterEscape":{"match":"\\\\\\\\(x\\\\h{2}|[012][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)","name":"constant.character.escape.ts"},"templateLiteral":{"patterns":[{"include":"#templateLiteralCall"},{"begin":"([$_[:alpha:]][$_[:alnum:]]*)?(`)","beginCaptures":{"1":{"name":"entity.name.function.tagged-template.ts"},"2":{"name":"string.template.ts punctuation.definition.string.template.begin.ts"}},"contentName":"string.template.ts","end":"`","endCaptures":{"0":{"name":"string.template.ts punctuation.definition.string.template.end.ts"}},"patterns":[{"include":"#templateLiteralSubstitutionElement"},{"include":"#stringCharacterEscape"}]}]},"templateLiteralCall":{"patterns":[{"begin":"(?=(([$_[:alpha:]][$_[:alnum:]]*\\\\s*\\\\??\\\\.\\\\s*)*|(\\\\??\\\\.\\\\s*)?)([$_[:alpha:]][$_[:alnum:]]*)(<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>|<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))(([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>|<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>)*(?<!=)>))*(?<!=)>)*(?<!=)>\\\\s*)?`)","end":"(?=`)","patterns":[{"begin":"(?=(([$_[:alpha:]][$_[:alnum:]]*\\\\s*\\\\??\\\\.\\\\s*)*|(\\\\??\\\\.\\\\s*)?)([$_[:alpha:]][$_[:alnum:]]*))","end":"(?=(<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>|<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))(([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>|<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>)*(?<!=)>))*(?<!=)>)*(?<!=)>\\\\s*)?`)","patterns":[{"include":"#support-function-call-identifiers"},{"match":"([$_[:alpha:]][$_[:alnum:]]*)","name":"entity.name.function.tagged-template.ts"}]},{"include":"#typeArguments"}]},{"begin":"([$_[:alpha:]][$_[:alnum:]]*)?\\\\s*(?=(<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>|<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))(([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>|<\\\\s*(((keyof|infer|typeof|readonly)\\\\s+)|(([$_[:alpha:]][$_[:alnum:]]*|(\\\\{([^{}]|(\\\\{([^{}]|\\\\{[^{}]*})*}))*})|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(\\\\[([^]\\\\[]|(\\\\[([^]\\\\[]|\\\\[[^]\\\\[]*])*]))*])|(\'([^\'\\\\\\\\]|\\\\\\\\.)*\')|(\\"([^\\"\\\\\\\\]|\\\\\\\\.)*\\")|(`([^\\\\\\\\`]|\\\\\\\\.)*`))(?=\\\\s*([,.<>\\\\[]|=>|&(?!&)|\\\\|(?!\\\\|)))))([^(<>]|(\\\\(([^()]|(\\\\(([^()]|\\\\([^()]*\\\\))*\\\\)))*\\\\))|(?<==)>)*(?<!=)>))*(?<!=)>)*(?<!=)>\\\\s*)`)","beginCaptures":{"1":{"name":"entity.name.function.tagged-template.ts"}},"end":"(?=`)","patterns":[{"include":"#typeArguments"}]}]},"templateLiteralSubstitutionElement":{"begin":"\\\\$\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.template-expression.begin.ts"}},"contentName":"meta.embedded.line.ts","end":"}","endCaptures":{"0":{"name":"punctuation.definition.template-expression.end.ts"}},"name":"meta.template.expression.ts","patterns":[{"include":"#ngExpression"}]},"ternaryExpression":{"begin":"(?!\\\\?\\\\.\\\\s*\\\\D)(\\\\?)(?!\\\\?)","beginCaptures":{"1":{"name":"keyword.operator.ternary.ts"}},"end":"\\\\s*(:)","endCaptures":{"1":{"name":"keyword.operator.ternary.ts"}},"patterns":[{"include":"#ngExpression"}]},"thisLiteral":{"match":"(?<![$.])\\\\bthis\\\\b(?!\\\\$)","name":"variable.language.this.ts"},"type":{"name":"meta.type.ts","patterns":[{"include":"#string"},{"include":"#numericLiteral"},{"include":"#typeBuiltinLiterals"},{"include":"#typeTuple"},{"include":"#typeObject"},{"include":"#typeOperators"},{"include":"#typeFnTypeParameters"},{"include":"#typeParenOrFunctionParameters"},{"include":"#typeName"}]},"typeAnnotation":{"begin":":","beginCaptures":{"0":{"name":"keyword.operator.type.annotation.ts"}},"end":"(?=$|[]),;}]|//|\\")|(?==[^>])|(?<=[]$)>_}[:alpha:]])\\\\s*(?=\\\\{)","name":"meta.type.annotation.ts","patterns":[{"include":"#type"}]},"typeArguments":{"begin":"<","beginCaptures":{"0":{"name":"punctuation.definition.typeparameters.begin.ts"}},"end":">","endCaptures":{"0":{"name":"punctuation.definition.typeparameters.end.ts"}},"name":"meta.type.parameters.ts","patterns":[{"include":"#typeArgumentsBody"}]},"typeArgumentsBody":{"patterns":[{"captures":{"0":{"name":"keyword.operator.type.ts"}},"match":"(?<![$_[:alnum:]])(?:(?<=\\\\.\\\\.\\\\.)|(?<!\\\\.))(_)(?![$_[:alnum:]])(?:(?=\\\\.\\\\.\\\\.)|(?!\\\\.))"},{"include":"#type"},{"include":"#punctuationComma"}]},"typeBuiltinLiterals":{"match":"(?<![$.])\\\\b(this|true|false|undefined|null)\\\\b(?!\\\\$)","name":"support.type.builtin.ts"},"typeFnTypeParameters":{"patterns":[{"captures":{"1":{"name":"keyword.control.new.ts"}},"match":"(?<![$.])\\\\b(new)\\\\b(?=\\\\s*<)","name":"meta.type.constructor.ts"},{"begin":"(?<![$.])\\\\b(new)\\\\b\\\\s*(?=\\\\()","beginCaptures":{"1":{"name":"keyword.control.new.ts"}},"end":"(?<=\\\\))","name":"meta.type.constructor.ts","patterns":[{"include":"#functionParameters"}]},{"begin":"(?<=>)\\\\s*(?=\\\\()","end":"(?<=\\\\))","include":"#typeofOperator","name":"meta.type.function.ts","patterns":[{"include":"#functionParameters"}]},{"begin":"((?=\\\\(\\\\s*((\\\\))|(\\\\.\\\\.\\\\.)|([$_[:alnum:]]+\\\\s*(([,:=?])|(\\\\)\\\\s*=>))))))","end":"(?<=\\\\))","name":"meta.type.function.ts","patterns":[{"include":"#functionParameters"}]}]},"typeName":{"patterns":[{"captures":{"1":{"name":"entity.name.type.module.ts"},"2":{"name":"punctuation.accessor.ts"}},"match":"([$_[:alpha:]][$_[:alnum:]]*)\\\\s*([!?]?\\\\.)"},{"match":"[$_[:alpha:]][$_[:alnum:]]*","name":"entity.name.type.ts"}]},"typeObject":{"begin":"\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.block.ts"}},"end":"}","endCaptures":{"0":{"name":"punctuation.definition.block.ts"}},"name":"meta.object.type.ts","patterns":[{"include":"#typeObjectMembers"}]},"typeObjectMembers":{"patterns":[{"include":"#typeAnnotation"},{"include":"#punctuationComma"},{"include":"#punctuationSemicolon"}]},"typeOperators":{"patterns":[{"include":"#typeofOperator"},{"match":"[\\\\&|]","name":"keyword.operator.type.ts"},{"match":"(?<![$.])\\\\bkeyof\\\\b(?!\\\\$)","name":"keyword.operator.expression.keyof.ts"}]},"typeParenOrFunctionParameters":{"begin":"\\\\(","beginCaptures":{"0":{"name":"meta.brace.round.ts"}},"end":"\\\\)","endCaptures":{"0":{"name":"meta.brace.round.ts"}},"name":"meta.type.paren.cover.ts","patterns":[{"include":"#type"},{"include":"#functionParameters"}]},"typeTuple":{"begin":"\\\\[","beginCaptures":{"0":{"name":"meta.brace.square.ts"}},"end":"]","endCaptures":{"0":{"name":"meta.brace.square.ts"}},"name":"meta.type.tuple.ts","patterns":[{"include":"#type"},{"include":"#punctuationComma"}]},"typeofOperator":{"match":"(?<![$.])\\\\btypeof\\\\b(?!\\\\$)","name":"keyword.operator.expression.typeof.ts"},"undefinedLiteral":{"match":"(?<![$.])\\\\bundefined\\\\b(?!\\\\$)","name":"constant.language.undefined.ts"},"variableInitializer":{"begin":"(?<![!=])(=)(?!=)","beginCaptures":{"1":{"name":"keyword.operator.assignment.ts"}},"end":"(?=$|[]),;}])","patterns":[{"include":"#ngExpression"}]}},"scopeName":"expression.ng"}'))],r=Object.freeze(JSON.parse(`{"injectTo":["text.html.derivative","text.html.derivative.ng","source.ts.ng"],"injectionSelector":"L:text.html -comment -expression.ng -meta.tag -source.css -source.js","name":"angular-let-declaration","patterns":[{"include":"#letDeclaration"}],"repository":{"letDeclaration":{"begin":"(@let)\\\\s+([$_[:alpha:]][$_[:alnum:]]*)\\\\s*(=)?","beginCaptures":{"1":{"name":"storage.type.ng"},"2":{"name":"variable.other.constant.ng"},"3":{"name":"keyword.operator.assignment.ng"}},"end":"(?<=;)","name":"meta.definition.variable.ng","patterns":[{"include":"#letInitializer"}]},"letInitializer":{"begin":"\\\\s*","beginCaptures":{"0":{"name":"keyword.operator.assignment.ng"}},"contentName":"meta.definition.variable.initializer.ng","end":";","endCaptures":{"0":{"name":"punctuation.terminator.statement.ng"}},"patterns":[{"include":"expression.ng"}]}},"scopeName":"template.let.ng","embeddedLangs":["angular-expression"]}`)),i=[...n,r],a=Object.freeze(JSON.parse(`{"injectTo":["text.html.derivative","text.html.derivative.ng","source.ts.ng"],"injectionSelector":"L:text.html -comment","name":"angular-template","patterns":[{"include":"#interpolation"}],"repository":{"interpolation":{"begin":"\\\\{\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.block.ts"}},"contentName":"expression.ng","end":"}}","endCaptures":{"0":{"name":"punctuation.definition.block.ts"}},"patterns":[{"include":"expression.ng"}]}},"scopeName":"template.ng","embeddedLangs":["angular-expression"]}`)),o=[...n,a],s=Object.freeze(JSON.parse(`{"injectTo":["text.html.derivative","text.html.derivative.ng","source.ts.ng"],"injectionSelector":"L:text.html -comment -expression.ng -meta.tag -source.css -source.js","name":"angular-template-blocks","patterns":[{"include":"#block"}],"repository":{"block":{"begin":"(@)(if|else if|else|defer|placeholder|loading|error|switch|case|default|for|empty)\\\\s*","beginCaptures":{"1":{"patterns":[{"include":"#transition"}]},"2":{"name":"keyword.control.block.kind.ng"}},"end":"(?<=})","name":"control.block.ng","patterns":[{"include":"#blockExpression"},{"include":"#blockBody"}]},"blockBody":{"begin":"\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.block.ts"}},"contentName":"control.block.body.ng","end":"}","endCaptures":{"0":{"name":"punctuation.definition.block.ts"}},"patterns":[{"include":"text.html.derivative.ng"},{"include":"template.ng"}]},"blockExpression":{"begin":"\\\\(","beginCaptures":{"0":{"name":"meta.brace.round.ts"}},"contentName":"control.block.expression.ng","end":"\\\\)","endCaptures":{"0":{"name":"meta.brace.round.ts"}},"patterns":[{"include":"#blockExpressionOfClause"},{"include":"#blockExpressionLetBinding"},{"include":"#blockExpressionTrackClause"},{"include":"expression.ng"}]},"blockExpressionLetBinding":{"begin":"\\\\blet\\\\b","beginCaptures":{"0":{"name":"storage.type.ng"}},"end":"(?=[$)])|(?<=;)","patterns":[{"include":"expression.ng"}]},"blockExpressionOfClause":{"begin":"([$_[:alpha:]][$_[:alnum:]]*)\\\\s+(of)\\\\b","beginCaptures":{"1":{"name":"variable.other.constant.ng"},"2":{"name":"keyword.operator.expression.of.ng"}},"end":"(?=[$)])|(?<=;)","patterns":[{"include":"expression.ng"}]},"blockExpressionTrackClause":{"begin":"\\\\btrack\\\\b","beginCaptures":{"0":{"name":"keyword.control.track.ng"}},"end":"(?=[$)])|(?<=;)","patterns":[{"include":"expression.ng"}]},"transition":{"match":"@","name":"keyword.control.block.transition.ng"}},"scopeName":"template.blocks.ng","embeddedLangs":["angular-expression","angular-template"]}`)),c=[...n,...o,s],l=e({default:()=>d}),u=Object.freeze(JSON.parse(`{"displayName":"Angular HTML","injections":{"R:text.html - (comment.block, text.html meta.embedded, meta.tag.*.*.html, meta.tag.*.*.*.html, meta.tag.*.*.*.*.html)":{"patterns":[{"match":"<","name":"invalid.illegal.bad-angle-bracket.html"}]}},"name":"angular-html","patterns":[{"include":"text.html.basic#core-minus-invalid"},{"begin":"(</?)(\\\\w[^>\\\\s]*)(?<!/)","beginCaptures":{"1":{"name":"punctuation.definition.tag.begin.html"},"2":{"name":"entity.name.tag.html"}},"end":"((?: ?/)?>)","endCaptures":{"1":{"name":"punctuation.definition.tag.end.html"}},"name":"meta.tag.other.unrecognized.html.derivative","patterns":[{"include":"text.html.basic#attribute"}]}],"scopeName":"text.html.derivative.ng","embeddedLangs":["html","angular-expression","angular-let-declaration","angular-template","angular-template-blocks"]}`)),d=[...t,...n,...i,...o,...c,u];export{i as a,o as i,l as n,n as o,c as r,d as t};
|