doc-detective 4.29.1 → 4.31.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.
Files changed (71) hide show
  1. package/bin/doc-detective-lsp.js +6 -0
  2. package/dist/cli.js +2 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/common/src/validate.d.ts +16 -1
  5. package/dist/common/src/validate.d.ts.map +1 -1
  6. package/dist/common/src/validate.js +18 -1
  7. package/dist/common/src/validate.js.map +1 -1
  8. package/dist/core/tests/saveScreenshot.d.ts.map +1 -1
  9. package/dist/core/tests/saveScreenshot.js +116 -59
  10. package/dist/core/tests/saveScreenshot.js.map +1 -1
  11. package/dist/core/tests/startSurface.d.ts.map +1 -1
  12. package/dist/core/tests/startSurface.js +17 -12
  13. package/dist/core/tests/startSurface.js.map +1 -1
  14. package/dist/core/tests.d.ts.map +1 -1
  15. package/dist/core/tests.js +33 -19
  16. package/dist/core/tests.js.map +1 -1
  17. package/dist/core/utils.d.ts +73 -0
  18. package/dist/core/utils.d.ts.map +1 -1
  19. package/dist/core/utils.js +100 -0
  20. package/dist/core/utils.js.map +1 -1
  21. package/dist/index.cjs +140 -55
  22. package/dist/lsp/command.d.ts +12 -0
  23. package/dist/lsp/command.d.ts.map +1 -0
  24. package/dist/lsp/command.js +24 -0
  25. package/dist/lsp/command.js.map +1 -0
  26. package/dist/lsp/completion.d.ts +27 -0
  27. package/dist/lsp/completion.d.ts.map +1 -0
  28. package/dist/lsp/completion.js +114 -0
  29. package/dist/lsp/completion.js.map +1 -0
  30. package/dist/lsp/diagnostics.d.ts +21 -0
  31. package/dist/lsp/diagnostics.d.ts.map +1 -0
  32. package/dist/lsp/diagnostics.js +137 -0
  33. package/dist/lsp/diagnostics.js.map +1 -0
  34. package/dist/lsp/gate.d.ts +30 -0
  35. package/dist/lsp/gate.d.ts.map +1 -0
  36. package/dist/lsp/gate.js +80 -0
  37. package/dist/lsp/gate.js.map +1 -0
  38. package/dist/lsp/hover.d.ts +9 -0
  39. package/dist/lsp/hover.d.ts.map +1 -0
  40. package/dist/lsp/hover.js +56 -0
  41. package/dist/lsp/hover.js.map +1 -0
  42. package/dist/lsp/inline.d.ts +25 -0
  43. package/dist/lsp/inline.d.ts.map +1 -0
  44. package/dist/lsp/inline.js +208 -0
  45. package/dist/lsp/inline.js.map +1 -0
  46. package/dist/lsp/json/positions.d.ts +51 -0
  47. package/dist/lsp/json/positions.d.ts.map +1 -0
  48. package/dist/lsp/json/positions.js +101 -0
  49. package/dist/lsp/json/positions.js.map +1 -0
  50. package/dist/lsp/messages.d.ts +27 -0
  51. package/dist/lsp/messages.d.ts.map +1 -0
  52. package/dist/lsp/messages.js +33 -0
  53. package/dist/lsp/messages.js.map +1 -0
  54. package/dist/lsp/model.d.ts +27 -0
  55. package/dist/lsp/model.d.ts.map +1 -0
  56. package/dist/lsp/model.js +49 -0
  57. package/dist/lsp/model.js.map +1 -0
  58. package/dist/lsp/registry.d.ts +61 -0
  59. package/dist/lsp/registry.d.ts.map +1 -0
  60. package/dist/lsp/registry.js +124 -0
  61. package/dist/lsp/registry.js.map +1 -0
  62. package/dist/lsp/server.d.ts +40 -0
  63. package/dist/lsp/server.d.ts.map +1 -0
  64. package/dist/lsp/server.js +64 -0
  65. package/dist/lsp/server.js.map +1 -0
  66. package/dist/lsp/yaml/positions.d.ts +32 -0
  67. package/dist/lsp/yaml/positions.d.ts.map +1 -0
  68. package/dist/lsp/yaml/positions.js +92 -0
  69. package/dist/lsp/yaml/positions.js.map +1 -0
  70. package/package.json +6 -2
  71. package/scripts/postinstall.js +144 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positions.d.ts","sourceRoot":"","sources":["../../../src/lsp/json/positions.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,IAAI,EACJ,UAAU,EACX,MAAM,cAAc,CAAC;AAEtB,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,2EAA2E;AAC3E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAOrD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CASnF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,GACnB,WAAW,GAAG,IAAI,CAWpB;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,QAAQ,EAAE,WAAW,CAAC;IACtB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;CACjB;AASD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CASxE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,eAAe,EAAE,CA2BlE"}
@@ -0,0 +1,101 @@
1
+ import { parseTree, findNodeAtLocation, getNodePath, } from "jsonc-parser";
2
+ /**
3
+ * Parse JSON(-with-comments) into a position-preserving CST. jsonc-parser is
4
+ * tolerant of the half-typed, comma-trailing states an editor streams, and
5
+ * collects syntax errors rather than throwing.
6
+ */
7
+ export function parseJsonTree(text) {
8
+ const errors = [];
9
+ const root = parseTree(text, errors, {
10
+ allowTrailingComma: true,
11
+ disallowComments: false,
12
+ });
13
+ return { root, errors };
14
+ }
15
+ /**
16
+ * Turn an AJV `instancePath` (`/tests/0/steps/1/goTo`) into path segments,
17
+ * decoding the JSON-Pointer escapes (`~1`→`/`, `~0`→`~`) and numeric indices.
18
+ */
19
+ export function instancePathToSegments(instancePath) {
20
+ if (!instancePath)
21
+ return [];
22
+ return instancePath
23
+ .split("/")
24
+ .slice(1)
25
+ .map((seg) => {
26
+ const unescaped = seg.replace(/~1/g, "/").replace(/~0/g, "~");
27
+ return /^\d+$/.test(unescaped) ? Number(unescaped) : unescaped;
28
+ });
29
+ }
30
+ /**
31
+ * Resolve the source span for an AJV `instancePath`. When the exact node is
32
+ * absent (e.g. a `required` error names an object whose child doesn't exist),
33
+ * walks up to the nearest present ancestor so the diagnostic still anchors
34
+ * somewhere sensible instead of vanishing. Returns `null` only when even the
35
+ * root can't be located (unparseable input).
36
+ */
37
+ export function rangeForInstancePath(root, instancePath) {
38
+ const segments = instancePathToSegments(instancePath);
39
+ for (let end = segments.length; end >= 0; end--) {
40
+ const node = end === 0 ? root : findNodeAtLocation(root, segments.slice(0, end));
41
+ if (node) {
42
+ return { start: node.offset, end: node.offset + node.length };
43
+ }
44
+ }
45
+ /* c8 ignore next 2 - root is always locatable when this is called with a real tree */
46
+ return null;
47
+ }
48
+ function visit(node, cb) {
49
+ cb(node);
50
+ if (node.children) {
51
+ for (const child of node.children)
52
+ visit(child, cb);
53
+ }
54
+ }
55
+ /**
56
+ * Build a JSON-Pointer from path segments, escaping `~`→`~0` and `/`→`~1` per
57
+ * RFC 6901. Shared by the JSON and YAML action-keyed detectors.
58
+ */
59
+ export function pointerFromPath(segments) {
60
+ /* c8 ignore next - defensive: callers pass a nested node's path, never the empty root path */
61
+ if (segments.length === 0)
62
+ return "";
63
+ return ("/" +
64
+ segments
65
+ .map((s) => String(s).replace(/~/g, "~0").replace(/\//g, "~1"))
66
+ .join("/"));
67
+ }
68
+ /**
69
+ * Find every step written as an object carrying an `action` property inside a
70
+ * `steps` array — the classic Doc Detective mistake (action name as a *value*
71
+ * under `action`, instead of the compact action-as-key form). Returns the
72
+ * `"action"` key span (to squiggle) and the step's JSON-Pointer (to suppress
73
+ * the otherwise-overwhelming `anyOf` schema failures for that same step).
74
+ */
75
+ export function findActionKeyedSteps(root) {
76
+ const found = [];
77
+ visit(root, (node) => {
78
+ if (node.type !== "property" ||
79
+ !node.children ||
80
+ node.children[0]?.value !== "steps") {
81
+ return;
82
+ }
83
+ const arr = node.children[1];
84
+ if (arr?.type !== "array" || !arr.children)
85
+ return;
86
+ for (const el of arr.children) {
87
+ if (el.type !== "object" || !el.children)
88
+ continue;
89
+ const actionProp = el.children.find((p) => p.type === "property" && p.children?.[0]?.value === "action");
90
+ if (actionProp && actionProp.children) {
91
+ const keyNode = actionProp.children[0];
92
+ found.push({
93
+ keyRange: { start: keyNode.offset, end: keyNode.offset + keyNode.length },
94
+ pointer: pointerFromPath(getNodePath(el)),
95
+ });
96
+ }
97
+ }
98
+ });
99
+ return found;
100
+ }
101
+ //# sourceMappingURL=positions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positions.js","sourceRoot":"","sources":["../../../src/lsp/json/positions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared diagnostic strings and the AJV-error→message formatter. Kept in its own
3
+ * module so both the spec pipeline (diagnostics.ts) and the inline pipeline
4
+ * (inline.ts) can use them without a circular import.
5
+ */
6
+ /** Diagnostic `source` label shown in the editor gutter/problems panel. */
7
+ export declare const DIAGNOSTIC_SOURCE = "doc-detective";
8
+ /**
9
+ * The flagship message: the single most common Doc Detective authoring mistake
10
+ * gets one clear diagnostic instead of the wall of `anyOf` failures the raw
11
+ * schema produces. Mirrors the plugin's write-blocking hook. Fires only on an
12
+ * INVALID document/step — a valid legacy v2 form gets the softer deprecation
13
+ * warning instead.
14
+ */
15
+ export declare const ACTION_KEYED_MESSAGE: string;
16
+ /**
17
+ * The version-mixing nudge: a document/step that is *valid* but uses the legacy
18
+ * v2 `action`-keyed form gets a non-blocking warning steering it to compact v3.
19
+ */
20
+ export declare const V2_DEPRECATION_MESSAGE = "Legacy v2 step form. Prefer the compact v3 form \u2014 the action name is the key, e.g. `{\"goTo\": \u2026}`.";
21
+ /** Format a single AJV error into a concise human message. */
22
+ export declare function schemaMessage(error: {
23
+ message?: string;
24
+ keyword?: string;
25
+ params?: Record<string, any>;
26
+ }): string;
27
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/lsp/messages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAEQ,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,kHACkE,CAAC;AAEtG,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,GAAG,MAAM,CAST"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Shared diagnostic strings and the AJV-error→message formatter. Kept in its own
3
+ * module so both the spec pipeline (diagnostics.ts) and the inline pipeline
4
+ * (inline.ts) can use them without a circular import.
5
+ */
6
+ /** Diagnostic `source` label shown in the editor gutter/problems panel. */
7
+ export const DIAGNOSTIC_SOURCE = "doc-detective";
8
+ /**
9
+ * The flagship message: the single most common Doc Detective authoring mistake
10
+ * gets one clear diagnostic instead of the wall of `anyOf` failures the raw
11
+ * schema produces. Mirrors the plugin's write-blocking hook. Fires only on an
12
+ * INVALID document/step — a valid legacy v2 form gets the softer deprecation
13
+ * warning instead.
14
+ */
15
+ export const ACTION_KEYED_MESSAGE = 'The action name is the key: write `{"goTo": …}`, not an object with an "action" property. ' +
16
+ 'Each step is `{"<action>": <value>}`.';
17
+ /**
18
+ * The version-mixing nudge: a document/step that is *valid* but uses the legacy
19
+ * v2 `action`-keyed form gets a non-blocking warning steering it to compact v3.
20
+ */
21
+ export const V2_DEPRECATION_MESSAGE = 'Legacy v2 step form. Prefer the compact v3 form — the action name is the key, e.g. `{"goTo": …}`.';
22
+ /** Format a single AJV error into a concise human message. */
23
+ export function schemaMessage(error) {
24
+ const base = error.message || "does not match the schema";
25
+ const params = error.params || {};
26
+ if (error.keyword === "additionalProperties" && params.additionalProperty) {
27
+ return `${base}: "${params.additionalProperty}"`;
28
+ }
29
+ // AJV's `required` message already names the missing property, so `base`
30
+ // needs no augmentation — it falls through to the return below.
31
+ return base;
32
+ }
33
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/lsp/messages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,4FAA4F;IAC5F,uCAAuC,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,mGAAmG,CAAC;AAEtG,8DAA8D;AAC9D,MAAM,UAAU,aAAa,CAAC,KAI7B;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,OAAO,KAAK,sBAAsB,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC1E,OAAO,GAAG,IAAI,MAAM,MAAM,CAAC,kBAAkB,GAAG,CAAC;IACnD,CAAC;IACD,yEAAyE;IACzE,gEAAgE;IAChE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { OffsetRange, ActionKeyedStep } from "./json/positions.js";
2
+ /** A syntax error reduced to an offset span + message, format-agnostic. */
3
+ export interface SyntaxErrorSpan {
4
+ range: OffsetRange;
5
+ message: string;
6
+ }
7
+ /**
8
+ * A format-agnostic view of a parsed spec/config buffer. JSON and YAML each
9
+ * provide one; the diagnostics (and, later, inline) pipeline works against this
10
+ * interface so the schema/action logic is written once.
11
+ */
12
+ export interface SpecModel {
13
+ /** The plain JS value (undefined for empty/unparseable buffers). */
14
+ value: any;
15
+ /** Syntax-error spans + messages (empty when the buffer parses cleanly). */
16
+ syntaxErrors: SyntaxErrorSpan[];
17
+ /** Source span for an AJV instancePath, or null if unlocatable. */
18
+ rangeForPath(instancePath: string): OffsetRange | null;
19
+ /** Steps written in the legacy `action`-keyed form. */
20
+ actionKeyedSteps(): ActionKeyedStep[];
21
+ }
22
+ /**
23
+ * Build the right model for a buffer by extension, or null for an unsupported
24
+ * one. Callers gate on the classifier separately (spec vs config).
25
+ */
26
+ export declare function buildModel(uri: string, text: string): SpecModel | null;
27
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/lsp/model.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,WAAW,EACX,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAQ7B,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,oEAAoE;IACpE,KAAK,EAAE,GAAG,CAAC;IACX,4EAA4E;IAC5E,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,mEAAmE;IACnE,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACvD,uDAAuD;IACvD,gBAAgB,IAAI,eAAe,EAAE,CAAC;CACvC;AAqCD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAItE"}
@@ -0,0 +1,49 @@
1
+ import { getNodeValue, printParseErrorCode } from "jsonc-parser";
2
+ import { isJsonUri, isYamlUri } from "./gate.js";
3
+ import { parseJsonTree, rangeForInstancePath, findActionKeyedSteps, } from "./json/positions.js";
4
+ import { parseYamlTree, yamlSyntaxErrors, rangeForInstancePathYaml, findActionKeyedStepsYaml, } from "./yaml/positions.js";
5
+ function buildJsonModel(text) {
6
+ const { root, errors } = parseJsonTree(text);
7
+ return {
8
+ value: root ? getNodeValue(root) : undefined,
9
+ syntaxErrors: errors.map((e) => ({
10
+ range: { start: e.offset, end: e.offset + e.length },
11
+ message: `JSON syntax: ${printParseErrorCode(e.error)}`,
12
+ })),
13
+ rangeForPath: (path) => (root ? rangeForInstancePath(root, path) : null),
14
+ actionKeyedSteps: () => (root ? findActionKeyedSteps(root) : []),
15
+ };
16
+ }
17
+ function buildYamlModel(text) {
18
+ const { doc, value, valueError } = parseYamlTree(text);
19
+ const syntaxErrors = yamlSyntaxErrors(doc).map((e) => ({
20
+ range: e.range,
21
+ message: `YAML syntax: ${e.message}`,
22
+ }));
23
+ // A `toJS()` failure (e.g. an alias bomb) has no single node to blame; anchor
24
+ // it at the document start so the author still sees the problem.
25
+ if (valueError) {
26
+ syntaxErrors.push({
27
+ range: { start: 0, end: Math.min(text.length, 1) },
28
+ message: `YAML error: ${valueError}`,
29
+ });
30
+ }
31
+ return {
32
+ value,
33
+ syntaxErrors,
34
+ rangeForPath: (path) => rangeForInstancePathYaml(doc, path),
35
+ actionKeyedSteps: () => findActionKeyedStepsYaml(doc),
36
+ };
37
+ }
38
+ /**
39
+ * Build the right model for a buffer by extension, or null for an unsupported
40
+ * one. Callers gate on the classifier separately (spec vs config).
41
+ */
42
+ export function buildModel(uri, text) {
43
+ if (isJsonUri(uri))
44
+ return buildJsonModel(text);
45
+ if (isYamlUri(uri))
46
+ return buildYamlModel(text);
47
+ return null;
48
+ }
49
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/lsp/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,oBAAoB,GAGrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAwB7B,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;QAC5C,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/B,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE;YACpD,OAAO,EAAE,gBAAgB,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;SACxD,CAAC,CAAC;QACH,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACjE,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,YAAY,GAAsB,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxE,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,gBAAgB,CAAC,CAAC,OAAO,EAAE;KACrC,CAAC,CAAC,CAAC;IACJ,8EAA8E;IAC9E,iEAAiE;IACjE,IAAI,UAAU,EAAE,CAAC;QACf,YAAY,CAAC,IAAI,CAAC;YAChB,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE;YAClD,OAAO,EAAE,eAAe,UAAU,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;IACD,OAAO;QACL,KAAK;QACL,YAAY;QACZ,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,wBAAwB,CAAC,GAAG,EAAE,IAAI,CAAC;QAC3D,gBAAgB,EAAE,GAAG,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,IAAY;IAClD,IAAI,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,61 @@
1
+ /** The kind of scalar an action's compact form accepts, if any. */
2
+ export type PrimitiveKind = "string" | "number" | "boolean" | null;
3
+ /**
4
+ * A field inside an action's object form — used for field-name completion and
5
+ * (Phase 3) enum-value completion.
6
+ */
7
+ export interface ActionField {
8
+ name: string;
9
+ description?: string;
10
+ /**
11
+ * The scalar kind this field accepts, or null for object/array fields. Drives
12
+ * whether a completion snippet quotes the value placeholder.
13
+ */
14
+ primitiveKind: PrimitiveKind;
15
+ /** Enumerated values, when the field's schema (or a branch) pins them. */
16
+ enumValues?: Array<string | number | boolean>;
17
+ }
18
+ /** Everything the language features need to know about one action. */
19
+ export interface ActionInfo {
20
+ /** The action key, which IS the step key (`goTo`, `find`, …). */
21
+ key: string;
22
+ title?: string;
23
+ description?: string;
24
+ /** True when the compact scalar form (e.g. `"goTo": "https://…"`) is valid. */
25
+ acceptsPrimitive: boolean;
26
+ /**
27
+ * The scalar kind the compact form accepts (`"goTo"` → string, `"wait"` →
28
+ * number, `"stopRecord"` → boolean), or null for object-only actions. Drives
29
+ * whether a completion snippet quotes the placeholder.
30
+ */
31
+ primitiveKind: PrimitiveKind;
32
+ /** Fields available inside the object form. */
33
+ fields: ActionField[];
34
+ }
35
+ export interface Registry {
36
+ actions: ActionInfo[];
37
+ byKey: Map<string, ActionInfo>;
38
+ }
39
+ /** Collect the candidate sub-schemas of a schema: itself plus anyOf/oneOf/allOf. */
40
+ export declare function branchesOf(schema: any): any[];
41
+ /** Dig for a human description across a schema and its immediate branches. */
42
+ export declare function findDescription(schema: any): string | undefined;
43
+ /**
44
+ * The scalar kind a schema (or a branch) accepts in its compact form, or null.
45
+ * The first primitive type encountered across branches wins.
46
+ */
47
+ export declare function primitiveKindOf(schema: any): PrimitiveKind;
48
+ /** Does the schema (or a branch) accept a primitive scalar value? */
49
+ export declare function acceptsPrimitive(schema: any): boolean;
50
+ /** Merge the `properties` maps found across a schema's object branches. */
51
+ export declare function collectFields(schema: any): ActionField[];
52
+ /** Pull an enum list from a schema or its branches, if any. */
53
+ export declare function extractEnum(schema: any): Array<string | number | boolean> | undefined;
54
+ /**
55
+ * Build the action registry from the live `step_v3` schema. Derived at runtime
56
+ * (not a build step) so a new action added to the schemas automatically appears
57
+ * in completion/hover — the anti-drift test pins that guarantee.
58
+ */
59
+ export declare function buildRegistry(step?: any): Registry;
60
+ export declare function getRegistry(): Registry;
61
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/lsp/registry.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,aAAa,EAAE,aAAa,CAAC;IAC7B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC/C;AAED,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,gBAAgB,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,aAAa,EAAE,aAAa,CAAC;IAC7B,+CAA+C;IAC/C,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CAChC;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,CAO7C;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAO/D;AAUD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,aAAa,CAU1D;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAErD;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,GAAG,WAAW,EAAE,CAgBxD;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,CAKrF;AAgBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,GAAE,GAAiC,GAAG,QAAQ,CAoB/E;AAID,wBAAgB,WAAW,IAAI,QAAQ,CAGtC"}
@@ -0,0 +1,124 @@
1
+ import { schemas } from "../common/src/schemas/index.js";
2
+ /** Collect the candidate sub-schemas of a schema: itself plus anyOf/oneOf/allOf. */
3
+ export function branchesOf(schema) {
4
+ if (!schema || typeof schema !== "object")
5
+ return [];
6
+ const out = [schema];
7
+ for (const key of ["anyOf", "oneOf", "allOf"]) {
8
+ if (Array.isArray(schema[key]))
9
+ out.push(...schema[key]);
10
+ }
11
+ return out;
12
+ }
13
+ /** Dig for a human description across a schema and its immediate branches. */
14
+ export function findDescription(schema) {
15
+ for (const branch of branchesOf(schema)) {
16
+ if (typeof branch.description === "string" && branch.description.length > 0) {
17
+ return branch.description;
18
+ }
19
+ }
20
+ return undefined;
21
+ }
22
+ /** Map a JSON-Schema scalar type onto the snippet-relevant primitive kind. */
23
+ function normalizePrimitive(type) {
24
+ if (type === "string")
25
+ return "string";
26
+ if (type === "number" || type === "integer")
27
+ return "number";
28
+ if (type === "boolean")
29
+ return "boolean";
30
+ return null;
31
+ }
32
+ /**
33
+ * The scalar kind a schema (or a branch) accepts in its compact form, or null.
34
+ * The first primitive type encountered across branches wins.
35
+ */
36
+ export function primitiveKindOf(schema) {
37
+ for (const branch of branchesOf(schema)) {
38
+ const type = branch.type;
39
+ const types = typeof type === "string" ? [type] : Array.isArray(type) ? type : [];
40
+ for (const t of types) {
41
+ const kind = normalizePrimitive(t);
42
+ if (kind)
43
+ return kind;
44
+ }
45
+ }
46
+ return null;
47
+ }
48
+ /** Does the schema (or a branch) accept a primitive scalar value? */
49
+ export function acceptsPrimitive(schema) {
50
+ return primitiveKindOf(schema) !== null;
51
+ }
52
+ /** Merge the `properties` maps found across a schema's object branches. */
53
+ export function collectFields(schema) {
54
+ const seen = new Map();
55
+ for (const branch of branchesOf(schema)) {
56
+ const props = branch.properties;
57
+ if (!props || typeof props !== "object")
58
+ continue;
59
+ for (const [name, propSchema] of Object.entries(props)) {
60
+ if (name === "$schema" || seen.has(name))
61
+ continue;
62
+ seen.set(name, {
63
+ name,
64
+ description: findDescription(propSchema),
65
+ primitiveKind: primitiveKindOf(propSchema),
66
+ enumValues: extractEnum(propSchema),
67
+ });
68
+ }
69
+ }
70
+ return [...seen.values()];
71
+ }
72
+ /** Pull an enum list from a schema or its branches, if any. */
73
+ export function extractEnum(schema) {
74
+ for (const branch of branchesOf(schema)) {
75
+ if (Array.isArray(branch.enum))
76
+ return branch.enum.slice();
77
+ }
78
+ return undefined;
79
+ }
80
+ /**
81
+ * The `allOf` element of a `step_v3` anyOf branch that carries the action: the
82
+ * one whose `required` names exactly the action key (never `$schema`).
83
+ */
84
+ function actionPartOf(branch) {
85
+ const parts = Array.isArray(branch.allOf) ? branch.allOf : [branch];
86
+ return parts.find((p) => Array.isArray(p.required) &&
87
+ p.required.length === 1 &&
88
+ p.required[0] !== "$schema");
89
+ }
90
+ /**
91
+ * Build the action registry from the live `step_v3` schema. Derived at runtime
92
+ * (not a build step) so a new action added to the schemas automatically appears
93
+ * in completion/hover — the anti-drift test pins that guarantee.
94
+ */
95
+ export function buildRegistry(step = schemas["step_v3"]) {
96
+ const actions = [];
97
+ for (const branch of step.anyOf || []) {
98
+ const part = actionPartOf(branch);
99
+ /* c8 ignore next - every step_v3 anyOf branch has an action part; defensive */
100
+ if (!part)
101
+ continue;
102
+ const key = part.required[0];
103
+ const propSchema = part.properties?.[key];
104
+ const primitiveKind = primitiveKindOf(propSchema);
105
+ actions.push({
106
+ key,
107
+ title: part.title || key,
108
+ description: findDescription(propSchema),
109
+ acceptsPrimitive: primitiveKind !== null,
110
+ primitiveKind,
111
+ fields: collectFields(propSchema),
112
+ });
113
+ }
114
+ const byKey = new Map(actions.map((a) => [a.key, a]));
115
+ return { actions, byKey };
116
+ }
117
+ /** Lazily-built shared registry (the schemas are static within a process). */
118
+ let cached;
119
+ export function getRegistry() {
120
+ if (!cached)
121
+ cached = buildRegistry();
122
+ return cached;
123
+ }
124
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lsp/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type InitializeResult } from "vscode-languageserver/node.js";
2
+ import type { CompletionItem, CompletionParams, Hover, HoverParams } from "vscode-languageserver";
3
+ import { TextDocument } from "vscode-languageserver-textdocument";
4
+ /**
5
+ * The subset of a `Connection` the handlers touch. Narrowed to an interface so
6
+ * tests can drive the wiring with a fake instead of a live stdio transport.
7
+ */
8
+ export interface DiagnosticsConnection {
9
+ onInitialize(handler: () => InitializeResult): void;
10
+ sendDiagnostics(params: {
11
+ uri: string;
12
+ diagnostics: unknown[];
13
+ }): void;
14
+ onCompletion(handler: (params: CompletionParams) => CompletionItem[]): void;
15
+ onHover(handler: (params: HoverParams) => Hover | null): void;
16
+ }
17
+ /**
18
+ * The subset of a `TextDocuments` manager the handlers subscribe to.
19
+ */
20
+ export interface DocumentEvents {
21
+ onDidChangeContent(handler: (event: {
22
+ document: TextDocument;
23
+ }) => void): void;
24
+ onDidClose(handler: (event: {
25
+ document: TextDocument;
26
+ }) => void): void;
27
+ get(uri: string): TextDocument | undefined;
28
+ }
29
+ /**
30
+ * Wire language-server behavior onto a connection + document manager. Pure of
31
+ * any transport, so a unit test can pass fakes, capture the registered
32
+ * callbacks, and assert what gets published — no real process required.
33
+ */
34
+ export declare function registerHandlers(connection: DiagnosticsConnection, documents: DocumentEvents): void;
35
+ /**
36
+ * Boot the language server over stdio. Called by the `doc-detective lsp`
37
+ * subcommand.
38
+ */
39
+ export declare function startServer(): void;
40
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/lsp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,KAAK,EACL,WAAW,EACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAKlE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,OAAO,EAAE,MAAM,gBAAgB,GAAG,IAAI,CAAC;IACpD,eAAe,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,YAAY,CACV,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,cAAc,EAAE,GACtD,IAAI,CAAC;IACR,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;CAC/D;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/E,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,YAAY,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IACvE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;CAC5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,qBAAqB,EACjC,SAAS,EAAE,cAAc,GACxB,IAAI,CAsCN;AAKD;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAclC"}
@@ -0,0 +1,64 @@
1
+ import { createConnection, TextDocuments, ProposedFeatures, StreamMessageReader, StreamMessageWriter, TextDocumentSyncKind, } from "vscode-languageserver/node.js";
2
+ import { TextDocument } from "vscode-languageserver-textdocument";
3
+ import { computeDiagnostics } from "./diagnostics.js";
4
+ import { computeCompletions } from "./completion.js";
5
+ import { computeHover } from "./hover.js";
6
+ /**
7
+ * Wire language-server behavior onto a connection + document manager. Pure of
8
+ * any transport, so a unit test can pass fakes, capture the registered
9
+ * callbacks, and assert what gets published — no real process required.
10
+ */
11
+ export function registerHandlers(connection, documents) {
12
+ connection.onInitialize(() => ({
13
+ capabilities: {
14
+ // Full sync keeps Phase 1 simple; jsonc-parser reparses the whole buffer
15
+ // on each change anyway, so incremental patching buys nothing yet.
16
+ textDocumentSync: TextDocumentSyncKind.Full,
17
+ completionProvider: { triggerCharacters: ['"', "{"] },
18
+ hoverProvider: true,
19
+ },
20
+ }));
21
+ const publish = (document) => {
22
+ connection.sendDiagnostics({
23
+ uri: document.uri,
24
+ diagnostics: computeDiagnostics(document),
25
+ });
26
+ };
27
+ // Fires on open and on every edit — the single hook we need for live
28
+ // diagnostics.
29
+ documents.onDidChangeContent((event) => publish(event.document));
30
+ // Clear diagnostics when a document closes so stale squiggles don't linger.
31
+ documents.onDidClose((event) => connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] }));
32
+ connection.onCompletion((params) => {
33
+ const document = documents.get(params.textDocument.uri);
34
+ if (!document)
35
+ return [];
36
+ return computeCompletions(document, params.position);
37
+ });
38
+ connection.onHover((params) => {
39
+ const document = documents.get(params.textDocument.uri);
40
+ if (!document)
41
+ return null;
42
+ return computeHover(document, params.position);
43
+ });
44
+ }
45
+ /* c8 ignore start - real stdio bootstrap: no injectable seam; the pure wiring
46
+ in registerHandlers is unit-tested, and the whole server is exercised
47
+ end-to-end by the spawned protocol test. */
48
+ /**
49
+ * Boot the language server over stdio. Called by the `doc-detective lsp`
50
+ * subcommand.
51
+ */
52
+ export function startServer() {
53
+ // Explicit stdio streams so the server works no matter how it's launched —
54
+ // the `doc-detective lsp` subcommand OR the bare `doc-detective-lsp` bin.
55
+ // (createConnection(ProposedFeatures.all) alone sniffs argv for `--stdio`,
56
+ // which the bare bin doesn't pass.)
57
+ const connection = createConnection(ProposedFeatures.all, new StreamMessageReader(process.stdin), new StreamMessageWriter(process.stdout));
58
+ const documents = new TextDocuments(TextDocument);
59
+ registerHandlers(connection, documents);
60
+ documents.listen(connection);
61
+ connection.listen();
62
+ }
63
+ /* c8 ignore stop */
64
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/lsp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GAGrB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAwB1C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAiC,EACjC,SAAyB;IAEzB,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7B,YAAY,EAAE;YACZ,yEAAyE;YACzE,mEAAmE;YACnE,gBAAgB,EAAE,oBAAoB,CAAC,IAAI;YAC3C,kBAAkB,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;YACrD,aAAa,EAAE,IAAI;SACpB;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,OAAO,GAAG,CAAC,QAAsB,EAAE,EAAE;QACzC,UAAU,CAAC,eAAe,CAAC;YACzB,GAAG,EAAE,QAAQ,CAAC,GAAG;YACjB,WAAW,EAAE,kBAAkB,CAAC,QAAQ,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,qEAAqE;IACrE,eAAe;IACf,SAAS,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEjE,4EAA4E;IAC5E,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7B,UAAU,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CACzE,CAAC;IAEF,UAAU,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QACzB,OAAO,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC5B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC3B,OAAO,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;8CAE8C;AAC9C;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,2EAA2E;IAC3E,0EAA0E;IAC1E,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,UAAU,GAAe,gBAAgB,CAC7C,gBAAgB,CAAC,GAAG,EACpB,IAAI,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,EACtC,IAAI,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,CACxC,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;IAClD,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACxC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7B,UAAU,CAAC,MAAM,EAAE,CAAC;AACtB,CAAC;AACD,oBAAoB"}
@@ -0,0 +1,32 @@
1
+ import YAML from "yaml";
2
+ import type { OffsetRange, ActionKeyedStep } from "../json/positions.js";
3
+ /** Result of parsing YAML: the document (for node lookups) plus its value. */
4
+ export interface YamlParse {
5
+ doc: YAML.Document.Parsed;
6
+ value: any;
7
+ /** Set when `doc.toJS()` threw (e.g. an alias-bomb exceeding maxAliasCount). */
8
+ valueError?: string;
9
+ }
10
+ /** Parse YAML into a position-preserving document plus its plain JS value. */
11
+ export declare function parseYamlTree(text: string): YamlParse;
12
+ /** A YAML syntax error reduced to an offset span and message. */
13
+ export interface YamlSyntaxError {
14
+ range: OffsetRange;
15
+ message: string;
16
+ }
17
+ /** Collect YAML syntax errors as offset spans (empty when the doc is clean). */
18
+ export declare function yamlSyntaxErrors(doc: YAML.Document.Parsed): YamlSyntaxError[];
19
+ /**
20
+ * Resolve the source span for an AJV `instancePath` in a YAML document. Walks
21
+ * up to the nearest present ancestor (like the JSON resolver) so a
22
+ * `required`-style error still anchors somewhere. Returns null only when even
23
+ * the document contents can't be located.
24
+ */
25
+ export declare function rangeForInstancePathYaml(doc: YAML.Document.Parsed, instancePath: string): OffsetRange | null;
26
+ /**
27
+ * Find every step written as a map carrying an `action` key inside a `steps`
28
+ * sequence — the YAML twin of the JSON detector. Returns the offending `action`
29
+ * key span and the step's JSON-Pointer.
30
+ */
31
+ export declare function findActionKeyedStepsYaml(doc: YAML.Document.Parsed): ActionKeyedStep[];
32
+ //# sourceMappingURL=positions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positions.d.ts","sourceRoot":"","sources":["../../../src/lsp/yaml/positions.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGzE,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC1B,KAAK,EAAE,GAAG,CAAC;IACX,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAarD;AAED,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,eAAe,EAAE,CAK7E;AASD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,EACzB,YAAY,EAAE,MAAM,GACnB,WAAW,GAAG,IAAI,CAUpB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,GACxB,eAAe,EAAE,CAqCnB"}