@kekonic/diagrams-language-service 1.0.0-rc.4
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/LICENSE +21 -0
- package/README.md +16 -0
- package/dist/index.d.mts +127 -0
- package/dist/index.mjs +675 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kekonic
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# `@kekonic/diagrams-language-service`
|
|
2
|
+
|
|
3
|
+
Browser-compatible KDiagram language intelligence shared by Monaco and LSP hosts. The package owns
|
|
4
|
+
document snapshots, diagnostics, completion, hover, navigation, rename, symbols, folding, semantic
|
|
5
|
+
tokens, formatting, code actions, and the versioned custom-semantics extension protocol.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { KDiagramLanguageService } from "@kekonic/diagrams-language-service";
|
|
9
|
+
|
|
10
|
+
const service = new KDiagramLanguageService();
|
|
11
|
+
service.updateDocument("file:///architecture.kdiagram", source, 1);
|
|
12
|
+
const diagnostics = service.diagnostics("file:///architecture.kdiagram");
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Hosts supply transport and editor-specific conversions. Node processes should use
|
|
16
|
+
`kdiagrams lsp --stdio`; browser editors can call this package directly.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Diagnostic, SourceRange } from "@kekonic/diagrams-core";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
type LanguagePosition = {
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
offset?: number;
|
|
8
|
+
};
|
|
9
|
+
type LanguageRange = SourceRange;
|
|
10
|
+
type TextEdit = {
|
|
11
|
+
range: LanguageRange;
|
|
12
|
+
newText: string;
|
|
13
|
+
};
|
|
14
|
+
type WorkspaceTextEdit = TextEdit & {
|
|
15
|
+
uri: string;
|
|
16
|
+
};
|
|
17
|
+
type DocumentChange = {
|
|
18
|
+
text: string;
|
|
19
|
+
range?: {
|
|
20
|
+
start: LanguagePosition;
|
|
21
|
+
end: LanguagePosition;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
type CompletionKind = "keyword" | "kind" | "property" | "value" | "reference" | "style" | "icon" | "theme-token";
|
|
25
|
+
type CompletionItem = {
|
|
26
|
+
label: string;
|
|
27
|
+
kind: CompletionKind;
|
|
28
|
+
detail?: string;
|
|
29
|
+
documentation?: string;
|
|
30
|
+
insertText?: string;
|
|
31
|
+
};
|
|
32
|
+
type Hover = {
|
|
33
|
+
range: LanguageRange;
|
|
34
|
+
markdown: string;
|
|
35
|
+
preview?: {
|
|
36
|
+
kind: string;
|
|
37
|
+
shape: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
type Location = {
|
|
41
|
+
uri: string;
|
|
42
|
+
range: LanguageRange;
|
|
43
|
+
};
|
|
44
|
+
type DocumentSymbol = {
|
|
45
|
+
name: string;
|
|
46
|
+
kind: "diagram" | "node" | "group" | "style" | "animation";
|
|
47
|
+
range: LanguageRange;
|
|
48
|
+
children?: DocumentSymbol[];
|
|
49
|
+
};
|
|
50
|
+
type FoldingRange = {
|
|
51
|
+
startLine: number;
|
|
52
|
+
endLine: number;
|
|
53
|
+
};
|
|
54
|
+
type SemanticToken = {
|
|
55
|
+
line: number;
|
|
56
|
+
column: number;
|
|
57
|
+
length: number;
|
|
58
|
+
type: "keyword" | "string" | "number" | "operator" | "property" | "type" | "variable" | "class";
|
|
59
|
+
};
|
|
60
|
+
type CodeAction = {
|
|
61
|
+
title: string;
|
|
62
|
+
kind: "quickfix" | "source.format" | "source.migrate";
|
|
63
|
+
edits: TextEdit[];
|
|
64
|
+
diagnosticCode?: string;
|
|
65
|
+
};
|
|
66
|
+
type LanguageSnapshot = {
|
|
67
|
+
uri: string;
|
|
68
|
+
version: number;
|
|
69
|
+
source: string;
|
|
70
|
+
diagnostics: Diagnostic[];
|
|
71
|
+
};
|
|
72
|
+
type SemanticProperty = {
|
|
73
|
+
name: string;
|
|
74
|
+
description: string;
|
|
75
|
+
values?: readonly string[];
|
|
76
|
+
};
|
|
77
|
+
type LanguageExtension = {
|
|
78
|
+
protocolVersion: 1;
|
|
79
|
+
id: string;
|
|
80
|
+
kinds?: Record<string, {
|
|
81
|
+
description: string;
|
|
82
|
+
shape?: string;
|
|
83
|
+
}>;
|
|
84
|
+
properties?: SemanticProperty[];
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/catalog.d.ts
|
|
88
|
+
declare const LANGUAGE_KEYWORDS: readonly ["diagram", "state", "sequence", "group", "boundary", "zone", "swimlane", "style", "animation", "direction", "density", "layout", "edges", "render", "presentation", "activate", "deactivate", "create", "destroy", "note", "autonumber", "alt", "else", "opt", "loop", "par"];
|
|
89
|
+
declare const BUILTIN_PROPERTIES: readonly SemanticProperty[];
|
|
90
|
+
declare const builtinCatalog: {
|
|
91
|
+
readonly kinds: string[];
|
|
92
|
+
readonly kindDetails: Readonly<Record<string, import("@kekonic/diagrams-core").NodeKindDefaults>>;
|
|
93
|
+
readonly shapes: readonly ["rectangle", "rounded", "pill", "circle", "ellipse", "diamond", "hexagon", "triangle", "parallelogram", "trapezoid", "document", "folded-document", "cylinder", "cloud", "person", "queue", "stream", "table", "boundary"];
|
|
94
|
+
readonly edgeOperators: readonly ["<->", "<..", "<~", "<=", "<-", "x-", "=>", "~>", "..>", "-->", "-x", "->", "--"];
|
|
95
|
+
readonly icons: string[];
|
|
96
|
+
readonly styles: readonly ["danger", "warning", "success", "critical", "muted", "info"];
|
|
97
|
+
readonly themeTokens: string[];
|
|
98
|
+
readonly properties: readonly SemanticProperty[];
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/service.d.ts
|
|
102
|
+
declare class KDiagramLanguageService {
|
|
103
|
+
#private;
|
|
104
|
+
readonly protocolVersion: 1;
|
|
105
|
+
updateDocument(uri: string, source: string, version?: number): LanguageSnapshot;
|
|
106
|
+
applyDocumentChanges(uri: string, version: number, changes: readonly DocumentChange[]): LanguageSnapshot;
|
|
107
|
+
closeDocument(uri: string): void;
|
|
108
|
+
getDocument(uri: string): LanguageSnapshot | undefined;
|
|
109
|
+
diagnostics(uri: string): Diagnostic[];
|
|
110
|
+
format(uri: string): TextEdit[];
|
|
111
|
+
complete(uri: string, position: LanguagePosition): CompletionItem[];
|
|
112
|
+
hover(uri: string, position: LanguagePosition): Hover | undefined;
|
|
113
|
+
definition(uri: string, position: LanguagePosition): Location | undefined;
|
|
114
|
+
references(uri: string, position: LanguagePosition, includeDeclaration?: boolean): Location[];
|
|
115
|
+
rename(uri: string, position: LanguagePosition, newName: string): TextEdit[];
|
|
116
|
+
renameWorkspace(uri: string, position: LanguagePosition, newName: string): WorkspaceTextEdit[];
|
|
117
|
+
documentSymbols(uri: string): DocumentSymbol[];
|
|
118
|
+
foldingRanges(uri: string): FoldingRange[];
|
|
119
|
+
semanticTokens(uri: string): SemanticToken[];
|
|
120
|
+
codeActions(uri: string): CodeAction[];
|
|
121
|
+
registerExtension(extension: LanguageExtension): () => void;
|
|
122
|
+
}
|
|
123
|
+
declare function positionAt(source: string, offset: number): Required<LanguagePosition>;
|
|
124
|
+
declare function offsetAt(source: string, position: LanguagePosition): number;
|
|
125
|
+
//#endregion
|
|
126
|
+
export { BUILTIN_PROPERTIES, type CodeAction, type CompletionItem, type CompletionKind, type DocumentChange, type DocumentSymbol, type FoldingRange, type Hover, KDiagramLanguageService, LANGUAGE_KEYWORDS, type LanguageExtension, type LanguagePosition, type LanguageRange, type LanguageSnapshot, type Location, type SemanticProperty, type SemanticToken, type TextEdit, type WorkspaceTextEdit, builtinCatalog, offsetAt, positionAt };
|
|
127
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import { BUILTIN_KIND_CATALOG, BUILTIN_KIND_LIST, BUILTIN_SHAPE_IDS, EDGE_OPS, compile, formatSource, parse } from "@kekonic/diagrams-core";
|
|
2
|
+
import { listBuiltinIconIds } from "@kekonic/diagrams-icons";
|
|
3
|
+
import { BUILTIN_SEMANTIC_STYLE_NAMES, getThemeTokens } from "@kekonic/diagrams-theme";
|
|
4
|
+
//#region src/catalog.ts
|
|
5
|
+
const LANGUAGE_KEYWORDS = [
|
|
6
|
+
"diagram",
|
|
7
|
+
"state",
|
|
8
|
+
"sequence",
|
|
9
|
+
"group",
|
|
10
|
+
"boundary",
|
|
11
|
+
"zone",
|
|
12
|
+
"swimlane",
|
|
13
|
+
"style",
|
|
14
|
+
"animation",
|
|
15
|
+
"direction",
|
|
16
|
+
"density",
|
|
17
|
+
"layout",
|
|
18
|
+
"edges",
|
|
19
|
+
"render",
|
|
20
|
+
"presentation",
|
|
21
|
+
"activate",
|
|
22
|
+
"deactivate",
|
|
23
|
+
"create",
|
|
24
|
+
"destroy",
|
|
25
|
+
"note",
|
|
26
|
+
"autonumber",
|
|
27
|
+
"alt",
|
|
28
|
+
"else",
|
|
29
|
+
"opt",
|
|
30
|
+
"loop",
|
|
31
|
+
"par"
|
|
32
|
+
];
|
|
33
|
+
const BUILTIN_PROPERTIES = [
|
|
34
|
+
{
|
|
35
|
+
name: "label",
|
|
36
|
+
description: "Visible label for the element."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "subtitle",
|
|
40
|
+
description: "Secondary text shown beneath the label."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "icon",
|
|
44
|
+
description: "Built-in or collection-qualified icon identifier."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "shape",
|
|
48
|
+
description: "Geometry used to draw the node.",
|
|
49
|
+
values: BUILTIN_SHAPE_IDS
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "columns",
|
|
53
|
+
description: "ERD table column declarations."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "direction",
|
|
57
|
+
description: "Diagram reading direction.",
|
|
58
|
+
values: [
|
|
59
|
+
"LR",
|
|
60
|
+
"RL",
|
|
61
|
+
"TD",
|
|
62
|
+
"BT"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "density",
|
|
67
|
+
description: "Layout spacing policy.",
|
|
68
|
+
values: [
|
|
69
|
+
"compact",
|
|
70
|
+
"normal",
|
|
71
|
+
"spacious"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "route",
|
|
76
|
+
description: "Edge routing algorithm.",
|
|
77
|
+
values: [
|
|
78
|
+
"straight",
|
|
79
|
+
"bezier",
|
|
80
|
+
"orthogonal",
|
|
81
|
+
"rounded",
|
|
82
|
+
"metro"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "stroke",
|
|
87
|
+
description: "Authored stroke color or theme-token reference."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "fill",
|
|
91
|
+
description: "Authored fill color or theme-token reference."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "arrange",
|
|
95
|
+
description: "Group content arrangement.",
|
|
96
|
+
values: [
|
|
97
|
+
"flow",
|
|
98
|
+
"pack",
|
|
99
|
+
"stack",
|
|
100
|
+
"row",
|
|
101
|
+
"grid"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "align",
|
|
106
|
+
description: "Group content alignment.",
|
|
107
|
+
values: [
|
|
108
|
+
"stretch",
|
|
109
|
+
"start",
|
|
110
|
+
"center",
|
|
111
|
+
"end"
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "gap",
|
|
116
|
+
description: "Explicit group gap."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "row",
|
|
120
|
+
description: "Grid row placement."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "column",
|
|
124
|
+
description: "Grid column placement."
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "rowSpan",
|
|
128
|
+
description: "Number of grid rows occupied."
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "colSpan",
|
|
132
|
+
description: "Number of grid columns occupied."
|
|
133
|
+
}
|
|
134
|
+
];
|
|
135
|
+
const builtinCatalog = {
|
|
136
|
+
kinds: BUILTIN_KIND_LIST,
|
|
137
|
+
kindDetails: BUILTIN_KIND_CATALOG,
|
|
138
|
+
shapes: BUILTIN_SHAPE_IDS,
|
|
139
|
+
edgeOperators: EDGE_OPS,
|
|
140
|
+
icons: listBuiltinIconIds(),
|
|
141
|
+
styles: BUILTIN_SEMANTIC_STYLE_NAMES,
|
|
142
|
+
themeTokens: Object.keys(getThemeTokens("dark")).sort(),
|
|
143
|
+
properties: BUILTIN_PROPERTIES
|
|
144
|
+
};
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/service.ts
|
|
147
|
+
const IDENTIFIER = /[A-Za-z_][\w-]*/gu;
|
|
148
|
+
const WORD_AT = /[A-Za-z_][\w-]*/u;
|
|
149
|
+
var KDiagramLanguageService = class {
|
|
150
|
+
constructor() {
|
|
151
|
+
this.protocolVersion = 1;
|
|
152
|
+
this.#documents = /* @__PURE__ */ new Map();
|
|
153
|
+
this.#extensions = /* @__PURE__ */ new Map();
|
|
154
|
+
}
|
|
155
|
+
#documents;
|
|
156
|
+
#extensions;
|
|
157
|
+
updateDocument(uri, source, version = 1) {
|
|
158
|
+
const previous = this.#documents.get(uri);
|
|
159
|
+
if (previous && version < previous.version) return snapshot(previous);
|
|
160
|
+
const ast = parse(source);
|
|
161
|
+
const compiled = compile(ast);
|
|
162
|
+
const record = {
|
|
163
|
+
uri,
|
|
164
|
+
source,
|
|
165
|
+
version,
|
|
166
|
+
diagnostics: dedupeDiagnostics([...ast.diagnostics, ...compiled.diagnostics]),
|
|
167
|
+
ast,
|
|
168
|
+
symbols: collectSymbols(source, ast),
|
|
169
|
+
references: collectReferences(source)
|
|
170
|
+
};
|
|
171
|
+
this.#documents.set(uri, record);
|
|
172
|
+
return snapshot(record);
|
|
173
|
+
}
|
|
174
|
+
applyDocumentChanges(uri, version, changes) {
|
|
175
|
+
const current = this.#require(uri);
|
|
176
|
+
if (version < current.version) return snapshot(current);
|
|
177
|
+
let source = current.source;
|
|
178
|
+
for (const change of changes) {
|
|
179
|
+
if (!change.range) {
|
|
180
|
+
source = change.text;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
const start = offsetAt(source, change.range.start);
|
|
184
|
+
const end = offsetAt(source, change.range.end);
|
|
185
|
+
if (end < start) throw new Error("KDiagram document change range ends before it starts");
|
|
186
|
+
source = `${source.slice(0, start)}${change.text}${source.slice(end)}`;
|
|
187
|
+
}
|
|
188
|
+
return this.updateDocument(uri, source, version);
|
|
189
|
+
}
|
|
190
|
+
closeDocument(uri) {
|
|
191
|
+
this.#documents.delete(uri);
|
|
192
|
+
}
|
|
193
|
+
getDocument(uri) {
|
|
194
|
+
const document = this.#documents.get(uri);
|
|
195
|
+
return document ? snapshot(document) : void 0;
|
|
196
|
+
}
|
|
197
|
+
diagnostics(uri) {
|
|
198
|
+
return [...this.#require(uri).diagnostics];
|
|
199
|
+
}
|
|
200
|
+
format(uri) {
|
|
201
|
+
const document = this.#require(uri);
|
|
202
|
+
const formatted = formatSource(document.source);
|
|
203
|
+
return formatted === document.source ? [] : [{
|
|
204
|
+
range: fullRange(document.source),
|
|
205
|
+
newText: formatted
|
|
206
|
+
}];
|
|
207
|
+
}
|
|
208
|
+
complete(uri, position) {
|
|
209
|
+
const document = this.#require(uri);
|
|
210
|
+
const offset = offsetAt(document.source, position);
|
|
211
|
+
const before = document.source.slice(Math.max(0, offset - 160), offset);
|
|
212
|
+
const customKinds = [...this.#extensions.values()].flatMap((extension) => Object.keys(extension.kinds ?? {}));
|
|
213
|
+
const customProperties = [...this.#extensions.values()].flatMap((extension) => extension.properties ?? []);
|
|
214
|
+
if (/\bicon\s*:\s*[\w:-]*$/u.test(before)) return builtinCatalog.icons.map((label) => ({
|
|
215
|
+
label,
|
|
216
|
+
kind: "icon",
|
|
217
|
+
detail: "Built-in icon"
|
|
218
|
+
}));
|
|
219
|
+
if (/\bshape\s*:\s*[\w-]*$/u.test(before)) return builtinCatalog.shapes.map((label) => ({
|
|
220
|
+
label,
|
|
221
|
+
kind: "value",
|
|
222
|
+
detail: "Built-in shape"
|
|
223
|
+
}));
|
|
224
|
+
if (/\bis\s+[\w-]*$/u.test(before)) {
|
|
225
|
+
const authored = document.symbols.filter((item) => item.kind === "style").map((item) => item.name);
|
|
226
|
+
return unique([...builtinCatalog.styles, ...authored]).map((label) => ({
|
|
227
|
+
label,
|
|
228
|
+
kind: "style"
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
if (/var\(\s*--[\w-]*$/u.test(before)) return builtinCatalog.themeTokens.map((label) => ({
|
|
232
|
+
label,
|
|
233
|
+
kind: "theme-token"
|
|
234
|
+
}));
|
|
235
|
+
const property = /\b([A-Za-z][\w-]*)\s*:\s*[\w-]*$/u.exec(before)?.[1];
|
|
236
|
+
if (property) {
|
|
237
|
+
const definition = [...builtinCatalog.properties, ...customProperties].find((item) => item.name === property);
|
|
238
|
+
if (definition?.values) return definition.values.map((label) => ({
|
|
239
|
+
label,
|
|
240
|
+
kind: "value",
|
|
241
|
+
detail: definition.description
|
|
242
|
+
}));
|
|
243
|
+
if (property === "columns") return tableColumnCompletions(document);
|
|
244
|
+
if (property === "theme") return ["dark", "light"].map((label) => ({
|
|
245
|
+
label,
|
|
246
|
+
kind: "value"
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
if (/^\s*[A-Za-z_][\w-]*\s*:\s*[\w-]*$/u.test(linePrefix(document.source, offset))) return unique([...builtinCatalog.kinds, ...customKinds]).map((label) => ({
|
|
250
|
+
label,
|
|
251
|
+
kind: "kind",
|
|
252
|
+
detail: this.#kindDescription(label)
|
|
253
|
+
}));
|
|
254
|
+
if (/\{[^{}]*$/u.test(before)) return uniqueProperties([...builtinCatalog.properties, ...customProperties]).map((item) => ({
|
|
255
|
+
label: item.name,
|
|
256
|
+
kind: "property",
|
|
257
|
+
detail: item.description,
|
|
258
|
+
insertText: `${item.name}: `
|
|
259
|
+
}));
|
|
260
|
+
const ids = document.symbols.filter((item) => item.kind === "node" || item.kind === "group");
|
|
261
|
+
return [...LANGUAGE_KEYWORDS.map((label) => ({
|
|
262
|
+
label,
|
|
263
|
+
kind: "keyword"
|
|
264
|
+
})), ...ids.map((item) => ({
|
|
265
|
+
label: item.name,
|
|
266
|
+
kind: "reference",
|
|
267
|
+
detail: item.detail
|
|
268
|
+
}))];
|
|
269
|
+
}
|
|
270
|
+
hover(uri, position) {
|
|
271
|
+
const document = this.#require(uri);
|
|
272
|
+
const word = wordAt(document.source, offsetAt(document.source, position));
|
|
273
|
+
if (!word) return void 0;
|
|
274
|
+
const symbol = document.symbols.find((item) => item.name === word.value);
|
|
275
|
+
if (symbol) return {
|
|
276
|
+
range: word.range,
|
|
277
|
+
markdown: `**${symbol.name}** \nKDiagram ${symbol.kind}${symbol.detail ? ` · ${symbol.detail}` : ""}`
|
|
278
|
+
};
|
|
279
|
+
const kind = builtinCatalog.kindDetails[word.value];
|
|
280
|
+
if (kind) return {
|
|
281
|
+
range: word.range,
|
|
282
|
+
markdown: `**${word.value}** · ${kind.subtitle} \nShape: \`${kind.shape}\` · Category: ${kind.category}`,
|
|
283
|
+
preview: {
|
|
284
|
+
kind: word.value,
|
|
285
|
+
shape: kind.shape
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
for (const extension of this.#extensions.values()) {
|
|
289
|
+
const custom = extension.kinds?.[word.value];
|
|
290
|
+
if (custom) return {
|
|
291
|
+
range: word.range,
|
|
292
|
+
markdown: `**${word.value}** · ${custom.description}${custom.shape ? ` \nShape: \`${custom.shape}\`` : ""}`,
|
|
293
|
+
preview: custom.shape ? {
|
|
294
|
+
kind: word.value,
|
|
295
|
+
shape: custom.shape
|
|
296
|
+
} : void 0
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const property = this.#properties().find((item) => item.name === word.value);
|
|
300
|
+
if (property) return {
|
|
301
|
+
range: word.range,
|
|
302
|
+
markdown: `**${property.name}** \n${property.description}`
|
|
303
|
+
};
|
|
304
|
+
if (builtinCatalog.themeTokens.includes(word.value.startsWith("--") ? word.value : `--${word.value}`)) return {
|
|
305
|
+
range: word.range,
|
|
306
|
+
markdown: `Theme token \`${word.value}\``
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
definition(uri, position) {
|
|
310
|
+
const document = this.#require(uri);
|
|
311
|
+
const word = wordAt(document.source, offsetAt(document.source, position));
|
|
312
|
+
if (!word) return void 0;
|
|
313
|
+
for (const candidate of [document, ...this.#documents.values()]) {
|
|
314
|
+
const symbol = candidate.symbols.find((item) => item.name === word.value);
|
|
315
|
+
if (symbol) return {
|
|
316
|
+
uri: candidate.uri,
|
|
317
|
+
range: symbol.selectionRange
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
references(uri, position, includeDeclaration = true) {
|
|
322
|
+
const document = this.#require(uri);
|
|
323
|
+
const word = wordAt(document.source, offsetAt(document.source, position));
|
|
324
|
+
if (!word) return [];
|
|
325
|
+
const locations = [];
|
|
326
|
+
for (const candidate of this.#documents.values()) {
|
|
327
|
+
const declaration = candidate.symbols.find((item) => item.name === word.value)?.selectionRange;
|
|
328
|
+
locations.push(...(candidate.references.get(word.value) ?? []).filter((range) => includeDeclaration || !sameRange(range, declaration)).map((range) => ({
|
|
329
|
+
uri: candidate.uri,
|
|
330
|
+
range
|
|
331
|
+
})));
|
|
332
|
+
}
|
|
333
|
+
return locations;
|
|
334
|
+
}
|
|
335
|
+
rename(uri, position, newName) {
|
|
336
|
+
return this.renameWorkspace(uri, position, newName).filter((edit) => edit.uri === uri).map(({ range, newText }) => ({
|
|
337
|
+
range,
|
|
338
|
+
newText
|
|
339
|
+
}));
|
|
340
|
+
}
|
|
341
|
+
renameWorkspace(uri, position, newName) {
|
|
342
|
+
if (!/^[A-Za-z_][\w-]*$/u.test(newName)) throw new Error(`Invalid KDiagram identifier: ${newName}`);
|
|
343
|
+
const document = this.#require(uri);
|
|
344
|
+
const word = wordAt(document.source, offsetAt(document.source, position));
|
|
345
|
+
if (!word || ![...this.#documents.values()].some((candidate) => candidate.symbols.some((item) => item.name === word.value))) return [];
|
|
346
|
+
return [...this.#documents.values()].flatMap((candidate) => (candidate.references.get(word.value) ?? []).map((range) => ({
|
|
347
|
+
uri: candidate.uri,
|
|
348
|
+
range,
|
|
349
|
+
newText: newName
|
|
350
|
+
})));
|
|
351
|
+
}
|
|
352
|
+
documentSymbols(uri) {
|
|
353
|
+
return this.#require(uri).symbols.map(({ name, kind, range }) => ({
|
|
354
|
+
name,
|
|
355
|
+
kind,
|
|
356
|
+
range
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
foldingRanges(uri) {
|
|
360
|
+
const source = this.#require(uri).source;
|
|
361
|
+
const stack = [];
|
|
362
|
+
const ranges = [];
|
|
363
|
+
let line = 1;
|
|
364
|
+
let quote = false;
|
|
365
|
+
let comment = false;
|
|
366
|
+
for (let offset = 0; offset < source.length; offset++) {
|
|
367
|
+
const char = source[offset];
|
|
368
|
+
const next = source[offset + 1];
|
|
369
|
+
if (char === "\n") {
|
|
370
|
+
line++;
|
|
371
|
+
comment = false;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (!quote && !comment && char === "/" && next === "/") {
|
|
375
|
+
comment = true;
|
|
376
|
+
offset++;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (comment) continue;
|
|
380
|
+
if (char === "\"" && source[offset - 1] !== "\\") quote = !quote;
|
|
381
|
+
if (quote) continue;
|
|
382
|
+
if (char === "{") stack.push({ line });
|
|
383
|
+
if (char === "}") {
|
|
384
|
+
const start = stack.pop();
|
|
385
|
+
if (start && line > start.line) ranges.push({
|
|
386
|
+
startLine: start.line,
|
|
387
|
+
endLine: line
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return ranges;
|
|
392
|
+
}
|
|
393
|
+
semanticTokens(uri) {
|
|
394
|
+
const source = this.#require(uri).source;
|
|
395
|
+
const tokens = [];
|
|
396
|
+
for (const match of source.matchAll(/"(?:[^"\\]|\\.)*"|(?:-->|->|=>|~>|\.>|-x>|<->|<-)|\b\d+(?:\.\d+)?\b|[A-Za-z_][\w-]*/gu)) {
|
|
397
|
+
const value = match[0];
|
|
398
|
+
const offset = match.index;
|
|
399
|
+
const position = positionAt(source, offset);
|
|
400
|
+
let type = "variable";
|
|
401
|
+
if (value.startsWith("\"")) type = "string";
|
|
402
|
+
else if (/^\d/u.test(value)) type = "number";
|
|
403
|
+
else if (builtinCatalog.edgeOperators.includes(value)) type = "operator";
|
|
404
|
+
else if (LANGUAGE_KEYWORDS.includes(value)) type = "keyword";
|
|
405
|
+
else if (this.#kindDescription(value)) type = "type";
|
|
406
|
+
else if (this.#properties().some((item) => item.name === value) && /^\s*:/u.test(source.slice(offset + value.length))) type = "property";
|
|
407
|
+
else if (this.#require(uri).symbols.some((item) => item.kind === "style" && item.name === value)) type = "class";
|
|
408
|
+
tokens.push({
|
|
409
|
+
line: position.line,
|
|
410
|
+
column: position.column,
|
|
411
|
+
length: value.length,
|
|
412
|
+
type
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return tokens;
|
|
416
|
+
}
|
|
417
|
+
codeActions(uri) {
|
|
418
|
+
const document = this.#require(uri);
|
|
419
|
+
const actions = [];
|
|
420
|
+
const formatting = this.format(uri);
|
|
421
|
+
if (formatting.length) actions.push({
|
|
422
|
+
title: "Format KDiagram document",
|
|
423
|
+
kind: "source.format",
|
|
424
|
+
edits: formatting
|
|
425
|
+
});
|
|
426
|
+
for (const diagnostic of document.diagnostics) {
|
|
427
|
+
const replacement = /Did you mean (?:“|")([^”"]+)(?:”|")\?/u.exec(diagnostic.hint ?? "")?.[1];
|
|
428
|
+
if (!replacement) continue;
|
|
429
|
+
actions.push({
|
|
430
|
+
title: `Replace with ‘${replacement}’`,
|
|
431
|
+
kind: "quickfix",
|
|
432
|
+
edits: [{
|
|
433
|
+
range: diagnostic.range,
|
|
434
|
+
newText: replacement
|
|
435
|
+
}],
|
|
436
|
+
diagnosticCode: diagnostic.code
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
for (const match of document.source.matchAll(/\broomy\b/gu)) actions.push({
|
|
440
|
+
title: "Migrate deprecated density ‘roomy’ to ‘spacious’",
|
|
441
|
+
kind: "source.migrate",
|
|
442
|
+
edits: [{
|
|
443
|
+
range: rangeFromOffsets(document.source, match.index, match.index + match[0].length),
|
|
444
|
+
newText: "spacious"
|
|
445
|
+
}]
|
|
446
|
+
});
|
|
447
|
+
return actions;
|
|
448
|
+
}
|
|
449
|
+
registerExtension(extension) {
|
|
450
|
+
const protocolVersion = extension.protocolVersion;
|
|
451
|
+
if (protocolVersion !== 1) throw new Error(`Unsupported language extension protocol: ${protocolVersion}`);
|
|
452
|
+
if (!extension.id.trim()) throw new Error("Language extension id is required");
|
|
453
|
+
this.#extensions.set(extension.id, extension);
|
|
454
|
+
return () => {
|
|
455
|
+
this.#extensions.delete(extension.id);
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
#properties() {
|
|
459
|
+
return uniqueProperties([...builtinCatalog.properties, ...[...this.#extensions.values()].flatMap((extension) => extension.properties ?? [])]);
|
|
460
|
+
}
|
|
461
|
+
#kindDescription(kind) {
|
|
462
|
+
const builtin = builtinCatalog.kindDetails[kind];
|
|
463
|
+
if (builtin) return `${builtin.subtitle} · ${builtin.category} · ${builtin.shape}`;
|
|
464
|
+
for (const extension of this.#extensions.values()) {
|
|
465
|
+
const custom = extension.kinds?.[kind];
|
|
466
|
+
if (custom) return custom.description;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
#require(uri) {
|
|
470
|
+
const document = this.#documents.get(uri);
|
|
471
|
+
if (!document) throw new Error(`Unknown KDiagram document: ${uri}`);
|
|
472
|
+
return document;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
function snapshot(document) {
|
|
476
|
+
return {
|
|
477
|
+
uri: document.uri,
|
|
478
|
+
source: document.source,
|
|
479
|
+
version: document.version,
|
|
480
|
+
diagnostics: [...document.diagnostics]
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function dedupeDiagnostics(diagnostics) {
|
|
484
|
+
const seen = /* @__PURE__ */ new Set();
|
|
485
|
+
return diagnostics.filter((item) => {
|
|
486
|
+
const key = `${item.code}:${item.message}:${item.range.start.offset}:${item.range.end.offset}`;
|
|
487
|
+
if (seen.has(key)) return false;
|
|
488
|
+
seen.add(key);
|
|
489
|
+
return true;
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
function collectSymbols(source, ast) {
|
|
493
|
+
const symbols = [];
|
|
494
|
+
for (const top of ast.body) {
|
|
495
|
+
const name = top.name ?? (top.type === "Sequence" ? "Sequence" : top.diagramKind === "state" ? "State" : "Diagram");
|
|
496
|
+
symbols.push({
|
|
497
|
+
name,
|
|
498
|
+
kind: "diagram",
|
|
499
|
+
range: top.range,
|
|
500
|
+
selectionRange: findTextRange(source, top.range, top.name ?? top.type.toLowerCase())
|
|
501
|
+
});
|
|
502
|
+
visitStatements(source, top.statements, symbols);
|
|
503
|
+
}
|
|
504
|
+
return symbols;
|
|
505
|
+
}
|
|
506
|
+
function visitStatements(source, statements, symbols) {
|
|
507
|
+
for (const statement of statements) switch (statement.type) {
|
|
508
|
+
case "Node":
|
|
509
|
+
symbols.push({
|
|
510
|
+
name: statement.id,
|
|
511
|
+
kind: "node",
|
|
512
|
+
range: statement.range,
|
|
513
|
+
selectionRange: findTextRange(source, statement.range, statement.id),
|
|
514
|
+
detail: statement.kind
|
|
515
|
+
});
|
|
516
|
+
break;
|
|
517
|
+
case "Group":
|
|
518
|
+
if (statement.id) symbols.push({
|
|
519
|
+
name: statement.id,
|
|
520
|
+
kind: "group",
|
|
521
|
+
range: statement.range,
|
|
522
|
+
selectionRange: findTextRange(source, statement.range, statement.id),
|
|
523
|
+
detail: statement.groupKind
|
|
524
|
+
});
|
|
525
|
+
visitStatements(source, statement.statements, symbols);
|
|
526
|
+
break;
|
|
527
|
+
case "Style":
|
|
528
|
+
symbols.push({
|
|
529
|
+
name: statement.name,
|
|
530
|
+
kind: "style",
|
|
531
|
+
range: statement.range,
|
|
532
|
+
selectionRange: findTextRange(source, statement.range, statement.name),
|
|
533
|
+
detail: statement.target
|
|
534
|
+
});
|
|
535
|
+
break;
|
|
536
|
+
case "AnimationBlock":
|
|
537
|
+
symbols.push({
|
|
538
|
+
name: statement.name,
|
|
539
|
+
kind: "animation",
|
|
540
|
+
range: statement.range,
|
|
541
|
+
selectionRange: findTextRange(source, statement.range, statement.name)
|
|
542
|
+
});
|
|
543
|
+
break;
|
|
544
|
+
case "SequenceCreate":
|
|
545
|
+
symbols.push({
|
|
546
|
+
name: statement.node.id,
|
|
547
|
+
kind: "node",
|
|
548
|
+
range: statement.range,
|
|
549
|
+
selectionRange: findTextRange(source, statement.range, statement.node.id),
|
|
550
|
+
detail: statement.node.kind
|
|
551
|
+
});
|
|
552
|
+
break;
|
|
553
|
+
case "SequenceFragment":
|
|
554
|
+
for (const operand of statement.operands) visitStatements(source, operand.statements, symbols);
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function collectReferences(source) {
|
|
559
|
+
const references = /* @__PURE__ */ new Map();
|
|
560
|
+
for (const match of semanticIdentifierMatches(source)) {
|
|
561
|
+
const ranges = references.get(match[0]) ?? [];
|
|
562
|
+
const index = match.index;
|
|
563
|
+
ranges.push(rangeFromOffsets(source, index, index + match[0].length));
|
|
564
|
+
references.set(match[0], ranges);
|
|
565
|
+
}
|
|
566
|
+
return references;
|
|
567
|
+
}
|
|
568
|
+
function semanticIdentifierMatches(source) {
|
|
569
|
+
const masked = source.split("");
|
|
570
|
+
let quote = false;
|
|
571
|
+
let lineComment = false;
|
|
572
|
+
let blockComment = false;
|
|
573
|
+
for (let index = 0; index < source.length; index++) {
|
|
574
|
+
const char = source[index];
|
|
575
|
+
const next = source[index + 1];
|
|
576
|
+
if (lineComment) {
|
|
577
|
+
if (char === "\n") lineComment = false;
|
|
578
|
+
else masked[index] = " ";
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
if (blockComment) {
|
|
582
|
+
masked[index] = char === "\n" ? "\n" : " ";
|
|
583
|
+
if (char === "*" && next === "/") {
|
|
584
|
+
masked[index + 1] = " ";
|
|
585
|
+
blockComment = false;
|
|
586
|
+
index++;
|
|
587
|
+
}
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
if (!quote && char === "/" && next === "/") {
|
|
591
|
+
masked[index] = masked[index + 1] = " ";
|
|
592
|
+
lineComment = true;
|
|
593
|
+
index++;
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
if (!quote && char === "/" && next === "*") {
|
|
597
|
+
masked[index] = masked[index + 1] = " ";
|
|
598
|
+
blockComment = true;
|
|
599
|
+
index++;
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
if (char === "\"" && source[index - 1] !== "\\") {
|
|
603
|
+
quote = !quote;
|
|
604
|
+
masked[index] = " ";
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
if (quote) masked[index] = char === "\n" ? "\n" : " ";
|
|
608
|
+
}
|
|
609
|
+
return [...masked.join("").matchAll(IDENTIFIER)];
|
|
610
|
+
}
|
|
611
|
+
function tableColumnCompletions(document) {
|
|
612
|
+
const names = /* @__PURE__ */ new Set();
|
|
613
|
+
for (const match of document.source.matchAll(/\b(?:pk|fk|uk)?\s*([A-Za-z_][\w-]*)\s*:/gu)) names.add(match[1]);
|
|
614
|
+
return [...names].sort().map((label) => ({
|
|
615
|
+
label,
|
|
616
|
+
kind: "reference",
|
|
617
|
+
detail: "Table column"
|
|
618
|
+
}));
|
|
619
|
+
}
|
|
620
|
+
function wordAt(source, offset) {
|
|
621
|
+
let start = Math.min(offset, source.length);
|
|
622
|
+
while (start > 0 && /[\w-]/u.test(source[start - 1])) start--;
|
|
623
|
+
const match = WORD_AT.exec(source.slice(start));
|
|
624
|
+
if (!match || match.index !== 0) return void 0;
|
|
625
|
+
return {
|
|
626
|
+
value: match[0],
|
|
627
|
+
range: rangeFromOffsets(source, start, start + match[0].length)
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
function findTextRange(source, within, text) {
|
|
631
|
+
const offset = source.indexOf(text, within.start.offset);
|
|
632
|
+
if (offset < 0 || offset >= within.end.offset) return within;
|
|
633
|
+
return rangeFromOffsets(source, offset, offset + text.length);
|
|
634
|
+
}
|
|
635
|
+
function positionAt(source, offset) {
|
|
636
|
+
const bounded = Math.max(0, Math.min(offset, source.length));
|
|
637
|
+
const prefix = source.slice(0, bounded);
|
|
638
|
+
return {
|
|
639
|
+
line: prefix.split("\n").length,
|
|
640
|
+
column: bounded - prefix.lastIndexOf("\n"),
|
|
641
|
+
offset: bounded
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function offsetAt(source, position) {
|
|
645
|
+
if (position.offset != null) return Math.max(0, Math.min(position.offset, source.length));
|
|
646
|
+
const lines = source.split("\n");
|
|
647
|
+
let offset = 0;
|
|
648
|
+
for (let line = 1; line < position.line; line++) offset += (lines[line - 1]?.length ?? 0) + 1;
|
|
649
|
+
return Math.min(source.length, offset + Math.max(0, position.column - 1));
|
|
650
|
+
}
|
|
651
|
+
function rangeFromOffsets(source, start, end) {
|
|
652
|
+
return {
|
|
653
|
+
start: positionAt(source, start),
|
|
654
|
+
end: positionAt(source, end)
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
function fullRange(source) {
|
|
658
|
+
return rangeFromOffsets(source, 0, source.length);
|
|
659
|
+
}
|
|
660
|
+
function linePrefix(source, offset) {
|
|
661
|
+
return source.slice(source.lastIndexOf("\n", offset - 1) + 1, offset);
|
|
662
|
+
}
|
|
663
|
+
function sameRange(left, right) {
|
|
664
|
+
return Boolean(right && left.start.offset === right.start.offset && left.end.offset === right.end.offset);
|
|
665
|
+
}
|
|
666
|
+
function unique(values) {
|
|
667
|
+
return [...new Set(values)].sort();
|
|
668
|
+
}
|
|
669
|
+
function uniqueProperties(values) {
|
|
670
|
+
return [...new Map(values.map((item) => [item.name, item])).values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
671
|
+
}
|
|
672
|
+
//#endregion
|
|
673
|
+
export { BUILTIN_PROPERTIES, KDiagramLanguageService, LANGUAGE_KEYWORDS, builtinCatalog, offsetAt, positionAt };
|
|
674
|
+
|
|
675
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#documents","#extensions","#require","#kindDescription","#properties"],"sources":["../src/catalog.ts","../src/service.ts"],"sourcesContent":["import {\n BUILTIN_KIND_CATALOG,\n BUILTIN_KIND_LIST,\n BUILTIN_SHAPE_IDS,\n EDGE_OPS,\n} from \"@kekonic/diagrams-core\";\nimport { listBuiltinIconIds } from \"@kekonic/diagrams-icons\";\nimport { BUILTIN_SEMANTIC_STYLE_NAMES, getThemeTokens } from \"@kekonic/diagrams-theme\";\nimport type { SemanticProperty } from \"./types.ts\";\n\nexport const LANGUAGE_KEYWORDS = [\n \"diagram\",\n \"state\",\n \"sequence\",\n \"group\",\n \"boundary\",\n \"zone\",\n \"swimlane\",\n \"style\",\n \"animation\",\n \"direction\",\n \"density\",\n \"layout\",\n \"edges\",\n \"render\",\n \"presentation\",\n \"activate\",\n \"deactivate\",\n \"create\",\n \"destroy\",\n \"note\",\n \"autonumber\",\n \"alt\",\n \"else\",\n \"opt\",\n \"loop\",\n \"par\",\n] as const;\n\nexport const BUILTIN_PROPERTIES: readonly SemanticProperty[] = [\n { name: \"label\", description: \"Visible label for the element.\" },\n { name: \"subtitle\", description: \"Secondary text shown beneath the label.\" },\n { name: \"icon\", description: \"Built-in or collection-qualified icon identifier.\" },\n { name: \"shape\", description: \"Geometry used to draw the node.\", values: BUILTIN_SHAPE_IDS },\n { name: \"columns\", description: \"ERD table column declarations.\" },\n {\n name: \"direction\",\n description: \"Diagram reading direction.\",\n values: [\"LR\", \"RL\", \"TD\", \"BT\"],\n },\n {\n name: \"density\",\n description: \"Layout spacing policy.\",\n values: [\"compact\", \"normal\", \"spacious\"],\n },\n {\n name: \"route\",\n description: \"Edge routing algorithm.\",\n values: [\"straight\", \"bezier\", \"orthogonal\", \"rounded\", \"metro\"],\n },\n { name: \"stroke\", description: \"Authored stroke color or theme-token reference.\" },\n { name: \"fill\", description: \"Authored fill color or theme-token reference.\" },\n {\n name: \"arrange\",\n description: \"Group content arrangement.\",\n values: [\"flow\", \"pack\", \"stack\", \"row\", \"grid\"],\n },\n {\n name: \"align\",\n description: \"Group content alignment.\",\n values: [\"stretch\", \"start\", \"center\", \"end\"],\n },\n { name: \"gap\", description: \"Explicit group gap.\" },\n { name: \"row\", description: \"Grid row placement.\" },\n { name: \"column\", description: \"Grid column placement.\" },\n { name: \"rowSpan\", description: \"Number of grid rows occupied.\" },\n { name: \"colSpan\", description: \"Number of grid columns occupied.\" },\n] as const;\n\nexport const builtinCatalog = {\n kinds: BUILTIN_KIND_LIST,\n kindDetails: BUILTIN_KIND_CATALOG,\n shapes: BUILTIN_SHAPE_IDS,\n edgeOperators: EDGE_OPS,\n icons: listBuiltinIconIds(),\n styles: BUILTIN_SEMANTIC_STYLE_NAMES,\n themeTokens: Object.keys(getThemeTokens(\"dark\")).sort(),\n properties: BUILTIN_PROPERTIES,\n} as const;\n","import {\n compile,\n formatSource,\n parse,\n type Diagnostic,\n type KDiagramAst,\n type SequenceStatementAst,\n type SourceRange,\n type StatementAst,\n} from \"@kekonic/diagrams-core\";\nimport { builtinCatalog, LANGUAGE_KEYWORDS } from \"./catalog.ts\";\nimport type {\n CodeAction,\n CompletionItem,\n DocumentSymbol,\n DocumentChange,\n FoldingRange,\n Hover,\n LanguageExtension,\n LanguagePosition,\n LanguageSnapshot,\n Location,\n SemanticProperty,\n SemanticToken,\n TextEdit,\n WorkspaceTextEdit,\n} from \"./types.ts\";\n\ntype SymbolRecord = {\n name: string;\n kind: \"diagram\" | \"node\" | \"group\" | \"style\" | \"animation\";\n range: SourceRange;\n selectionRange: SourceRange;\n detail?: string;\n};\n\ntype DocumentRecord = LanguageSnapshot & {\n ast: KDiagramAst;\n symbols: SymbolRecord[];\n references: Map<string, SourceRange[]>;\n};\n\nconst IDENTIFIER = /[A-Za-z_][\\w-]*/gu;\nconst WORD_AT = /[A-Za-z_][\\w-]*/u;\n\nexport class KDiagramLanguageService {\n readonly protocolVersion = 1 as const;\n readonly #documents = new Map<string, DocumentRecord>();\n readonly #extensions = new Map<string, LanguageExtension>();\n\n updateDocument(uri: string, source: string, version = 1): LanguageSnapshot {\n const previous = this.#documents.get(uri);\n if (previous && version < previous.version) return snapshot(previous);\n const ast = parse(source);\n const compiled = compile(ast);\n const diagnostics = dedupeDiagnostics([...ast.diagnostics, ...compiled.diagnostics]);\n const symbols = collectSymbols(source, ast);\n const references = collectReferences(source);\n const record: DocumentRecord = { uri, source, version, diagnostics, ast, symbols, references };\n this.#documents.set(uri, record);\n return snapshot(record);\n }\n\n applyDocumentChanges(\n uri: string,\n version: number,\n changes: readonly DocumentChange[],\n ): LanguageSnapshot {\n const current = this.#require(uri);\n if (version < current.version) return snapshot(current);\n let source = current.source;\n for (const change of changes) {\n if (!change.range) {\n source = change.text;\n continue;\n }\n const start = offsetAt(source, change.range.start);\n const end = offsetAt(source, change.range.end);\n if (end < start) throw new Error(\"KDiagram document change range ends before it starts\");\n source = `${source.slice(0, start)}${change.text}${source.slice(end)}`;\n }\n return this.updateDocument(uri, source, version);\n }\n\n closeDocument(uri: string): void {\n this.#documents.delete(uri);\n }\n\n getDocument(uri: string): LanguageSnapshot | undefined {\n const document = this.#documents.get(uri);\n return document ? snapshot(document) : undefined;\n }\n\n diagnostics(uri: string): Diagnostic[] {\n return [...this.#require(uri).diagnostics];\n }\n\n format(uri: string): TextEdit[] {\n const document = this.#require(uri);\n const formatted = formatSource(document.source);\n return formatted === document.source\n ? []\n : [{ range: fullRange(document.source), newText: formatted }];\n }\n\n complete(uri: string, position: LanguagePosition): CompletionItem[] {\n const document = this.#require(uri);\n const offset = offsetAt(document.source, position);\n const before = document.source.slice(Math.max(0, offset - 160), offset);\n const customKinds = [...this.#extensions.values()].flatMap((extension) =>\n Object.keys(extension.kinds ?? {}),\n );\n const customProperties = [...this.#extensions.values()].flatMap(\n (extension) => extension.properties ?? [],\n );\n if (/\\bicon\\s*:\\s*[\\w:-]*$/u.test(before)) {\n return builtinCatalog.icons.map((label) => ({\n label,\n kind: \"icon\",\n detail: \"Built-in icon\",\n }));\n }\n if (/\\bshape\\s*:\\s*[\\w-]*$/u.test(before)) {\n return builtinCatalog.shapes.map((label) => ({\n label,\n kind: \"value\",\n detail: \"Built-in shape\",\n }));\n }\n if (/\\bis\\s+[\\w-]*$/u.test(before)) {\n const authored = document.symbols\n .filter((item) => item.kind === \"style\")\n .map((item) => item.name);\n return unique([...builtinCatalog.styles, ...authored]).map((label) => ({\n label,\n kind: \"style\",\n }));\n }\n if (/var\\(\\s*--[\\w-]*$/u.test(before)) {\n return builtinCatalog.themeTokens.map((label) => ({ label, kind: \"theme-token\" }));\n }\n const property = /\\b([A-Za-z][\\w-]*)\\s*:\\s*[\\w-]*$/u.exec(before)?.[1];\n if (property) {\n const definition = [...builtinCatalog.properties, ...customProperties].find(\n (item) => item.name === property,\n );\n if (definition?.values)\n return definition.values.map((label) => ({\n label,\n kind: \"value\",\n detail: definition.description,\n }));\n if (property === \"columns\") return tableColumnCompletions(document);\n if (property === \"theme\")\n return [\"dark\", \"light\"].map((label) => ({ label, kind: \"value\" }) as CompletionItem);\n }\n if (/^\\s*[A-Za-z_][\\w-]*\\s*:\\s*[\\w-]*$/u.test(linePrefix(document.source, offset))) {\n return unique([...builtinCatalog.kinds, ...customKinds]).map((label) => ({\n label,\n kind: \"kind\",\n detail: this.#kindDescription(label),\n }));\n }\n if (/\\{[^{}]*$/u.test(before)) {\n return uniqueProperties([...builtinCatalog.properties, ...customProperties]).map((item) => ({\n label: item.name,\n kind: \"property\",\n detail: item.description,\n insertText: `${item.name}: `,\n }));\n }\n const ids = document.symbols.filter((item) => item.kind === \"node\" || item.kind === \"group\");\n return [\n ...LANGUAGE_KEYWORDS.map((label) => ({ label, kind: \"keyword\" as const })),\n ...ids.map((item) => ({ label: item.name, kind: \"reference\" as const, detail: item.detail })),\n ];\n }\n\n hover(uri: string, position: LanguagePosition): Hover | undefined {\n const document = this.#require(uri);\n const word = wordAt(document.source, offsetAt(document.source, position));\n if (!word) return undefined;\n const symbol = document.symbols.find((item) => item.name === word.value);\n if (symbol)\n return {\n range: word.range,\n markdown: `**${symbol.name}** \\nKDiagram ${symbol.kind}${symbol.detail ? ` · ${symbol.detail}` : \"\"}`,\n };\n const kind = builtinCatalog.kindDetails[word.value];\n if (kind)\n return {\n range: word.range,\n markdown: `**${word.value}** · ${kind.subtitle} \\nShape: \\`${kind.shape}\\` · Category: ${kind.category}`,\n preview: { kind: word.value, shape: kind.shape },\n };\n for (const extension of this.#extensions.values()) {\n const custom = extension.kinds?.[word.value];\n if (custom)\n return {\n range: word.range,\n markdown: `**${word.value}** · ${custom.description}${custom.shape ? ` \\nShape: \\`${custom.shape}\\`` : \"\"}`,\n preview: custom.shape ? { kind: word.value, shape: custom.shape } : undefined,\n };\n }\n const property = this.#properties().find((item) => item.name === word.value);\n if (property)\n return { range: word.range, markdown: `**${property.name}** \\n${property.description}` };\n if (\n (builtinCatalog.themeTokens as readonly string[]).includes(\n word.value.startsWith(\"--\") ? word.value : `--${word.value}`,\n )\n ) {\n return { range: word.range, markdown: `Theme token \\`${word.value}\\`` };\n }\n return undefined;\n }\n\n definition(uri: string, position: LanguagePosition): Location | undefined {\n const document = this.#require(uri);\n const word = wordAt(document.source, offsetAt(document.source, position));\n if (!word) return undefined;\n for (const candidate of [document, ...this.#documents.values()]) {\n const symbol = candidate.symbols.find((item) => item.name === word.value);\n if (symbol) return { uri: candidate.uri, range: symbol.selectionRange };\n }\n return undefined;\n }\n\n references(uri: string, position: LanguagePosition, includeDeclaration = true): Location[] {\n const document = this.#require(uri);\n const word = wordAt(document.source, offsetAt(document.source, position));\n if (!word) return [];\n const locations: Location[] = [];\n for (const candidate of this.#documents.values()) {\n const declaration = candidate.symbols.find(\n (item) => item.name === word.value,\n )?.selectionRange;\n locations.push(\n ...(candidate.references.get(word.value) ?? [])\n .filter((range) => includeDeclaration || !sameRange(range, declaration))\n .map((range) => ({ uri: candidate.uri, range })),\n );\n }\n return locations;\n }\n\n rename(uri: string, position: LanguagePosition, newName: string): TextEdit[] {\n return this.renameWorkspace(uri, position, newName)\n .filter((edit) => edit.uri === uri)\n .map(({ range, newText }) => ({ range, newText }));\n }\n\n renameWorkspace(uri: string, position: LanguagePosition, newName: string): WorkspaceTextEdit[] {\n if (!/^[A-Za-z_][\\w-]*$/u.test(newName))\n throw new Error(`Invalid KDiagram identifier: ${newName}`);\n const document = this.#require(uri);\n const word = wordAt(document.source, offsetAt(document.source, position));\n if (\n !word ||\n ![...this.#documents.values()].some((candidate) =>\n candidate.symbols.some((item) => item.name === word.value),\n )\n )\n return [];\n return [...this.#documents.values()].flatMap((candidate) =>\n (candidate.references.get(word.value) ?? []).map((range) => ({\n uri: candidate.uri,\n range,\n newText: newName,\n })),\n );\n }\n\n documentSymbols(uri: string): DocumentSymbol[] {\n const document = this.#require(uri);\n return document.symbols.map(({ name, kind, range }) => ({ name, kind, range }));\n }\n\n foldingRanges(uri: string): FoldingRange[] {\n const source = this.#require(uri).source;\n const stack: Array<{ line: number }> = [];\n const ranges: FoldingRange[] = [];\n let line = 1;\n let quote = false;\n let comment = false;\n for (let offset = 0; offset < source.length; offset++) {\n const char = source[offset]!;\n const next = source[offset + 1];\n if (char === \"\\n\") {\n line++;\n comment = false;\n continue;\n }\n if (!quote && !comment && char === \"/\" && next === \"/\") {\n comment = true;\n offset++;\n continue;\n }\n if (comment) continue;\n if (char === '\"' && source[offset - 1] !== \"\\\\\") quote = !quote;\n if (quote) continue;\n if (char === \"{\") stack.push({ line });\n if (char === \"}\") {\n const start = stack.pop();\n if (start && line > start.line) ranges.push({ startLine: start.line, endLine: line });\n }\n }\n return ranges;\n }\n\n semanticTokens(uri: string): SemanticToken[] {\n const source = this.#require(uri).source;\n const tokens: SemanticToken[] = [];\n const pattern =\n /\"(?:[^\"\\\\]|\\\\.)*\"|(?:-->|->|=>|~>|\\.>|-x>|<->|<-)|\\b\\d+(?:\\.\\d+)?\\b|[A-Za-z_][\\w-]*/gu;\n for (const match of source.matchAll(pattern)) {\n const value = match[0];\n const offset = match.index;\n const position = positionAt(source, offset);\n let type: SemanticToken[\"type\"] = \"variable\";\n if (value.startsWith('\"')) type = \"string\";\n else if (/^\\d/u.test(value)) type = \"number\";\n else if ((builtinCatalog.edgeOperators as readonly string[]).includes(value))\n type = \"operator\";\n else if ((LANGUAGE_KEYWORDS as readonly string[]).includes(value)) type = \"keyword\";\n else if (this.#kindDescription(value)) type = \"type\";\n else if (\n this.#properties().some((item) => item.name === value) &&\n /^\\s*:/u.test(source.slice(offset + value.length))\n )\n type = \"property\";\n else if (\n this.#require(uri).symbols.some((item) => item.kind === \"style\" && item.name === value)\n )\n type = \"class\";\n tokens.push({ line: position.line, column: position.column, length: value.length, type });\n }\n return tokens;\n }\n\n codeActions(uri: string): CodeAction[] {\n const document = this.#require(uri);\n const actions: CodeAction[] = [];\n const formatting = this.format(uri);\n if (formatting.length)\n actions.push({ title: \"Format KDiagram document\", kind: \"source.format\", edits: formatting });\n for (const diagnostic of document.diagnostics) {\n const replacement = /Did you mean (?:“|\")([^”\"]+)(?:”|\")\\?/u.exec(diagnostic.hint ?? \"\")?.[1];\n if (!replacement) continue;\n actions.push({\n title: `Replace with ‘${replacement}’`,\n kind: \"quickfix\",\n edits: [{ range: diagnostic.range, newText: replacement }],\n diagnosticCode: diagnostic.code,\n });\n }\n for (const match of document.source.matchAll(/\\broomy\\b/gu)) {\n actions.push({\n title: \"Migrate deprecated density ‘roomy’ to ‘spacious’\",\n kind: \"source.migrate\",\n edits: [\n {\n range: rangeFromOffsets(document.source, match.index, match.index + match[0].length),\n newText: \"spacious\",\n },\n ],\n });\n }\n return actions;\n }\n\n registerExtension(extension: LanguageExtension): () => void {\n const protocolVersion: number = extension.protocolVersion;\n if (protocolVersion !== 1)\n throw new Error(`Unsupported language extension protocol: ${protocolVersion}`);\n if (!extension.id.trim()) throw new Error(\"Language extension id is required\");\n this.#extensions.set(extension.id, extension);\n return () => {\n this.#extensions.delete(extension.id);\n };\n }\n\n #properties(): SemanticProperty[] {\n return uniqueProperties([\n ...builtinCatalog.properties,\n ...[...this.#extensions.values()].flatMap((extension) => extension.properties ?? []),\n ]);\n }\n\n #kindDescription(kind: string): string | undefined {\n const builtin = builtinCatalog.kindDetails[kind];\n if (builtin) return `${builtin.subtitle} · ${builtin.category} · ${builtin.shape}`;\n for (const extension of this.#extensions.values()) {\n const custom = extension.kinds?.[kind];\n if (custom) return custom.description;\n }\n return undefined;\n }\n\n #require(uri: string): DocumentRecord {\n const document = this.#documents.get(uri);\n if (!document) throw new Error(`Unknown KDiagram document: ${uri}`);\n return document;\n }\n}\n\nfunction snapshot(document: DocumentRecord): LanguageSnapshot {\n return {\n uri: document.uri,\n source: document.source,\n version: document.version,\n diagnostics: [...document.diagnostics],\n };\n}\n\nfunction dedupeDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] {\n const seen = new Set<string>();\n return diagnostics.filter((item) => {\n const key = `${item.code}:${item.message}:${item.range.start.offset}:${item.range.end.offset}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction collectSymbols(source: string, ast: KDiagramAst): SymbolRecord[] {\n const symbols: SymbolRecord[] = [];\n for (const top of ast.body) {\n const name =\n top.name ??\n (top.type === \"Sequence\" ? \"Sequence\" : top.diagramKind === \"state\" ? \"State\" : \"Diagram\");\n symbols.push({\n name,\n kind: \"diagram\",\n range: top.range,\n selectionRange: findTextRange(source, top.range, top.name ?? top.type.toLowerCase()),\n });\n visitStatements(source, top.statements, symbols);\n }\n return symbols;\n}\n\nfunction visitStatements(\n source: string,\n statements: readonly (StatementAst | SequenceStatementAst)[],\n symbols: SymbolRecord[],\n): void {\n for (const statement of statements) {\n switch (statement.type) {\n case \"Node\":\n symbols.push({\n name: statement.id,\n kind: \"node\",\n range: statement.range,\n selectionRange: findTextRange(source, statement.range, statement.id),\n detail: statement.kind,\n });\n break;\n case \"Group\":\n if (statement.id)\n symbols.push({\n name: statement.id,\n kind: \"group\",\n range: statement.range,\n selectionRange: findTextRange(source, statement.range, statement.id),\n detail: statement.groupKind,\n });\n visitStatements(source, statement.statements, symbols);\n break;\n case \"Style\":\n symbols.push({\n name: statement.name,\n kind: \"style\",\n range: statement.range,\n selectionRange: findTextRange(source, statement.range, statement.name),\n detail: statement.target,\n });\n break;\n case \"AnimationBlock\":\n symbols.push({\n name: statement.name,\n kind: \"animation\",\n range: statement.range,\n selectionRange: findTextRange(source, statement.range, statement.name),\n });\n break;\n case \"SequenceCreate\":\n symbols.push({\n name: statement.node.id,\n kind: \"node\",\n range: statement.range,\n selectionRange: findTextRange(source, statement.range, statement.node.id),\n detail: statement.node.kind,\n });\n break;\n case \"SequenceFragment\":\n for (const operand of statement.operands) {\n visitStatements(source, operand.statements, symbols);\n }\n break;\n }\n }\n}\n\nfunction collectReferences(source: string): Map<string, SourceRange[]> {\n const references = new Map<string, SourceRange[]>();\n for (const match of semanticIdentifierMatches(source)) {\n const ranges = references.get(match[0]) ?? [];\n const index = match.index!;\n ranges.push(rangeFromOffsets(source, index, index + match[0].length));\n references.set(match[0], ranges);\n }\n return references;\n}\n\nfunction semanticIdentifierMatches(source: string): RegExpMatchArray[] {\n const masked = source.split(\"\");\n let quote = false;\n let lineComment = false;\n let blockComment = false;\n for (let index = 0; index < source.length; index++) {\n const char = source[index]!;\n const next = source[index + 1];\n if (lineComment) {\n if (char === \"\\n\") lineComment = false;\n else masked[index] = \" \";\n continue;\n }\n if (blockComment) {\n masked[index] = char === \"\\n\" ? \"\\n\" : \" \";\n if (char === \"*\" && next === \"/\") {\n masked[index + 1] = \" \";\n blockComment = false;\n index++;\n }\n continue;\n }\n if (!quote && char === \"/\" && next === \"/\") {\n masked[index] = masked[index + 1] = \" \";\n lineComment = true;\n index++;\n continue;\n }\n if (!quote && char === \"/\" && next === \"*\") {\n masked[index] = masked[index + 1] = \" \";\n blockComment = true;\n index++;\n continue;\n }\n if (char === '\"' && source[index - 1] !== \"\\\\\") {\n quote = !quote;\n masked[index] = \" \";\n continue;\n }\n if (quote) masked[index] = char === \"\\n\" ? \"\\n\" : \" \";\n }\n return [...masked.join(\"\").matchAll(IDENTIFIER)];\n}\n\nfunction tableColumnCompletions(document: DocumentRecord): CompletionItem[] {\n const names = new Set<string>();\n for (const match of document.source.matchAll(/\\b(?:pk|fk|uk)?\\s*([A-Za-z_][\\w-]*)\\s*:/gu))\n names.add(match[1]!);\n return [...names].sort().map((label) => ({ label, kind: \"reference\", detail: \"Table column\" }));\n}\n\nfunction wordAt(source: string, offset: number): { value: string; range: SourceRange } | undefined {\n let start = Math.min(offset, source.length);\n while (start > 0 && /[\\w-]/u.test(source[start - 1]!)) start--;\n const match = WORD_AT.exec(source.slice(start));\n if (!match || match.index !== 0) return undefined;\n return { value: match[0], range: rangeFromOffsets(source, start, start + match[0].length) };\n}\n\nfunction findTextRange(source: string, within: SourceRange, text: string): SourceRange {\n const offset = source.indexOf(text, within.start.offset);\n if (offset < 0 || offset >= within.end.offset) return within;\n return rangeFromOffsets(source, offset, offset + text.length);\n}\n\nexport function positionAt(source: string, offset: number): Required<LanguagePosition> {\n const bounded = Math.max(0, Math.min(offset, source.length));\n const prefix = source.slice(0, bounded);\n const line = prefix.split(\"\\n\").length;\n const lastNewline = prefix.lastIndexOf(\"\\n\");\n return { line, column: bounded - lastNewline, offset: bounded };\n}\n\nexport function offsetAt(source: string, position: LanguagePosition): number {\n if (position.offset != null) return Math.max(0, Math.min(position.offset, source.length));\n const lines = source.split(\"\\n\");\n let offset = 0;\n for (let line = 1; line < position.line; line++) offset += (lines[line - 1]?.length ?? 0) + 1;\n return Math.min(source.length, offset + Math.max(0, position.column - 1));\n}\n\nfunction rangeFromOffsets(source: string, start: number, end: number): SourceRange {\n return { start: positionAt(source, start), end: positionAt(source, end) };\n}\n\nfunction fullRange(source: string): SourceRange {\n return rangeFromOffsets(source, 0, source.length);\n}\n\nfunction linePrefix(source: string, offset: number): string {\n return source.slice(source.lastIndexOf(\"\\n\", offset - 1) + 1, offset);\n}\n\nfunction sameRange(left: SourceRange, right: SourceRange | undefined): boolean {\n return Boolean(\n right && left.start.offset === right.start.offset && left.end.offset === right.end.offset,\n );\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)].sort();\n}\n\nfunction uniqueProperties(values: readonly SemanticProperty[]): SemanticProperty[] {\n return [...new Map(values.map((item) => [item.name, item])).values()].sort((left, right) =>\n left.name.localeCompare(right.name),\n );\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kekonic/diagrams-language-service",
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
|
+
"description": "Browser-compatible language intelligence for KDiagram editors and LSP hosts.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"diagram",
|
|
7
|
+
"language-server",
|
|
8
|
+
"lsp",
|
|
9
|
+
"monaco"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/kekonic/diagrams#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/kekonic/diagrams/issues"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/kekonic/diagrams.git",
|
|
19
|
+
"directory": "packages/diagrams-language-service"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"import": "./dist/index.mjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@kekonic/diagrams-core": "1.0.0-rc.4",
|
|
36
|
+
"@kekonic/diagrams-icons": "1.0.0-rc.4",
|
|
37
|
+
"@kekonic/diagrams-theme": "1.0.0-rc.4"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"typescript": "^5",
|
|
41
|
+
"vitest": "^4"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=22.18.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "vp pack",
|
|
48
|
+
"test": "vp test"
|
|
49
|
+
}
|
|
50
|
+
}
|