@miy2/xml-api 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dom.js CHANGED
@@ -1,14 +1,10 @@
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");
1
+ import { ModelCDATA, ModelComment, ModelElement, ModelText, } from "./model/xml-api-model";
6
2
  /**
7
3
  * Base class for all DOM nodes.
8
4
  * Implements a subset of the W3C Node interface to allow applications
9
5
  * to interact with the XML model using familiar methods.
10
6
  */
11
- class Node {
7
+ export class Node {
12
8
  constructor(model, ownerDocument) {
13
9
  this.model = model;
14
10
  this.ownerDocument = ownerDocument;
@@ -27,11 +23,16 @@ class Node {
27
23
  return createWrapper(this.model.parent, this.ownerDocument);
28
24
  }
29
25
  /**
30
- * Returns a NodeList containing all children of this node.
26
+ * Returns a NodeList containing all children of this node, respecting the document's filter.
31
27
  */
32
28
  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)));
29
+ var _a;
30
+ if (this.model instanceof ModelElement) {
31
+ let children = this.model.children;
32
+ if ((_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.nodeFilter) {
33
+ children = children.filter((c) => { var _a; return (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.accepts(c); });
34
+ }
35
+ return new NodeList(children.map((c) => createWrapper(c, this.ownerDocument)));
35
36
  }
36
37
  return new NodeList([]);
37
38
  }
@@ -47,9 +48,13 @@ class Node {
47
48
  const parent = this.model.parent;
48
49
  if (!parent)
49
50
  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);
51
+ let index = parent.children.indexOf(this.model);
52
+ while (index < parent.children.length - 1) {
53
+ index++;
54
+ const sibling = parent.children[index];
55
+ if (!this.ownerDocument || this.ownerDocument.accepts(sibling)) {
56
+ return createWrapper(sibling, this.ownerDocument);
57
+ }
53
58
  }
54
59
  return null;
55
60
  }
@@ -57,20 +62,24 @@ class Node {
57
62
  const parent = this.model.parent;
58
63
  if (!parent)
59
64
  return null;
60
- const index = parent.children.indexOf(this.model);
61
- if (index > 0) {
62
- return createWrapper(parent.children[index - 1], this.ownerDocument);
65
+ let index = parent.children.indexOf(this.model);
66
+ while (index > 0) {
67
+ index--;
68
+ const sibling = parent.children[index];
69
+ if (!this.ownerDocument || this.ownerDocument.accepts(sibling)) {
70
+ return createWrapper(sibling, this.ownerDocument);
71
+ }
63
72
  }
64
73
  return null;
65
74
  }
66
75
  get textContent() {
67
- if (this.model instanceof xml_api_model_1.ModelText)
76
+ if (this.model instanceof ModelText)
68
77
  return this.model.text;
69
- if (this.model instanceof xml_api_model_1.ModelComment)
78
+ if (this.model instanceof ModelComment)
70
79
  return this.model.content;
71
- if (this.model instanceof xml_api_model_1.ModelCDATA)
80
+ if (this.model instanceof ModelCDATA)
72
81
  return this.model.content;
73
- if (this.model instanceof xml_api_model_1.ModelElement) {
82
+ if (this.model instanceof ModelElement) {
74
83
  return this.model.children
75
84
  .map((c) => createWrapper(c, this.ownerDocument).textContent)
76
85
  .join("");
@@ -80,23 +89,24 @@ class Node {
80
89
  set textContent(value) {
81
90
  var _a, _b, _c, _d;
82
91
  const val = value || "";
83
- if (this.model instanceof xml_api_model_1.ModelText) {
84
- this.model.text = val;
92
+ const m = this.model;
93
+ if (m instanceof ModelText && this instanceof CharacterData) {
94
+ m.text = val;
85
95
  (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyTextChange(this, val);
86
96
  }
87
- else if (this.model instanceof xml_api_model_1.ModelComment) {
88
- this.model.content = val;
97
+ else if (m instanceof ModelComment && this instanceof CharacterData) {
98
+ m.content = val;
89
99
  (_b = this.ownerDocument) === null || _b === void 0 ? void 0 : _b.notifyTextChange(this, val);
90
100
  }
91
- else if (this.model instanceof xml_api_model_1.ModelCDATA) {
92
- this.model.content = val;
101
+ else if (m instanceof ModelCDATA && this instanceof CharacterData) {
102
+ m.content = val;
93
103
  (_c = this.ownerDocument) === null || _c === void 0 ? void 0 : _c.notifyTextChange(this, val);
94
104
  }
95
- else if (this.model instanceof xml_api_model_1.ModelElement) {
96
- this.model.children = [];
105
+ else if (m instanceof ModelElement && this instanceof Element) {
106
+ m.children = [];
97
107
  if (val) {
98
- const textNode = new xml_api_model_1.ModelText(val);
99
- this.model.addChild(textNode);
108
+ const textNode = new ModelText(val);
109
+ m.addChild(textNode);
100
110
  }
101
111
  (_d = this.ownerDocument) === null || _d === void 0 ? void 0 : _d.notifyElementTextChange(this, val);
102
112
  }
@@ -107,9 +117,8 @@ class Node {
107
117
  */
108
118
  appendChild(newChild) {
109
119
  var _a;
110
- if (this.model instanceof xml_api_model_1.ModelElement) {
120
+ if (this.model instanceof ModelElement) {
111
121
  this.model.addChild(newChild.getModel());
112
- // @ts-ignore
113
122
  newChild.ownerDocument = this.ownerDocument;
114
123
  (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyChildAdded(this, newChild, this.model.children.length - 1);
115
124
  return newChild;
@@ -123,7 +132,7 @@ class Node {
123
132
  */
124
133
  insertBefore(newChild, refChild) {
125
134
  var _a;
126
- if (this.model instanceof xml_api_model_1.ModelElement) {
135
+ if (this.model instanceof ModelElement) {
127
136
  if (!refChild) {
128
137
  return this.appendChild(newChild);
129
138
  }
@@ -134,20 +143,42 @@ class Node {
134
143
  // Update Model
135
144
  this.model.children.splice(index, 0, newChild.getModel());
136
145
  newChild.getModel().parent = this.model;
137
- // @ts-ignore
138
146
  newChild.ownerDocument = this.ownerDocument;
139
147
  (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyChildAdded(this, newChild, index);
140
148
  return newChild;
141
149
  }
142
150
  throw new Error("HierarchyRequestError");
143
151
  }
152
+ /**
153
+ * Replaces a child node with a new node.
154
+ * @param newChild The new node to add.
155
+ * @param oldChild The child node to be replaced.
156
+ */
157
+ replaceChild(newChild, oldChild) {
158
+ var _a;
159
+ if (this.model instanceof ModelElement) {
160
+ const oldModel = oldChild.getModel();
161
+ const index = this.model.children.indexOf(oldModel);
162
+ if (index === -1)
163
+ throw new Error("NotFoundError");
164
+ // Update Model
165
+ this.model.children[index] = newChild.getModel();
166
+ newChild.getModel().parent = this.model;
167
+ newChild.ownerDocument = this.ownerDocument;
168
+ // oldModel.parent = null; // Delayed until after notification
169
+ (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.notifyChildReplaced(this, newChild, oldChild);
170
+ oldModel.parent = null;
171
+ return oldChild;
172
+ }
173
+ throw new Error("HierarchyRequestError");
174
+ }
144
175
  /**
145
176
  * Removes a child node from the DOM and returns the removed node.
146
177
  * @param child The child node to remove.
147
178
  */
148
179
  removeChild(child) {
149
180
  var _a;
150
- if (this.model instanceof xml_api_model_1.ModelElement) {
181
+ if (this.model instanceof ModelElement) {
151
182
  const childModel = child.getModel();
152
183
  const index = this.model.children.indexOf(childModel);
153
184
  if (index === -1)
@@ -165,8 +196,7 @@ class Node {
165
196
  return this.model;
166
197
  }
167
198
  }
168
- exports.Node = Node;
169
- class NodeList extends Array {
199
+ export class NodeList extends Array {
170
200
  constructor(items) {
171
201
  super(...items);
172
202
  Object.setPrototypeOf(this, NodeList.prototype);
@@ -175,11 +205,10 @@ class NodeList extends Array {
175
205
  return this[index] || null;
176
206
  }
177
207
  }
178
- exports.NodeList = NodeList;
179
208
  /**
180
209
  * Base class for Text, Comment, and CDATASection nodes.
181
210
  */
182
- class CharacterData extends Node {
211
+ export class CharacterData extends Node {
183
212
  get data() {
184
213
  return this.textContent || "";
185
214
  }
@@ -190,8 +219,7 @@ class CharacterData extends Node {
190
219
  return this.data.length;
191
220
  }
192
221
  }
193
- exports.CharacterData = CharacterData;
194
- class Text extends CharacterData {
222
+ export class Text extends CharacterData {
195
223
  get nodeType() {
196
224
  return this.TEXT_NODE;
197
225
  }
@@ -199,8 +227,7 @@ class Text extends CharacterData {
199
227
  return "#text";
200
228
  }
201
229
  }
202
- exports.Text = Text;
203
- class Comment extends CharacterData {
230
+ export class Comment extends CharacterData {
204
231
  get nodeType() {
205
232
  return this.COMMENT_NODE;
206
233
  }
@@ -208,8 +235,7 @@ class Comment extends CharacterData {
208
235
  return "#comment";
209
236
  }
210
237
  }
211
- exports.Comment = Comment;
212
- class CDATASection extends CharacterData {
238
+ export class CDATASection extends CharacterData {
213
239
  get nodeType() {
214
240
  return this.CDATA_SECTION_NODE;
215
241
  }
@@ -217,11 +243,10 @@ class CDATASection extends CharacterData {
217
243
  return "#cdata-section";
218
244
  }
219
245
  }
220
- exports.CDATASection = CDATASection;
221
246
  /**
222
247
  * Represents an element in the XML document.
223
248
  */
224
- class Element extends Node {
249
+ export class Element extends Node {
225
250
  constructor(model, ownerDocument) {
226
251
  super(model, ownerDocument);
227
252
  this.model = model;
@@ -283,20 +308,26 @@ class Element extends Node {
283
308
  return new NodeList(results);
284
309
  }
285
310
  }
286
- exports.Element = Element;
287
311
  /**
288
312
  * Represents the entire XML document.
289
313
  */
290
- class Document extends Node {
314
+ export class Document extends Node {
291
315
  constructor() {
292
316
  // Document doesn't strictly have a ModelNode parent in this simplified architecture
293
317
  // Or it could wrap a "root" ModelElement
294
318
  // For now, we'll create a dummy root model or handle it differently
295
- super(new xml_api_model_1.ModelElement("#document"), null);
319
+ super(new ModelElement("#document"), null);
296
320
  this._documentElement = null;
297
321
  this.observer = null;
322
+ this.nodeFilter = null;
298
323
  this.ownerDocument = this; // Document owns itself
299
324
  }
325
+ /**
326
+ * Checks if a node is accepted by the current filter.
327
+ */
328
+ accepts(node) {
329
+ return this.nodeFilter ? this.nodeFilter(node) : true;
330
+ }
300
331
  /**
301
332
  * Sets the observer to listen for DOM changes.
302
333
  */
@@ -323,6 +354,10 @@ class Document extends Node {
323
354
  var _a;
324
355
  (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onChildRemoved(parent, child, index);
325
356
  }
357
+ notifyChildReplaced(parent, newChild, oldChild) {
358
+ var _a;
359
+ (_a = this.observer) === null || _a === void 0 ? void 0 : _a.onChildReplaced(parent, newChild, oldChild);
360
+ }
326
361
  get nodeType() {
327
362
  return this.DOCUMENT_NODE;
328
363
  }
@@ -339,21 +374,20 @@ class Document extends Node {
339
374
  // Ensure the element is part of the document structure
340
375
  // In a real DOM, documentElement is a child of Document
341
376
  // Here, we just link them logically
342
- // @ts-ignore
343
377
  element.ownerDocument = this;
344
378
  }
345
379
  }
346
380
  createElement(tagName) {
347
- return new Element(new xml_api_model_1.ModelElement(tagName), this);
381
+ return new Element(new ModelElement(tagName), this);
348
382
  }
349
383
  createTextNode(data) {
350
- return new Text(new xml_api_model_1.ModelText(data), this);
384
+ return new Text(new ModelText(data), this);
351
385
  }
352
386
  createComment(data) {
353
- return new Comment(new xml_api_model_1.ModelComment(data), this);
387
+ return new Comment(new ModelComment(data), this);
354
388
  }
355
389
  createCDATASection(data) {
356
- return new CDATASection(new xml_api_model_1.ModelCDATA(data), this);
390
+ return new CDATASection(new ModelCDATA(data), this);
357
391
  }
358
392
  querySelector(selector) {
359
393
  if (!this.documentElement)
@@ -366,16 +400,15 @@ class Document extends Node {
366
400
  return this.documentElement.querySelectorAll(selector);
367
401
  }
368
402
  }
369
- exports.Document = Document;
370
403
  // Helper factory
371
- function createWrapper(model, doc) {
372
- if (model instanceof xml_api_model_1.ModelElement)
404
+ export function createWrapper(model, doc) {
405
+ if (model instanceof ModelElement)
373
406
  return new Element(model, doc);
374
- if (model instanceof xml_api_model_1.ModelText)
407
+ if (model instanceof ModelText)
375
408
  return new Text(model, doc);
376
- if (model instanceof xml_api_model_1.ModelComment)
409
+ if (model instanceof ModelComment)
377
410
  return new Comment(model, doc);
378
- if (model instanceof xml_api_model_1.ModelCDATA)
411
+ if (model instanceof ModelCDATA)
379
412
  return new CDATASection(model, doc);
380
413
  throw new Error(`Unknown model type: ${model.getType()}`);
381
414
  }
@@ -1,11 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EditorState = void 0;
4
1
  /**
5
2
  * Represents a snapshot of the editor state at a specific point in time.
6
3
  * Includes the source code, the logical model, and the physical CST.
7
4
  */
8
- class EditorState {
5
+ export class EditorState {
9
6
  constructor(config) {
10
7
  this.source = config.source;
11
8
  this.model = config.model;
@@ -29,4 +26,3 @@ class EditorState {
29
26
  });
30
27
  }
31
28
  }
32
- exports.EditorState = EditorState;
@@ -1,10 +1,20 @@
1
+ import type { CollabBridge } from "../collab/bridge";
1
2
  import type { Grammar } from "../cst/grammar";
2
3
  import type { CST } from "../cst/xml-cst";
3
4
  import { ModelElement, type ModelNode } from "../model/xml-api-model";
4
5
  import { type EventHandler } from "../xml-api-events";
5
- import type { CollabBridge } from "../collab/bridge";
6
6
  import { EditorState } from "./editor-state";
7
7
  import { Transaction } from "./transaction";
8
+ /**
9
+ * The core engine that manages the editor state and coordinates synchronization.
10
+ *
11
+ * It implements a transaction-based update cycle:
12
+ * 1. Receives a `Transaction` describing changes.
13
+ * 2. Updates the `EditorState` (Source).
14
+ * 3. Triggers the `Parser` (Source -> CST).
15
+ * 4. Triggers the `XMLBinder` (CST -> Model).
16
+ * 5. Notifies listeners (including `SchemaView`s) of changes.
17
+ */
8
18
  export declare class SyncEngine {
9
19
  private _state;
10
20
  private parser;
@@ -26,30 +36,54 @@ export declare class SyncEngine {
26
36
  on(handler: EventHandler): () => void;
27
37
  /**
28
38
  * Applies a transaction to the engine, updating the state and notifying listeners.
39
+ * This is the single point of truth for all state transitions in the system.
40
+ *
41
+ * It handles:
42
+ * - History recording (Undo/Redo)
43
+ * - Incremental Parsing and Reconciliation
44
+ * - Event Dispatching
45
+ * - Collaboration hooks
46
+ *
47
+ * @param tr The transaction to apply.
29
48
  */
30
49
  dispatch(tr: Transaction): void;
31
50
  /**
32
51
  * Update the source code (e.g. from text editor).
33
52
  * Handles history recording and incremental parsing.
34
53
  */
35
- updateSource(from: number, to: number, text: string): void;
54
+ updateSource(from: number, to: number, text: string, meta?: Record<string, any>): void;
36
55
  /**
37
56
  * Apply a programmatic change derived from Model operations.
38
57
  * This is the "Application -> Source" flow.
58
+ * @deprecated Use `dispatch(new Transaction(state).replace(...))` instead.
39
59
  */
40
- applyPatch(start: number, end: number, text: string): void;
60
+ applyPatch(start: number, end: number, text: string, meta?: Record<string, any>): void;
41
61
  undo(): void;
42
62
  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;
63
+ /**
64
+ * @deprecated Use `dispatch(new TransactionBuilder(engine.state, engine.binder).setAttribute(...))` instead.
65
+ */
66
+ setAttribute(modelNode: ModelElement, key: string, value: string, meta?: Record<string, any>): void;
67
+ /**
68
+ * @deprecated Use `dispatch(new TransactionBuilder(engine.state, engine.binder).updateText(...))` instead.
69
+ */
70
+ updateText(modelNode: ModelElement, text: string, meta?: Record<string, any>): void;
71
+ /**
72
+ * @deprecated Use `dispatch(new TransactionBuilder(engine.state, engine.binder).replaceNode(...))` instead.
73
+ */
74
+ replaceNode(target: ModelNode, content: ModelNode, meta?: Record<string, any>): void;
75
+ /**
76
+ * @deprecated Use `dispatch(new TransactionBuilder(engine.state, engine.binder).insertNode(...))` instead.
77
+ */
78
+ insertNode(parent: ModelElement, child: ModelNode, index: number, meta?: Record<string, any>): void;
79
+ /**
80
+ * @deprecated Use `dispatch(new TransactionBuilder(engine.state, engine.binder).removeNode(...))` instead.
81
+ */
82
+ removeNode(parent: ModelElement, child: ModelNode, meta?: Record<string, any>): void;
48
83
  private fullParse;
49
84
  private tryIncrementalUpdate;
50
85
  private updateModelIncremental;
51
86
  private findNodeAt;
52
87
  private findModelNodePath;
53
88
  private updateAncestorsWellFormed;
54
- private detectIndent;
55
89
  }