@miy2/xml-api 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dom.d.ts ADDED
@@ -0,0 +1,172 @@
1
+ import { ModelElement, type ModelNode } from "./model/xml-api-model";
2
+ /**
3
+ * Observer interface to listen for changes in the DOM-like structure.
4
+ * This is crucial for synchronizing the visual representation or application model
5
+ * back to the source code via the XMLAPI.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const doc = new Document();
10
+ * doc.setObserver({
11
+ * onAttributeChange: (element, name, value) => {
12
+ * console.log(`Attribute ${name} changed to ${value}`);
13
+ * // Sync with XMLAPI...
14
+ * },
15
+ * // ...
16
+ * });
17
+ * ```
18
+ */
19
+ export interface DOMObserver {
20
+ /**
21
+ * Called when an attribute is added, changed, or removed.
22
+ * @param element The target element.
23
+ * @param name Attribute name.
24
+ * @param value New value, or null if removed.
25
+ */
26
+ onAttributeChange(element: Element, name: string, value: string | null): void;
27
+ /**
28
+ * Called when the text content of a node changes.
29
+ * @param node The target CharacterData node (Text, Comment, CDATA).
30
+ * @param text The new text content.
31
+ */
32
+ onTextChange(node: CharacterData, text: string): void;
33
+ /**
34
+ * Called when the text content of an Element changes (replacing all children).
35
+ * @param element The target Element.
36
+ * @param text The new text content.
37
+ */
38
+ onElementTextChange(element: Element, text: string): void;
39
+ /**
40
+ * Called when a child node is added.
41
+ * @param parent The parent node.
42
+ * @param child The added child node.
43
+ * @param index The index at which the child was added.
44
+ */
45
+ onChildAdded(parent: Node, child: Node, index: number): void;
46
+ /**
47
+ * Called when a child node is removed.
48
+ * @param parent The parent node.
49
+ * @param child The removed child node.
50
+ * @param index The index from which the child was removed.
51
+ */
52
+ onChildRemoved(parent: Node, child: Node, index: number): void;
53
+ }
54
+ /**
55
+ * Base class for all DOM nodes.
56
+ * Implements a subset of the W3C Node interface to allow applications
57
+ * to interact with the XML model using familiar methods.
58
+ */
59
+ export declare abstract class Node {
60
+ protected model: ModelNode;
61
+ ownerDocument: Document | null;
62
+ readonly ELEMENT_NODE = 1;
63
+ readonly TEXT_NODE = 3;
64
+ readonly CDATA_SECTION_NODE = 4;
65
+ readonly COMMENT_NODE = 8;
66
+ readonly DOCUMENT_NODE = 9;
67
+ constructor(model: ModelNode, ownerDocument: Document | null);
68
+ abstract get nodeType(): number;
69
+ abstract get nodeName(): string;
70
+ /**
71
+ * Returns the parent of this node.
72
+ */
73
+ get parentNode(): Node | null;
74
+ /**
75
+ * Returns a NodeList containing all children of this node.
76
+ */
77
+ get childNodes(): NodeList;
78
+ get firstChild(): Node | null;
79
+ get lastChild(): Node | null;
80
+ get nextSibling(): Node | null;
81
+ get previousSibling(): Node | null;
82
+ get textContent(): string | null;
83
+ set textContent(value: string | null);
84
+ /**
85
+ * Adds a node to the end of the list of children of a specified parent node.
86
+ * @param newChild The node to append.
87
+ */
88
+ appendChild<T extends Node>(newChild: T): T;
89
+ /**
90
+ * Inserts a node before a reference node as a child of this node.
91
+ * @param newChild The node to insert.
92
+ * @param refChild The reference node (must be a child of this node).
93
+ */
94
+ insertBefore<T extends Node>(newChild: T, refChild: Node | null): T;
95
+ /**
96
+ * Removes a child node from the DOM and returns the removed node.
97
+ * @param child The child node to remove.
98
+ */
99
+ removeChild<T extends Node>(child: T): T;
100
+ getModel(): ModelNode;
101
+ }
102
+ export declare class NodeList extends Array<Node> {
103
+ constructor(items: Node[]);
104
+ item(index: number): Node | null;
105
+ }
106
+ /**
107
+ * Base class for Text, Comment, and CDATASection nodes.
108
+ */
109
+ export declare abstract class CharacterData extends Node {
110
+ get data(): string;
111
+ set data(value: string);
112
+ get length(): number;
113
+ }
114
+ export declare class Text extends CharacterData {
115
+ get nodeType(): number;
116
+ get nodeName(): string;
117
+ }
118
+ export declare class Comment extends CharacterData {
119
+ get nodeType(): number;
120
+ get nodeName(): string;
121
+ }
122
+ export declare class CDATASection extends CharacterData {
123
+ get nodeType(): number;
124
+ get nodeName(): string;
125
+ }
126
+ /**
127
+ * Represents an element in the XML document.
128
+ */
129
+ export declare class Element extends Node {
130
+ protected model: ModelElement;
131
+ constructor(model: ModelElement, ownerDocument: Document | null);
132
+ get nodeType(): number;
133
+ get nodeName(): string;
134
+ get tagName(): string;
135
+ get prefix(): string | null;
136
+ get localName(): string;
137
+ get namespaceURI(): string | null;
138
+ getAttribute(name: string): string | null;
139
+ setAttribute(name: string, value: string): void;
140
+ removeAttribute(name: string): void;
141
+ hasAttribute(name: string): boolean;
142
+ querySelector(selector: string): Element | null;
143
+ querySelectorAll(selector: string): NodeList;
144
+ }
145
+ /**
146
+ * Represents the entire XML document.
147
+ */
148
+ export declare class Document extends Node {
149
+ private _documentElement;
150
+ private observer;
151
+ constructor();
152
+ /**
153
+ * Sets the observer to listen for DOM changes.
154
+ */
155
+ setObserver(observer: DOMObserver): void;
156
+ notifyAttributeChange(element: Element, name: string, value: string | null): void;
157
+ notifyTextChange(node: CharacterData, text: string): void;
158
+ notifyElementTextChange(element: Element, text: string): void;
159
+ notifyChildAdded(parent: Node, child: Node, index: number): void;
160
+ notifyChildRemoved(parent: Node, child: Node, index: number): void;
161
+ get nodeType(): number;
162
+ get nodeName(): string;
163
+ get documentElement(): Element | null;
164
+ set documentElement(element: Element | null);
165
+ createElement(tagName: string): Element;
166
+ createTextNode(data: string): Text;
167
+ createComment(data: string): Comment;
168
+ createCDATASection(data: string): CDATASection;
169
+ querySelector(selector: string): Element | null;
170
+ querySelectorAll(selector: string): NodeList;
171
+ }
172
+ export declare function createWrapper(model: ModelNode, doc: Document | null): Node;
package/dist/dom.js ADDED
@@ -0,0 +1,415 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Document = exports.Element = exports.CDATASection = exports.Comment = exports.Text = exports.CharacterData = exports.NodeList = exports.Node = void 0;
4
+ exports.createWrapper = createWrapper;
5
+ const xml_api_model_1 = require("./model/xml-api-model");
6
+ /**
7
+ * Base class for all DOM nodes.
8
+ * Implements a subset of the W3C Node interface to allow applications
9
+ * to interact with the XML model using familiar methods.
10
+ */
11
+ class Node {
12
+ constructor(model, ownerDocument) {
13
+ this.model = model;
14
+ this.ownerDocument = ownerDocument;
15
+ this.ELEMENT_NODE = 1;
16
+ this.TEXT_NODE = 3;
17
+ this.CDATA_SECTION_NODE = 4;
18
+ this.COMMENT_NODE = 8;
19
+ this.DOCUMENT_NODE = 9;
20
+ }
21
+ /**
22
+ * Returns the parent of this node.
23
+ */
24
+ get parentNode() {
25
+ if (!this.model.parent)
26
+ return null;
27
+ return createWrapper(this.model.parent, this.ownerDocument);
28
+ }
29
+ /**
30
+ * Returns a NodeList containing all children of this node.
31
+ */
32
+ get childNodes() {
33
+ if (this.model instanceof xml_api_model_1.ModelElement) {
34
+ return new NodeList(this.model.children.map((c) => createWrapper(c, this.ownerDocument)));
35
+ }
36
+ return new NodeList([]);
37
+ }
38
+ get firstChild() {
39
+ const nodes = this.childNodes;
40
+ return nodes.length > 0 ? nodes.item(0) : null;
41
+ }
42
+ get lastChild() {
43
+ const nodes = this.childNodes;
44
+ return nodes.length > 0 ? nodes.item(nodes.length - 1) : null;
45
+ }
46
+ get nextSibling() {
47
+ const parent = this.model.parent;
48
+ if (!parent)
49
+ return null;
50
+ const index = parent.children.indexOf(this.model);
51
+ if (index >= 0 && index < parent.children.length - 1) {
52
+ return createWrapper(parent.children[index + 1], this.ownerDocument);
53
+ }
54
+ return null;
55
+ }
56
+ get previousSibling() {
57
+ const parent = this.model.parent;
58
+ if (!parent)
59
+ return null;
60
+ const index = parent.children.indexOf(this.model);
61
+ if (index > 0) {
62
+ return createWrapper(parent.children[index - 1], this.ownerDocument);
63
+ }
64
+ return null;
65
+ }
66
+ get textContent() {
67
+ if (this.model instanceof xml_api_model_1.ModelText)
68
+ return this.model.text;
69
+ if (this.model instanceof xml_api_model_1.ModelComment)
70
+ return this.model.content;
71
+ if (this.model instanceof xml_api_model_1.ModelCDATA)
72
+ return this.model.content;
73
+ if (this.model instanceof xml_api_model_1.ModelElement) {
74
+ return this.model.children
75
+ .map((c) => createWrapper(c, this.ownerDocument).textContent)
76
+ .join("");
77
+ }
78
+ return null;
79
+ }
80
+ set textContent(value) {
81
+ var _a, _b, _c, _d;
82
+ const val = value || "";
83
+ if (this.model instanceof xml_api_model_1.ModelText) {
84
+ this.model.text = val;
85
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyTextChange(this, val);
86
+ }
87
+ else if (this.model instanceof xml_api_model_1.ModelComment) {
88
+ this.model.content = val;
89
+ (_b = this.ownerDocument) === null || _b === void 0 ? void 0 : _b.notifyTextChange(this, val);
90
+ }
91
+ else if (this.model instanceof xml_api_model_1.ModelCDATA) {
92
+ this.model.content = val;
93
+ (_c = this.ownerDocument) === null || _c === void 0 ? void 0 : _c.notifyTextChange(this, val);
94
+ }
95
+ else if (this.model instanceof xml_api_model_1.ModelElement) {
96
+ this.model.children = [];
97
+ if (val) {
98
+ const textNode = new xml_api_model_1.ModelText(val);
99
+ this.model.addChild(textNode);
100
+ }
101
+ (_d = this.ownerDocument) === null || _d === void 0 ? void 0 : _d.notifyElementTextChange(this, val);
102
+ }
103
+ }
104
+ /**
105
+ * Adds a node to the end of the list of children of a specified parent node.
106
+ * @param newChild The node to append.
107
+ */
108
+ appendChild(newChild) {
109
+ var _a;
110
+ if (this.model instanceof xml_api_model_1.ModelElement) {
111
+ this.model.addChild(newChild.getModel());
112
+ // @ts-ignore
113
+ newChild.ownerDocument = this.ownerDocument;
114
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyChildAdded(this, newChild, this.model.children.length - 1);
115
+ return newChild;
116
+ }
117
+ throw new Error("HierarchyRequestError");
118
+ }
119
+ /**
120
+ * Inserts a node before a reference node as a child of this node.
121
+ * @param newChild The node to insert.
122
+ * @param refChild The reference node (must be a child of this node).
123
+ */
124
+ insertBefore(newChild, refChild) {
125
+ var _a;
126
+ if (this.model instanceof xml_api_model_1.ModelElement) {
127
+ if (!refChild) {
128
+ return this.appendChild(newChild);
129
+ }
130
+ const refModel = refChild.getModel();
131
+ const index = this.model.children.indexOf(refModel);
132
+ if (index === -1)
133
+ throw new Error("NotFoundError");
134
+ // Update Model
135
+ this.model.children.splice(index, 0, newChild.getModel());
136
+ newChild.getModel().parent = this.model;
137
+ // @ts-ignore
138
+ newChild.ownerDocument = this.ownerDocument;
139
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyChildAdded(this, newChild, index);
140
+ return newChild;
141
+ }
142
+ throw new Error("HierarchyRequestError");
143
+ }
144
+ /**
145
+ * Removes a child node from the DOM and returns the removed node.
146
+ * @param child The child node to remove.
147
+ */
148
+ removeChild(child) {
149
+ var _a;
150
+ if (this.model instanceof xml_api_model_1.ModelElement) {
151
+ const childModel = child.getModel();
152
+ const index = this.model.children.indexOf(childModel);
153
+ if (index === -1)
154
+ throw new Error("NotFoundError");
155
+ // Update Model
156
+ this.model.children.splice(index, 1);
157
+ childModel.parent = null;
158
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyChildRemoved(this, child, index);
159
+ return child;
160
+ }
161
+ throw new Error("HierarchyRequestError");
162
+ }
163
+ // Internal access
164
+ getModel() {
165
+ return this.model;
166
+ }
167
+ }
168
+ exports.Node = Node;
169
+ class NodeList extends Array {
170
+ constructor(items) {
171
+ super(...items);
172
+ Object.setPrototypeOf(this, NodeList.prototype);
173
+ }
174
+ item(index) {
175
+ return this[index] || null;
176
+ }
177
+ }
178
+ exports.NodeList = NodeList;
179
+ /**
180
+ * Base class for Text, Comment, and CDATASection nodes.
181
+ */
182
+ class CharacterData extends Node {
183
+ get data() {
184
+ return this.textContent || "";
185
+ }
186
+ set data(value) {
187
+ this.textContent = value;
188
+ }
189
+ get length() {
190
+ return this.data.length;
191
+ }
192
+ }
193
+ exports.CharacterData = CharacterData;
194
+ class Text extends CharacterData {
195
+ get nodeType() {
196
+ return this.TEXT_NODE;
197
+ }
198
+ get nodeName() {
199
+ return "#text";
200
+ }
201
+ }
202
+ exports.Text = Text;
203
+ class Comment extends CharacterData {
204
+ get nodeType() {
205
+ return this.COMMENT_NODE;
206
+ }
207
+ get nodeName() {
208
+ return "#comment";
209
+ }
210
+ }
211
+ exports.Comment = Comment;
212
+ class CDATASection extends CharacterData {
213
+ get nodeType() {
214
+ return this.CDATA_SECTION_NODE;
215
+ }
216
+ get nodeName() {
217
+ return "#cdata-section";
218
+ }
219
+ }
220
+ exports.CDATASection = CDATASection;
221
+ /**
222
+ * Represents an element in the XML document.
223
+ */
224
+ class Element extends Node {
225
+ constructor(model, ownerDocument) {
226
+ super(model, ownerDocument);
227
+ this.model = model;
228
+ }
229
+ get nodeType() {
230
+ return this.ELEMENT_NODE;
231
+ }
232
+ get nodeName() {
233
+ return this.model.tagName;
234
+ }
235
+ get tagName() {
236
+ return this.model.tagName;
237
+ }
238
+ get prefix() {
239
+ const parts = this.model.tagName.split(":");
240
+ return parts.length > 1 ? parts[0] : null;
241
+ }
242
+ get localName() {
243
+ const parts = this.model.tagName.split(":");
244
+ return parts.length > 1 ? parts[1] : parts[0];
245
+ }
246
+ get namespaceURI() {
247
+ const prefix = this.prefix;
248
+ const xmlnsKey = prefix ? `xmlns:${prefix}` : "xmlns";
249
+ let current = this.model;
250
+ while (current) {
251
+ if (current.attributes.has(xmlnsKey)) {
252
+ return current.attributes.get(xmlnsKey) || null;
253
+ }
254
+ current = current.parent;
255
+ }
256
+ return null;
257
+ }
258
+ getAttribute(name) {
259
+ var _a;
260
+ return (_a = this.model.attributes.get(name)) !== null && _a !== void 0 ? _a : null;
261
+ }
262
+ setAttribute(name, value) {
263
+ var _a;
264
+ this.model.attributes.set(name, value);
265
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyAttributeChange(this, name, value);
266
+ }
267
+ removeAttribute(name) {
268
+ var _a;
269
+ this.model.attributes.delete(name);
270
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyAttributeChange(this, name, null);
271
+ }
272
+ hasAttribute(name) {
273
+ return this.model.attributes.has(name);
274
+ }
275
+ querySelector(selector) {
276
+ const results = [];
277
+ querySelectorAllRecursive(this, selector, results);
278
+ return results.length > 0 ? results[0] : null;
279
+ }
280
+ querySelectorAll(selector) {
281
+ const results = [];
282
+ querySelectorAllRecursive(this, selector, results);
283
+ return new NodeList(results);
284
+ }
285
+ }
286
+ exports.Element = Element;
287
+ /**
288
+ * Represents the entire XML document.
289
+ */
290
+ class Document extends Node {
291
+ constructor() {
292
+ // Document doesn't strictly have a ModelNode parent in this simplified architecture
293
+ // Or it could wrap a "root" ModelElement
294
+ // For now, we'll create a dummy root model or handle it differently
295
+ super(new xml_api_model_1.ModelElement("#document"), null);
296
+ this._documentElement = null;
297
+ this.observer = null;
298
+ this.ownerDocument = this; // Document owns itself
299
+ }
300
+ /**
301
+ * Sets the observer to listen for DOM changes.
302
+ */
303
+ setObserver(observer) {
304
+ this.observer = observer;
305
+ }
306
+ notifyAttributeChange(element, name, value) {
307
+ var _a;
308
+ (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onAttributeChange(element, name, value);
309
+ }
310
+ notifyTextChange(node, text) {
311
+ var _a;
312
+ (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onTextChange(node, text);
313
+ }
314
+ notifyElementTextChange(element, text) {
315
+ var _a;
316
+ (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onElementTextChange(element, text);
317
+ }
318
+ notifyChildAdded(parent, child, index) {
319
+ var _a;
320
+ (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onChildAdded(parent, child, index);
321
+ }
322
+ notifyChildRemoved(parent, child, index) {
323
+ var _a;
324
+ (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onChildRemoved(parent, child, index);
325
+ }
326
+ get nodeType() {
327
+ return this.DOCUMENT_NODE;
328
+ }
329
+ get nodeName() {
330
+ return "#document";
331
+ }
332
+ get documentElement() {
333
+ return this._documentElement;
334
+ }
335
+ // Not standard, but needed for initialization
336
+ set documentElement(element) {
337
+ this._documentElement = element;
338
+ if (element) {
339
+ // Ensure the element is part of the document structure
340
+ // In a real DOM, documentElement is a child of Document
341
+ // Here, we just link them logically
342
+ // @ts-ignore
343
+ element.ownerDocument = this;
344
+ }
345
+ }
346
+ createElement(tagName) {
347
+ return new Element(new xml_api_model_1.ModelElement(tagName), this);
348
+ }
349
+ createTextNode(data) {
350
+ return new Text(new xml_api_model_1.ModelText(data), this);
351
+ }
352
+ createComment(data) {
353
+ return new Comment(new xml_api_model_1.ModelComment(data), this);
354
+ }
355
+ createCDATASection(data) {
356
+ return new CDATASection(new xml_api_model_1.ModelCDATA(data), this);
357
+ }
358
+ querySelector(selector) {
359
+ if (!this.documentElement)
360
+ return null;
361
+ return this.documentElement.querySelector(selector);
362
+ }
363
+ querySelectorAll(selector) {
364
+ if (!this.documentElement)
365
+ return new NodeList([]);
366
+ return this.documentElement.querySelectorAll(selector);
367
+ }
368
+ }
369
+ exports.Document = Document;
370
+ // Helper factory
371
+ function createWrapper(model, doc) {
372
+ if (model instanceof xml_api_model_1.ModelElement)
373
+ return new Element(model, doc);
374
+ if (model instanceof xml_api_model_1.ModelText)
375
+ return new Text(model, doc);
376
+ if (model instanceof xml_api_model_1.ModelComment)
377
+ return new Comment(model, doc);
378
+ if (model instanceof xml_api_model_1.ModelCDATA)
379
+ return new CDATASection(model, doc);
380
+ throw new Error(`Unknown model type: ${model.getType()}`);
381
+ }
382
+ function matchSelector(el, selector) {
383
+ // Very basic selector engine
384
+ if (selector.startsWith("#")) {
385
+ return el.getAttribute("id") === selector.slice(1);
386
+ }
387
+ if (selector.startsWith(".")) {
388
+ const className = el.getAttribute("class");
389
+ return className
390
+ ? className.split(/\s+/).includes(selector.slice(1))
391
+ : false;
392
+ }
393
+ if (selector.startsWith("[") && selector.endsWith("]")) {
394
+ const parts = selector.slice(1, -1).split("=");
395
+ const key = parts[0];
396
+ const val = parts[1] ? parts[1].replace(/['"]/g, "") : null;
397
+ const attr = el.getAttribute(key);
398
+ return val ? attr === val : attr !== null;
399
+ }
400
+ // Tag name
401
+ return el.tagName === selector || selector === "*";
402
+ }
403
+ function querySelectorAllRecursive(root, selector, results) {
404
+ // Check self (if not root of query? Standard querySelectorAll doesn't match root usually, but here we traverse children)
405
+ // Actually querySelectorAll searches *descendants*.
406
+ const children = root.childNodes;
407
+ for (const child of children) {
408
+ if (child instanceof Element) {
409
+ if (matchSelector(child, selector)) {
410
+ results.push(child);
411
+ }
412
+ querySelectorAllRecursive(child, selector, results);
413
+ }
414
+ }
415
+ }
@@ -0,0 +1,22 @@
1
+ import type { CST } from "../cst/xml-cst";
2
+ import type { ModelElement } from "../model/xml-api-model";
3
+ export interface EditorStateConfig {
4
+ source: string;
5
+ model: ModelElement | null;
6
+ cst: CST | null;
7
+ }
8
+ /**
9
+ * Represents a snapshot of the editor state at a specific point in time.
10
+ * Includes the source code, the logical model, and the physical CST.
11
+ */
12
+ export declare class EditorState {
13
+ readonly source: string;
14
+ readonly model: ModelElement | null;
15
+ readonly cst: CST | null;
16
+ constructor(config: EditorStateConfig);
17
+ /**
18
+ * Creates a new state with updated properties.
19
+ */
20
+ update(changes: Partial<EditorStateConfig>): EditorState;
21
+ static create(source: string): EditorState;
22
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorState = void 0;
4
+ /**
5
+ * Represents a snapshot of the editor state at a specific point in time.
6
+ * Includes the source code, the logical model, and the physical CST.
7
+ */
8
+ class EditorState {
9
+ constructor(config) {
10
+ this.source = config.source;
11
+ this.model = config.model;
12
+ this.cst = config.cst;
13
+ }
14
+ /**
15
+ * Creates a new state with updated properties.
16
+ */
17
+ update(changes) {
18
+ return new EditorState({
19
+ source: changes.source !== undefined ? changes.source : this.source,
20
+ model: changes.model !== undefined ? changes.model : this.model,
21
+ cst: changes.cst !== undefined ? changes.cst : this.cst,
22
+ });
23
+ }
24
+ static create(source) {
25
+ return new EditorState({
26
+ source,
27
+ model: null,
28
+ cst: null,
29
+ });
30
+ }
31
+ }
32
+ exports.EditorState = EditorState;
@@ -0,0 +1,55 @@
1
+ import type { Grammar } from "../cst/grammar";
2
+ import type { CST } from "../cst/xml-cst";
3
+ import { ModelElement, type ModelNode } from "../model/xml-api-model";
4
+ import { type EventHandler } from "../xml-api-events";
5
+ import type { CollabBridge } from "../collab/bridge";
6
+ import { EditorState } from "./editor-state";
7
+ import { Transaction } from "./transaction";
8
+ export declare class SyncEngine {
9
+ private _state;
10
+ private parser;
11
+ private binder;
12
+ private history;
13
+ private events;
14
+ private isTransacting;
15
+ private collabBridge;
16
+ constructor(source: string, grammar?: Grammar);
17
+ get state(): EditorState;
18
+ get source(): string;
19
+ get model(): ModelElement | null;
20
+ get cst(): CST | null;
21
+ get grammar(): Grammar;
22
+ setCollabBridge(bridge: CollabBridge): void;
23
+ /**
24
+ * Subscribe to model changes.
25
+ */
26
+ on(handler: EventHandler): () => void;
27
+ /**
28
+ * Applies a transaction to the engine, updating the state and notifying listeners.
29
+ */
30
+ dispatch(tr: Transaction): void;
31
+ /**
32
+ * Update the source code (e.g. from text editor).
33
+ * Handles history recording and incremental parsing.
34
+ */
35
+ updateSource(from: number, to: number, text: string): void;
36
+ /**
37
+ * Apply a programmatic change derived from Model operations.
38
+ * This is the "Application -> Source" flow.
39
+ */
40
+ applyPatch(start: number, end: number, text: string): void;
41
+ undo(): void;
42
+ redo(): void;
43
+ setAttribute(modelNode: ModelElement, key: string, value: string): void;
44
+ updateText(modelNode: ModelElement, text: string): void;
45
+ replaceNode(target: ModelNode, content: ModelNode): void;
46
+ insertNode(parent: ModelElement, child: ModelNode, index: number): void;
47
+ removeNode(parent: ModelElement, child: ModelNode): void;
48
+ private fullParse;
49
+ private tryIncrementalUpdate;
50
+ private updateModelIncremental;
51
+ private findNodeAt;
52
+ private findModelNodePath;
53
+ private updateAncestorsWellFormed;
54
+ private detectIndent;
55
+ }