@invinite-org/chartlang-language-service 1.1.0 → 1.2.1

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 CHANGED
@@ -1,5 +1,93 @@
1
1
  # @invinite-org/chartlang-language-service
2
2
 
3
+ ## 1.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d7f8fad: Make the editor package browser-safe to import by default. The editor no longer imports or constructs the language service at module load or default mount time; hover, completions, and linting are enabled only when a service is injected, while preview wiring stays independent.
8
+
9
+ **Breaking (editor):** `createChartlangEditor({ targetCapabilities })` and the returned `setCapabilities(...)` method (and the React `<ChartlangEditor targetCapabilities>` prop) are now no-ops. Create a language service with capabilities and inject it via `service`:
10
+
11
+ ```ts
12
+ import { createChartlangEditor } from "@invinite-org/chartlang-editor";
13
+ import { createLanguageService } from "@invinite-org/chartlang-editor/language-service";
14
+
15
+ const editor = createChartlangEditor({
16
+ parent,
17
+ doc,
18
+ service: createLanguageService({ targetCapabilities }),
19
+ });
20
+ ```
21
+
22
+ The editor package also exposes explicit `./theme` and `./language-service` entry points so browser consumers can pick the surfaces they want without pulling the compiler into the main bundle.
23
+
24
+ The language-service change is purely internal: the compiler is now loaded via a dynamic `import("@invinite-org/chartlang-compiler")` inside `compileToDiagnostics`, so `createLanguageService(...)` no longer pulls the compiler graph at module load. Public signatures and behavior are unchanged.
25
+
26
+ ## 1.2.0
27
+
28
+ ### Minor Changes
29
+
30
+ - 2123181: Language service understands indicator-composition hovers, output-name
31
+ - override-key completions, and surfaces the new `dep-*` diagnostics
32
+ inline. Hover on `<binding>.output(...)` lists the producer's titled
33
+ outputs; hover on `<binding>.withInputs({...})` lists the producer's
34
+ input schema with kinds + defaults. Completion fires for output titles
35
+ inside `<binding>.output("|")` and for override keys inside
36
+ `<binding>.withInputs({ |})`. Best-effort go-to-definition for
37
+ `.output("title")` navigates to the producer's matching `plot(value,
38
+ { title })` call when the producer is a same-file `defineIndicator`;
39
+ cross-file and unresolvable cases fall back to `null`. Editor: no
40
+ public API change — new behaviour flows through the existing
41
+ `completionExtension` / `hoverExtension` / `linterExtension` wiring.
42
+ - 2123181: Indicator composition (Phase 7 closeout): one chartlang indicator can
43
+ read another indicator's titled plot output as a typed `Series<number>`.
44
+
45
+ - Compose via local `const` binding plus `<binding>.output("title")` —
46
+ no new public API beyond the chainable `.output` / `.withInputs`
47
+ accessors on `CompiledScriptObject`.
48
+ - A single `.chart.ts` MAY declare a default export plus any number of
49
+ named exports plus any number of private `const` deps. Export form
50
+ determines render policy: drawn exports render with the
51
+ `export:<exportName>/` slot-id prefix; private `const` deps are data
52
+ feeds only and their visuals are dropped.
53
+ - Cross-file `import baseTrend from "./base-trend.chart"` resolves
54
+ recursively; shared producers inline exactly once per consumer.
55
+ - Additive within `apiVersion: 1.x`. The 172-entry
56
+ `STATEFUL_PRIMITIVES` set is unchanged. `DiagnosticCode` widens to 32
57
+ with the new `dep-*` codes (`dep-error`, `dep-cycle`,
58
+ `dep-unknown-output`, `dep-invalid-input-override`, `dep-dynamic`,
59
+ `dep-output-not-titled`).
60
+ - Five conformance scenarios in `@invinite-org/chartlang-conformance`
61
+ pin the runtime contract end-to-end (`dep-private-single-file`,
62
+ `dep-multi-export`, `dep-cross-file`, `dep-diamond`,
63
+ `dep-error-halts-parent`). `Scenario.additionalSources` lets
64
+ cross-file scenarios ship producer + consumer side-by-side.
65
+ - Two new example scripts in `examples/scripts/`:
66
+ `base-trend.chart.ts` (producer) + `trend-confirmation.chart.ts`
67
+ (multi-export consumer). React-demo gains a fifth catalogue entry
68
+ exercising the feature end-to-end in the browser.
69
+ - Docs: `docs/language/indicator-composition.md` narrative guide,
70
+ `docs/spec/manifest.md` + `docs/spec/semantics.md` +
71
+ `docs/spec/versioning.md` updates, five new glossary entries.
72
+
73
+ ### Patch Changes
74
+
75
+ - Updated dependencies [d6d1a1f]
76
+ - Updated dependencies [f0c8eb8]
77
+ - Updated dependencies [f0c8eb8]
78
+ - Updated dependencies [2123181]
79
+ - Updated dependencies [2123181]
80
+ - Updated dependencies [2123181]
81
+ - Updated dependencies [2123181]
82
+ - Updated dependencies [2123181]
83
+ - Updated dependencies [4d77f4d]
84
+ - Updated dependencies [4d77f4d]
85
+ - Updated dependencies [3b4952d]
86
+ - Updated dependencies [0427459]
87
+ - @invinite-org/chartlang-core@1.1.0
88
+ - @invinite-org/chartlang-compiler@1.1.0
89
+ - @invinite-org/chartlang-adapter-kit@1.2.0
90
+
3
91
  ## 1.1.0
4
92
 
5
93
  ### Minor Changes
package/README.md CHANGED
@@ -24,6 +24,13 @@ pnpm add @invinite-org/chartlang-language-service
24
24
  | `getAvailableIntervals()` | Reads intervals from target capabilities. |
25
25
  | `HOVER_REGISTRY` | Checked-in generated hover-doc table. |
26
26
 
27
+ Dep-aware surfaces (Phase 0.7 indicator composition):
28
+ hovers + completions for `<binding>.output(...)` and
29
+ `<binding>.withInputs({...})` resolve same-file producer titles and
30
+ input schemas. The new `dep-*` compile diagnostics surface inline via
31
+ `compileToDiagnostics`. Go-to-definition on `.output("title")` jumps
32
+ to the producer's matching `plot(value, { title })` call.
33
+
27
34
  ## Minimum-viable API call
28
35
 
29
36
  ```ts
@@ -9,5 +9,5 @@ import type { CompletionItem } from "../types.js";
9
9
  * const items = collectCompletions("const length = 20;", 5, {});
10
10
  * void items;
11
11
  */
12
- export declare function collectCompletions(source: string, _offset: number, registry: Readonly<Record<string, HoverRegistryEntry>>): ReadonlyArray<CompletionItem>;
12
+ export declare function collectCompletions(source: string, offset: number, registry: Readonly<Record<string, HoverRegistryEntry>>): ReadonlyArray<CompletionItem>;
13
13
  //# sourceMappingURL=collectCompletions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collectCompletions.d.ts","sourceRoot":"","sources":["../../src/_lib/collectCompletions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,GACvD,aAAa,CAAC,cAAc,CAAC,CAa/B"}
1
+ {"version":3,"file":"collectCompletions.d.ts","sourceRoot":"","sources":["../../src/_lib/collectCompletions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMlD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,GACvD,aAAa,CAAC,cAAc,CAAC,CAsC/B"}
@@ -1,6 +1,9 @@
1
1
  // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
2
  // See the LICENSE file in the repo root for full license text.
3
3
  import ts from "typescript";
4
+ import { isInsideOutputStringLiteral } from "./isInsideOutputStringLiteral.js";
5
+ import { isInsideWithInputsKey } from "./isInsideWithInputsKey.js";
6
+ import { resolveDepInputsFor, resolveDepOutputsFor } from "./resolveDepAccessor.js";
4
7
  import { toHoverDoc } from "./toHoverDoc.js";
5
8
  /**
6
9
  * Collect registry and source-local completion items for an offset.
@@ -11,7 +14,23 @@ import { toHoverDoc } from "./toHoverDoc.js";
11
14
  * const items = collectCompletions("const length = 20;", 5, {});
12
15
  * void items;
13
16
  */
14
- export function collectCompletions(source, _offset, registry) {
17
+ export function collectCompletions(source, offset, registry) {
18
+ if (isInsideOutputStringLiteral(source, offset)) {
19
+ return Object.freeze(resolveDepOutputsFor(source, offset).map((title) => Object.freeze({
20
+ label: title,
21
+ kind: "property",
22
+ insertText: title,
23
+ detail: "Series<number> output",
24
+ })));
25
+ }
26
+ if (isInsideWithInputsKey(source, offset)) {
27
+ return Object.freeze(resolveDepInputsFor(source, offset).map((entry) => Object.freeze({
28
+ label: entry.name,
29
+ kind: "property",
30
+ insertText: entry.name,
31
+ detail: `${entry.kind} (default: ${entry.defaultText})`,
32
+ })));
33
+ }
15
34
  const registryItems = Object.values(registry).map(registryCompletion);
16
35
  const localItems = collectLocalIdentifiers(source).map((label) => Object.freeze({
17
36
  label,
@@ -1 +1 @@
1
- {"version":3,"file":"collectCompletions.js","sourceRoot":"","sources":["../../src/_lib/collectCompletions.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAC9B,MAAc,EACd,OAAe,EACf,QAAsD;IAEtD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7D,MAAM,CAAC,MAAM,CAAC;QACV,KAAK;QACL,IAAI,EAAE,UAAmB;QACzB,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,kBAAkB;KAC7B,CAAC,CACL,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,aAAa,EAAE,GAAG,UAAU,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAyB;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,KAAK,EAAE,KAAK,CAAC,GAAG;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;QACrD,UAAU,EAAE,KAAK,CAAC,GAAG;QACrB,MAAM,EAAE,KAAK,CAAC,KAAK;QACnB,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC;KACzB,CAAC,CAAC;AACP,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAc;IAC3C,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChG,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QAClC,IAAI,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5F,IAAI,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzF,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClF,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"collectCompletions.js","sourceRoot":"","sources":["../../src/_lib/collectCompletions.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAC9B,MAAc,EACd,MAAc,EACd,QAAsD;IAEtD,IAAI,2BAA2B,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QAC9C,OAAO,MAAM,CAAC,MAAM,CAChB,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/C,MAAM,CAAC,MAAM,CAAC;YACV,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,UAAmB;YACzB,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,uBAAuB;SAClC,CAAC,CACL,CACJ,CAAC;IACN,CAAC;IACD,IAAI,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACxC,OAAO,MAAM,CAAC,MAAM,CAChB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9C,MAAM,CAAC,MAAM,CAAC;YACV,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,IAAI,EAAE,UAAmB;YACzB,UAAU,EAAE,KAAK,CAAC,IAAI;YACtB,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,cAAc,KAAK,CAAC,WAAW,GAAG;SAC1D,CAAC,CACL,CACJ,CAAC;IACN,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7D,MAAM,CAAC,MAAM,CAAC;QACV,KAAK;QACL,IAAI,EAAE,UAAmB;QACzB,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,kBAAkB;KAC7B,CAAC,CACL,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,aAAa,EAAE,GAAG,UAAU,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAyB;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,KAAK,EAAE,KAAK,CAAC,GAAG;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;QACrD,UAAU,EAAE,KAAK,CAAC,GAAG;QACrB,MAAM,EAAE,KAAK,CAAC,KAAK;QACnB,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC;KACzB,CAAC,CAAC;AACP,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAc;IAC3C,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChG,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QAClC,IAAI,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5F,IAAI,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzF,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClF,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Return `true` when an offset lands inside the string-literal argument
3
+ * of a `<binding>.output("...")` call. The binding name itself is not
4
+ * validated here — the resolver inspects bindings when collecting
5
+ * completions or hovers.
6
+ *
7
+ * @since 0.7
8
+ * @stable
9
+ * @example
10
+ * const inside = isInsideOutputStringLiteral('baseTrend.output("line")', 19);
11
+ * void inside;
12
+ */
13
+ export declare function isInsideOutputStringLiteral(source: string, offset: number): boolean;
14
+ //# sourceMappingURL=isInsideOutputStringLiteral.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isInsideOutputStringLiteral.d.ts","sourceRoot":"","sources":["../../src/_lib/isInsideOutputStringLiteral.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAkBnF"}
@@ -0,0 +1,44 @@
1
+ // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
+ // See the LICENSE file in the repo root for full license text.
3
+ import ts from "typescript";
4
+ /**
5
+ * Return `true` when an offset lands inside the string-literal argument
6
+ * of a `<binding>.output("...")` call. The binding name itself is not
7
+ * validated here — the resolver inspects bindings when collecting
8
+ * completions or hovers.
9
+ *
10
+ * @since 0.7
11
+ * @stable
12
+ * @example
13
+ * const inside = isInsideOutputStringLiteral('baseTrend.output("line")', 19);
14
+ * void inside;
15
+ */
16
+ export function isInsideOutputStringLiteral(source, offset) {
17
+ const sourceFile = ts.createSourceFile("script.chart.ts", source, ts.ScriptTarget.Latest, true);
18
+ let matched = false;
19
+ const visit = (node) => {
20
+ if (matched)
21
+ return;
22
+ if (ts.isStringLiteral(node) &&
23
+ offset > node.getStart(sourceFile) &&
24
+ offset < node.getEnd()) {
25
+ matched = isOutputCallArgument(node);
26
+ return;
27
+ }
28
+ ts.forEachChild(node, visit);
29
+ };
30
+ visit(sourceFile);
31
+ return matched;
32
+ }
33
+ function isOutputCallArgument(node) {
34
+ const parent = node.parent;
35
+ if (!ts.isCallExpression(parent))
36
+ return false;
37
+ if (parent.arguments[0] !== node)
38
+ return false;
39
+ const callee = parent.expression;
40
+ if (!ts.isPropertyAccessExpression(callee))
41
+ return false;
42
+ return callee.name.text === "output";
43
+ }
44
+ //# sourceMappingURL=isInsideOutputStringLiteral.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isInsideOutputStringLiteral.js","sourceRoot":"","sources":["../../src/_lib/isInsideOutputStringLiteral.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAc,EAAE,MAAc;IACtE,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChG,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QAClC,IAAI,OAAO;YAAE,OAAO;QACpB,IACI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;YACxB,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAClC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,EACxB,CAAC;YACC,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YACrC,OAAO;QACX,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAsB;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;AACzC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Return `true` when an offset lands at a **key** position inside the
3
+ * object-literal argument of a `<binding>.withInputs({ ... })` call.
4
+ * Value-position offsets return `false` so completions don't fire when
5
+ * the user is filling in an override's value.
6
+ *
7
+ * @since 0.7
8
+ * @stable
9
+ * @example
10
+ * const source = 'baseTrend.withInputs({ length: 20 })';
11
+ * const atKey = isInsideWithInputsKey(source, source.indexOf("length"));
12
+ * void atKey;
13
+ */
14
+ export declare function isInsideWithInputsKey(source: string, offset: number): boolean;
15
+ //# sourceMappingURL=isInsideWithInputsKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isInsideWithInputsKey.d.ts","sourceRoot":"","sources":["../../src/_lib/isInsideWithInputsKey.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAK7E"}
@@ -0,0 +1,64 @@
1
+ // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
+ // See the LICENSE file in the repo root for full license text.
3
+ import ts from "typescript";
4
+ /**
5
+ * Return `true` when an offset lands at a **key** position inside the
6
+ * object-literal argument of a `<binding>.withInputs({ ... })` call.
7
+ * Value-position offsets return `false` so completions don't fire when
8
+ * the user is filling in an override's value.
9
+ *
10
+ * @since 0.7
11
+ * @stable
12
+ * @example
13
+ * const source = 'baseTrend.withInputs({ length: 20 })';
14
+ * const atKey = isInsideWithInputsKey(source, source.indexOf("length"));
15
+ * void atKey;
16
+ */
17
+ export function isInsideWithInputsKey(source, offset) {
18
+ const sourceFile = ts.createSourceFile("script.chart.ts", source, ts.ScriptTarget.Latest, true);
19
+ const objectLiteral = findEnclosingWithInputsObjectLiteral(sourceFile, offset);
20
+ if (objectLiteral === null)
21
+ return false;
22
+ return !isInsideAnyPropertyValueRange(objectLiteral, sourceFile, offset);
23
+ }
24
+ function findEnclosingWithInputsObjectLiteral(sourceFile, offset) {
25
+ let match = null;
26
+ const visit = (node) => {
27
+ if (match !== null)
28
+ return;
29
+ if (ts.isObjectLiteralExpression(node) &&
30
+ offset > node.getStart(sourceFile) &&
31
+ offset < node.getEnd() &&
32
+ isWithInputsArgument(node)) {
33
+ match = node;
34
+ return;
35
+ }
36
+ ts.forEachChild(node, visit);
37
+ };
38
+ visit(sourceFile);
39
+ return match;
40
+ }
41
+ function isWithInputsArgument(node) {
42
+ const parent = node.parent;
43
+ if (!ts.isCallExpression(parent))
44
+ return false;
45
+ if (parent.arguments[0] !== node)
46
+ return false;
47
+ const callee = parent.expression;
48
+ if (!ts.isPropertyAccessExpression(callee))
49
+ return false;
50
+ return callee.name.text === "withInputs";
51
+ }
52
+ function isInsideAnyPropertyValueRange(objectLiteral, sourceFile, offset) {
53
+ for (const property of objectLiteral.properties) {
54
+ if (!ts.isPropertyAssignment(property))
55
+ continue;
56
+ const initializer = property.initializer;
57
+ const start = initializer.getStart(sourceFile);
58
+ const end = initializer.getEnd();
59
+ if (offset >= start && offset <= end)
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ //# sourceMappingURL=isInsideWithInputsKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isInsideWithInputsKey.js","sourceRoot":"","sources":["../../src/_lib/isInsideWithInputsKey.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,MAAc;IAChE,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChG,MAAM,aAAa,GAAG,oCAAoC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/E,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,CAAC,6BAA6B,CAAC,aAAa,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,oCAAoC,CACzC,UAAyB,EACzB,MAAc;IAEd,IAAI,KAAK,GAAsC,IAAI,CAAC;IAEpD,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QAClC,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO;QAC3B,IACI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;YAClC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAClC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;YACtB,oBAAoB,CAAC,IAAI,CAAC,EAC5B,CAAC;YACC,KAAK,GAAG,IAAI,CAAC;YACb,OAAO;QACX,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAgC;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC;AAC7C,CAAC;AAED,SAAS,6BAA6B,CAClC,aAAyC,EACzC,UAAyB,EACzB,MAAc;IAEd,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;QAC9C,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC;YAAE,SAAS;QACjD,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;QACzC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;QACjC,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,GAAG;YAAE,OAAO,IAAI,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { DefinitionLocation, HoverDoc } from "../types.js";
2
+ /**
3
+ * Producer-side input descriptor surfaced by the dep accessor helpers.
4
+ * `kind` is the `input.<kind>(default)` builder name; `defaultText` is
5
+ * the literal default-value text printed verbatim into the completion
6
+ * detail line.
7
+ *
8
+ * @since 0.7
9
+ * @stable
10
+ * @example
11
+ * const d: DepInputDescriptor = {
12
+ * name: "length",
13
+ * kind: "int",
14
+ * defaultText: "20",
15
+ * };
16
+ * void d;
17
+ */
18
+ export type DepInputDescriptor = Readonly<{
19
+ name: string;
20
+ kind: string;
21
+ defaultText: string;
22
+ }>;
23
+ /**
24
+ * Resolve a hover doc when the offset lands on a `<binding>.output(...)`
25
+ * or `<binding>.withInputs({...})` call site whose binding's initialiser
26
+ * is a same-file `defineIndicator(...)` (optionally chained through
27
+ * `.withInputs(...)`).
28
+ *
29
+ * @since 0.7
30
+ * @stable
31
+ * @example
32
+ * const fn: typeof resolveDepAccessorHover = resolveDepAccessorHover;
33
+ * void fn;
34
+ */
35
+ export declare function resolveDepAccessorHover(source: string, offset: number): HoverDoc | null;
36
+ /**
37
+ * Resolve a best-effort go-to-definition target for a
38
+ * `<binding>.output("title")` call. Returns the line / column of the
39
+ * producer's matching `plot(value, { title: "<title>" })` call when
40
+ * resolvable. Returns `null` when the binding is missing, the producer
41
+ * is not a same-file `defineIndicator`, or no matching `plot` call is
42
+ * found.
43
+ *
44
+ * @since 0.7
45
+ * @stable
46
+ * @example
47
+ * const fn: typeof resolveDepAccessorDefinition = resolveDepAccessorDefinition;
48
+ * void fn;
49
+ */
50
+ export declare function resolveDepAccessorDefinition(source: string, offset: number): DefinitionLocation | null;
51
+ /**
52
+ * Collect every producer-side titled output reachable from the binding
53
+ * at the offset's `<binding>.output("|")` call site. Returns `[]` when
54
+ * the binding is missing or the producer is not a same-file
55
+ * `defineIndicator(...)`.
56
+ *
57
+ * @since 0.7
58
+ * @stable
59
+ * @example
60
+ * const titles = resolveDepOutputsFor("baseTrend.output(\"\")", 18);
61
+ * void titles;
62
+ */
63
+ export declare function resolveDepOutputsFor(source: string, offset: number): ReadonlyArray<string>;
64
+ /**
65
+ * Collect every producer-side input descriptor reachable from the
66
+ * binding at the offset's `<binding>.withInputs({ |})` call site.
67
+ * Returns `[]` when the binding is missing or the producer is not a
68
+ * same-file `defineIndicator(...)`.
69
+ *
70
+ * @since 0.7
71
+ * @stable
72
+ * @example
73
+ * const inputs = resolveDepInputsFor("baseTrend.withInputs({ })", 22);
74
+ * void inputs;
75
+ */
76
+ export declare function resolveDepInputsFor(source: string, offset: number): ReadonlyArray<DepInputDescriptor>;
77
+ //# sourceMappingURL=resolveDepAccessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveDepAccessor.d.ts","sourceRoot":"","sources":["../../src/_lib/resolveDepAccessor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGhE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAIH;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAQvF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CACxC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACf,kBAAkB,GAAG,IAAI,CAqB3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAO1F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACf,aAAa,CAAC,kBAAkB,CAAC,CAOnC"}