@bpmnkit/core 0.0.8
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/README.md +185 -0
- package/dist/bpmn/auto-layout.d.ts +10 -0
- package/dist/bpmn/auto-layout.js +203 -0
- package/dist/bpmn/bpmn-builder.d.ts +381 -0
- package/dist/bpmn/bpmn-builder.js +1223 -0
- package/dist/bpmn/bpmn-model.d.ts +403 -0
- package/dist/bpmn/bpmn-model.js +2 -0
- package/dist/bpmn/bpmn-parser.d.ts +4 -0
- package/dist/bpmn/bpmn-parser.js +642 -0
- package/dist/bpmn/bpmn-serializer.d.ts +4 -0
- package/dist/bpmn/bpmn-serializer.js +515 -0
- package/dist/bpmn/compact.d.ts +91 -0
- package/dist/bpmn/compact.js +349 -0
- package/dist/bpmn/di-color.d.ts +9 -0
- package/dist/bpmn/di-color.js +32 -0
- package/dist/bpmn/index.d.ts +105 -0
- package/dist/bpmn/index.js +176 -0
- package/dist/bpmn/optimize/feel.d.ts +4 -0
- package/dist/bpmn/optimize/feel.js +186 -0
- package/dist/bpmn/optimize/flow.d.ts +4 -0
- package/dist/bpmn/optimize/flow.js +323 -0
- package/dist/bpmn/optimize/index.d.ts +5 -0
- package/dist/bpmn/optimize/index.js +51 -0
- package/dist/bpmn/optimize/naming.d.ts +8 -0
- package/dist/bpmn/optimize/naming.js +145 -0
- package/dist/bpmn/optimize/tasks.d.ts +4 -0
- package/dist/bpmn/optimize/tasks.js +273 -0
- package/dist/bpmn/optimize/types.d.ts +44 -0
- package/dist/bpmn/optimize/types.js +2 -0
- package/dist/bpmn/optimize/utils.d.ts +23 -0
- package/dist/bpmn/optimize/utils.js +129 -0
- package/dist/bpmn/rest-connector.d.ts +48 -0
- package/dist/bpmn/rest-connector.js +69 -0
- package/dist/bpmn/svg.d.ts +35 -0
- package/dist/bpmn/svg.js +557 -0
- package/dist/bpmn/type-guards.d.ts +136 -0
- package/dist/bpmn/type-guards.js +211 -0
- package/dist/bpmn/utils.d.ts +88 -0
- package/dist/bpmn/utils.js +207 -0
- package/dist/bpmn/zeebe-extensions.d.ts +72 -0
- package/dist/bpmn/zeebe-extensions.js +96 -0
- package/dist/dmn/compact.d.ts +44 -0
- package/dist/dmn/compact.js +125 -0
- package/dist/dmn/dmn-builder.d.ts +59 -0
- package/dist/dmn/dmn-builder.js +144 -0
- package/dist/dmn/dmn-layout.d.ts +57 -0
- package/dist/dmn/dmn-layout.js +256 -0
- package/dist/dmn/dmn-model.d.ts +158 -0
- package/dist/dmn/dmn-model.js +2 -0
- package/dist/dmn/dmn-parser.d.ts +4 -0
- package/dist/dmn/dmn-parser.js +275 -0
- package/dist/dmn/dmn-serializer.d.ts +4 -0
- package/dist/dmn/dmn-serializer.js +296 -0
- package/dist/dmn/index.d.ts +28 -0
- package/dist/dmn/index.js +51 -0
- package/dist/errors.d.ts +77 -0
- package/dist/errors.js +66 -0
- package/dist/form/compact.d.ts +20 -0
- package/dist/form/compact.js +146 -0
- package/dist/form/form-builder.d.ts +111 -0
- package/dist/form/form-builder.js +347 -0
- package/dist/form/form-model.d.ts +221 -0
- package/dist/form/form-model.js +2 -0
- package/dist/form/form-parser.d.ts +4 -0
- package/dist/form/form-parser.js +514 -0
- package/dist/form/form-serializer.d.ts +4 -0
- package/dist/form/form-serializer.js +240 -0
- package/dist/form/index.d.ts +27 -0
- package/dist/form/index.js +43 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +19 -0
- package/dist/layout/bench.d.ts +86 -0
- package/dist/layout/bench.js +225 -0
- package/dist/layout/coordinates.d.ts +62 -0
- package/dist/layout/coordinates.js +868 -0
- package/dist/layout/crossing.d.ts +8 -0
- package/dist/layout/crossing.js +60 -0
- package/dist/layout/graph.d.ts +28 -0
- package/dist/layout/graph.js +126 -0
- package/dist/layout/index.d.ts +7 -0
- package/dist/layout/index.js +5 -0
- package/dist/layout/layers.d.ts +13 -0
- package/dist/layout/layers.js +49 -0
- package/dist/layout/layout-engine.d.ts +21 -0
- package/dist/layout/layout-engine.js +191 -0
- package/dist/layout/overlap.d.ts +10 -0
- package/dist/layout/overlap.js +70 -0
- package/dist/layout/routing.d.ts +26 -0
- package/dist/layout/routing.js +439 -0
- package/dist/layout/subprocess.d.ts +14 -0
- package/dist/layout/subprocess.js +77 -0
- package/dist/layout/types.d.ts +72 -0
- package/dist/layout/types.js +37 -0
- package/dist/types/id-generator.d.ts +8 -0
- package/dist/types/id-generator.js +31 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +2 -0
- package/dist/types/xml-element.d.ts +12 -0
- package/dist/types/xml-element.js +2 -0
- package/dist/xml/index.d.ts +2 -0
- package/dist/xml/index.js +2 -0
- package/dist/xml/xml-parser.d.ts +13 -0
- package/dist/xml/xml-parser.js +271 -0
- package/package.json +38 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Represents an XML element with preserved namespace prefixes for roundtrip fidelity. */
|
|
2
|
+
export interface XmlElement {
|
|
3
|
+
/** Qualified element name, e.g. "custom:myExtension" */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Attribute keys retain namespace prefix (e.g. "xsi:type"), values are strings */
|
|
6
|
+
attributes: Record<string, string>;
|
|
7
|
+
/** Nested child elements */
|
|
8
|
+
children: XmlElement[];
|
|
9
|
+
/** Text content, if any */
|
|
10
|
+
text?: string;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=xml-element.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { XmlElement } from "../types/xml-element.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse an XML string into an XmlElement tree.
|
|
4
|
+
* Returns the root element with all namespace prefixes preserved.
|
|
5
|
+
* @throws Error if the XML has no root element.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseXml(xml: string): XmlElement;
|
|
8
|
+
/**
|
|
9
|
+
* Serialize an XmlElement tree to an XML string.
|
|
10
|
+
* Produces a well-formed XML document with declaration.
|
|
11
|
+
*/
|
|
12
|
+
export declare function serializeXml(element: XmlElement): string;
|
|
13
|
+
//# sourceMappingURL=xml-parser.d.ts.map
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Parser
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* Parse an XML string into an XmlElement tree.
|
|
6
|
+
* Returns the root element with all namespace prefixes preserved.
|
|
7
|
+
* @throws Error if the XML has no root element.
|
|
8
|
+
*/
|
|
9
|
+
export function parseXml(xml) {
|
|
10
|
+
const p = new XmlReader(xml);
|
|
11
|
+
const root = p.parseDocument();
|
|
12
|
+
if (!root)
|
|
13
|
+
throw new Error("Failed to parse XML: no root element found");
|
|
14
|
+
return root;
|
|
15
|
+
}
|
|
16
|
+
class XmlReader {
|
|
17
|
+
s;
|
|
18
|
+
i = 0;
|
|
19
|
+
constructor(source) {
|
|
20
|
+
this.s = source;
|
|
21
|
+
}
|
|
22
|
+
parseDocument() {
|
|
23
|
+
let root;
|
|
24
|
+
while (this.i < this.s.length) {
|
|
25
|
+
this.skipWhitespace();
|
|
26
|
+
if (this.i >= this.s.length)
|
|
27
|
+
break;
|
|
28
|
+
if (this.s[this.i] !== "<") {
|
|
29
|
+
// text outside root — skip
|
|
30
|
+
this.i++;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (this.startsWith("<?")) {
|
|
34
|
+
this.skipPi();
|
|
35
|
+
}
|
|
36
|
+
else if (this.startsWith("<!--")) {
|
|
37
|
+
this.skipComment();
|
|
38
|
+
}
|
|
39
|
+
else if (this.startsWith("<!")) {
|
|
40
|
+
this.skipBang();
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
root = this.parseElement();
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return root;
|
|
48
|
+
}
|
|
49
|
+
parseElement() {
|
|
50
|
+
this.expect("<");
|
|
51
|
+
const name = this.readName();
|
|
52
|
+
const attributes = {};
|
|
53
|
+
this.readAttributes(attributes);
|
|
54
|
+
this.skipWhitespace();
|
|
55
|
+
if (this.s[this.i] === "/" && this.s[this.i + 1] === ">") {
|
|
56
|
+
// self-closing
|
|
57
|
+
this.i += 2;
|
|
58
|
+
return { name, attributes, children: [] };
|
|
59
|
+
}
|
|
60
|
+
this.expect(">");
|
|
61
|
+
const children = [];
|
|
62
|
+
let text;
|
|
63
|
+
while (this.i < this.s.length) {
|
|
64
|
+
if (this.startsWith("</"))
|
|
65
|
+
break;
|
|
66
|
+
if (this.s[this.i] === "<") {
|
|
67
|
+
if (this.startsWith("<!--")) {
|
|
68
|
+
this.skipComment();
|
|
69
|
+
}
|
|
70
|
+
else if (this.startsWith("<![CDATA[")) {
|
|
71
|
+
const cd = this.readCData();
|
|
72
|
+
text = text === undefined ? cd : text + cd;
|
|
73
|
+
}
|
|
74
|
+
else if (this.startsWith("<?")) {
|
|
75
|
+
this.skipPi();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
children.push(this.parseElement());
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const t = this.readText();
|
|
83
|
+
if (t.length > 0) {
|
|
84
|
+
text = text === undefined ? t : text + t;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// closing tag </name>
|
|
89
|
+
this.expect("</");
|
|
90
|
+
const closing = this.readName();
|
|
91
|
+
if (closing !== name) {
|
|
92
|
+
throw new Error(`Mismatched closing tag: expected </${name}>, got </${closing}>`);
|
|
93
|
+
}
|
|
94
|
+
this.skipWhitespace();
|
|
95
|
+
this.expect(">");
|
|
96
|
+
const el = { name, attributes, children };
|
|
97
|
+
if (text !== undefined)
|
|
98
|
+
el.text = text;
|
|
99
|
+
return el;
|
|
100
|
+
}
|
|
101
|
+
readAttributes(attrs) {
|
|
102
|
+
while (this.i < this.s.length) {
|
|
103
|
+
this.skipWhitespace();
|
|
104
|
+
const ch = this.s[this.i];
|
|
105
|
+
if (ch === ">" || ch === "/")
|
|
106
|
+
return;
|
|
107
|
+
const key = this.readName();
|
|
108
|
+
this.skipWhitespace();
|
|
109
|
+
this.expect("=");
|
|
110
|
+
this.skipWhitespace();
|
|
111
|
+
const value = this.readAttrValue();
|
|
112
|
+
attrs[key] = value;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
readAttrValue() {
|
|
116
|
+
const quote = this.s[this.i];
|
|
117
|
+
if (quote !== '"' && quote !== "'") {
|
|
118
|
+
throw new Error(`Expected quote at position ${this.i}`);
|
|
119
|
+
}
|
|
120
|
+
this.i++;
|
|
121
|
+
const start = this.i;
|
|
122
|
+
while (this.i < this.s.length && this.s[this.i] !== quote) {
|
|
123
|
+
this.i++;
|
|
124
|
+
}
|
|
125
|
+
const value = this.s.substring(start, this.i);
|
|
126
|
+
this.i++; // skip closing quote
|
|
127
|
+
return decodeXmlEntities(value);
|
|
128
|
+
}
|
|
129
|
+
readText() {
|
|
130
|
+
const start = this.i;
|
|
131
|
+
while (this.i < this.s.length && this.s[this.i] !== "<") {
|
|
132
|
+
this.i++;
|
|
133
|
+
}
|
|
134
|
+
return decodeXmlEntities(this.s.substring(start, this.i));
|
|
135
|
+
}
|
|
136
|
+
readName() {
|
|
137
|
+
const start = this.i;
|
|
138
|
+
while (this.i < this.s.length) {
|
|
139
|
+
const c = this.s[this.i];
|
|
140
|
+
if (c === " " ||
|
|
141
|
+
c === "\t" ||
|
|
142
|
+
c === "\n" ||
|
|
143
|
+
c === "\r" ||
|
|
144
|
+
c === ">" ||
|
|
145
|
+
c === "/" ||
|
|
146
|
+
c === "=")
|
|
147
|
+
break;
|
|
148
|
+
this.i++;
|
|
149
|
+
}
|
|
150
|
+
return this.s.substring(start, this.i);
|
|
151
|
+
}
|
|
152
|
+
readCData() {
|
|
153
|
+
this.i += 9; // skip <![CDATA[
|
|
154
|
+
const end = this.s.indexOf("]]>", this.i);
|
|
155
|
+
if (end === -1)
|
|
156
|
+
throw new Error("Unterminated CDATA section");
|
|
157
|
+
const text = this.s.substring(this.i, end);
|
|
158
|
+
this.i = end + 3;
|
|
159
|
+
return text;
|
|
160
|
+
}
|
|
161
|
+
skipPi() {
|
|
162
|
+
this.i += 2; // skip <?
|
|
163
|
+
const end = this.s.indexOf("?>", this.i);
|
|
164
|
+
this.i = end === -1 ? this.s.length : end + 2;
|
|
165
|
+
}
|
|
166
|
+
skipComment() {
|
|
167
|
+
this.i += 4; // skip <!--
|
|
168
|
+
const end = this.s.indexOf("-->", this.i);
|
|
169
|
+
this.i = end === -1 ? this.s.length : end + 3;
|
|
170
|
+
}
|
|
171
|
+
skipBang() {
|
|
172
|
+
// Skip <!DOCTYPE ...> and similar
|
|
173
|
+
this.i += 2;
|
|
174
|
+
let depth = 1;
|
|
175
|
+
while (this.i < this.s.length && depth > 0) {
|
|
176
|
+
if (this.s[this.i] === "<")
|
|
177
|
+
depth++;
|
|
178
|
+
else if (this.s[this.i] === ">")
|
|
179
|
+
depth--;
|
|
180
|
+
this.i++;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
skipWhitespace() {
|
|
184
|
+
while (this.i < this.s.length) {
|
|
185
|
+
const c = this.s[this.i];
|
|
186
|
+
if (c !== " " && c !== "\t" && c !== "\n" && c !== "\r")
|
|
187
|
+
break;
|
|
188
|
+
this.i++;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
expect(str) {
|
|
192
|
+
if (!this.s.startsWith(str, this.i)) {
|
|
193
|
+
throw new Error(`Expected "${str}" at position ${this.i}`);
|
|
194
|
+
}
|
|
195
|
+
this.i += str.length;
|
|
196
|
+
}
|
|
197
|
+
startsWith(prefix) {
|
|
198
|
+
return this.s.startsWith(prefix, this.i);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
// Entity helpers
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
/** Decode XML predefined and numeric character entities in a string. */
|
|
205
|
+
function decodeXmlEntities(s) {
|
|
206
|
+
if (!s.includes("&"))
|
|
207
|
+
return s;
|
|
208
|
+
return s.replace(/&(?:amp|lt|gt|quot|apos|#x[0-9a-fA-F]+|#[0-9]+);/g, (m) => {
|
|
209
|
+
if (m === "&")
|
|
210
|
+
return "&";
|
|
211
|
+
if (m === "<")
|
|
212
|
+
return "<";
|
|
213
|
+
if (m === ">")
|
|
214
|
+
return ">";
|
|
215
|
+
if (m === """)
|
|
216
|
+
return '"';
|
|
217
|
+
if (m === "'")
|
|
218
|
+
return "'";
|
|
219
|
+
if (m.startsWith("&#x"))
|
|
220
|
+
return String.fromCodePoint(Number.parseInt(m.slice(3, -1), 16));
|
|
221
|
+
return String.fromCodePoint(Number.parseInt(m.slice(2, -1), 10));
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
// Serializer
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
/**
|
|
228
|
+
* Serialize an XmlElement tree to an XML string.
|
|
229
|
+
* Produces a well-formed XML document with declaration.
|
|
230
|
+
*/
|
|
231
|
+
export function serializeXml(element) {
|
|
232
|
+
const parts = ['<?xml version="1.0" encoding="UTF-8"?>\n'];
|
|
233
|
+
writeElement(parts, element, 0);
|
|
234
|
+
parts.push("\n");
|
|
235
|
+
return parts.join("");
|
|
236
|
+
}
|
|
237
|
+
function writeElement(parts, el, depth) {
|
|
238
|
+
const indent = " ".repeat(depth);
|
|
239
|
+
parts.push(indent, "<", el.name);
|
|
240
|
+
for (const [key, value] of Object.entries(el.attributes)) {
|
|
241
|
+
parts.push(" ", key, '="', escapeAttr(value), '"');
|
|
242
|
+
}
|
|
243
|
+
const hasChildren = el.children.length > 0;
|
|
244
|
+
const hasText = el.text !== undefined;
|
|
245
|
+
if (!hasChildren && !hasText) {
|
|
246
|
+
parts.push("/>\n");
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
parts.push(">");
|
|
250
|
+
if (hasText) {
|
|
251
|
+
parts.push(escapeText(el.text));
|
|
252
|
+
}
|
|
253
|
+
if (hasChildren) {
|
|
254
|
+
parts.push("\n");
|
|
255
|
+
for (const child of el.children) {
|
|
256
|
+
writeElement(parts, child, depth + 1);
|
|
257
|
+
}
|
|
258
|
+
parts.push(indent);
|
|
259
|
+
}
|
|
260
|
+
parts.push("</", el.name, ">\n");
|
|
261
|
+
}
|
|
262
|
+
function escapeAttr(value) {
|
|
263
|
+
let s = value.replaceAll("&", "&").replaceAll("<", "<").replaceAll('"', """);
|
|
264
|
+
// Re-encode whitespace that XML parsers would normalize in attribute values
|
|
265
|
+
s = s.replaceAll("\n", " ").replaceAll("\r", " ").replaceAll("\t", "	");
|
|
266
|
+
return s;
|
|
267
|
+
}
|
|
268
|
+
function escapeText(value) {
|
|
269
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=xml-parser.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bpmnkit/core",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": ["dist/**/*.js", "dist/**/*.d.ts"],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"check": "biome check .",
|
|
18
|
+
"test": "vitest run"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {},
|
|
21
|
+
"description": "TypeScript-first BPMN 2.0 SDK — parse, build, layout, and optimize diagrams",
|
|
22
|
+
"keywords": [
|
|
23
|
+
"bpmn",
|
|
24
|
+
"bpmn2",
|
|
25
|
+
"camunda",
|
|
26
|
+
"zeebe",
|
|
27
|
+
"workflow",
|
|
28
|
+
"process",
|
|
29
|
+
"dmn",
|
|
30
|
+
"typescript",
|
|
31
|
+
"sdk"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/bpmnkit/monorepo"
|
|
37
|
+
}
|
|
38
|
+
}
|