@speclynx/apidom-datamodel 4.0.2 → 4.0.3

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +4 -5
  3. package/src/KeyValuePair.cjs +31 -0
  4. package/src/KeyValuePair.mjs +27 -0
  5. package/src/KeyValuePair.ts +31 -0
  6. package/src/Metadata.cjs +91 -0
  7. package/src/Metadata.mjs +87 -0
  8. package/src/Metadata.ts +100 -0
  9. package/src/Namespace.cjs +212 -0
  10. package/src/Namespace.mjs +206 -0
  11. package/src/Namespace.ts +260 -0
  12. package/src/ObjectSlice.cjs +199 -0
  13. package/src/ObjectSlice.mjs +195 -0
  14. package/src/ObjectSlice.ts +228 -0
  15. package/src/clone/errors/CloneError.cjs +22 -0
  16. package/src/clone/errors/CloneError.mjs +19 -0
  17. package/src/clone/errors/CloneError.ts +26 -0
  18. package/src/clone/errors/DeepCloneError.cjs +11 -0
  19. package/src/clone/errors/DeepCloneError.mjs +6 -0
  20. package/src/clone/errors/DeepCloneError.ts +8 -0
  21. package/src/clone/errors/ShallowCloneError.cjs +11 -0
  22. package/src/clone/errors/ShallowCloneError.mjs +6 -0
  23. package/src/clone/errors/ShallowCloneError.ts +8 -0
  24. package/src/clone/index.cjs +188 -0
  25. package/src/clone/index.mjs +178 -0
  26. package/src/clone/index.ts +195 -0
  27. package/src/elements/Annotation.cjs +35 -0
  28. package/src/elements/Annotation.mjs +30 -0
  29. package/src/elements/Annotation.ts +35 -0
  30. package/src/elements/Comment.cjs +18 -0
  31. package/src/elements/Comment.mjs +13 -0
  32. package/src/elements/Comment.ts +16 -0
  33. package/src/elements/LinkElement.cjs +50 -0
  34. package/src/elements/LinkElement.mjs +45 -0
  35. package/src/elements/LinkElement.ts +49 -0
  36. package/src/elements/ParseResult.cjs +91 -0
  37. package/src/elements/ParseResult.mjs +86 -0
  38. package/src/elements/ParseResult.ts +94 -0
  39. package/src/elements/RefElement.cjs +34 -0
  40. package/src/elements/RefElement.mjs +29 -0
  41. package/src/elements/RefElement.ts +33 -0
  42. package/src/elements/SourceMap.cjs +140 -0
  43. package/src/elements/SourceMap.mjs +134 -0
  44. package/src/elements/SourceMap.ts +170 -0
  45. package/src/elements/Style.cjs +54 -0
  46. package/src/elements/Style.mjs +48 -0
  47. package/src/elements/Style.ts +56 -0
  48. package/src/index.cjs +58 -0
  49. package/src/index.mjs +11 -0
  50. package/src/index.ts +79 -0
  51. package/src/predicates/elements.cjs +46 -0
  52. package/src/predicates/elements.mjs +35 -0
  53. package/src/predicates/elements.ts +42 -0
  54. package/src/predicates/index.cjs +77 -0
  55. package/src/predicates/index.mjs +56 -0
  56. package/src/predicates/index.ts +89 -0
  57. package/src/predicates/primitives.cjs +69 -0
  58. package/src/predicates/primitives.mjs +56 -0
  59. package/src/predicates/primitives.ts +79 -0
  60. package/src/primitives/ArrayElement.cjs +155 -0
  61. package/src/primitives/ArrayElement.mjs +148 -0
  62. package/src/primitives/ArrayElement.ts +161 -0
  63. package/src/primitives/BooleanElement.cjs +20 -0
  64. package/src/primitives/BooleanElement.mjs +15 -0
  65. package/src/primitives/BooleanElement.ts +18 -0
  66. package/src/primitives/CollectionElement.cjs +180 -0
  67. package/src/primitives/CollectionElement.mjs +173 -0
  68. package/src/primitives/CollectionElement.ts +191 -0
  69. package/src/primitives/Element.cjs +510 -0
  70. package/src/primitives/Element.mjs +505 -0
  71. package/src/primitives/Element.ts +556 -0
  72. package/src/primitives/MemberElement.cjs +58 -0
  73. package/src/primitives/MemberElement.mjs +53 -0
  74. package/src/primitives/MemberElement.ts +61 -0
  75. package/src/primitives/NullElement.cjs +28 -0
  76. package/src/primitives/NullElement.mjs +23 -0
  77. package/src/primitives/NullElement.ts +26 -0
  78. package/src/primitives/NumberElement.cjs +20 -0
  79. package/src/primitives/NumberElement.mjs +15 -0
  80. package/src/primitives/NumberElement.ts +18 -0
  81. package/src/primitives/ObjectElement.cjs +220 -0
  82. package/src/primitives/ObjectElement.mjs +214 -0
  83. package/src/primitives/ObjectElement.ts +263 -0
  84. package/src/primitives/StringElement.cjs +27 -0
  85. package/src/primitives/StringElement.mjs +22 -0
  86. package/src/primitives/StringElement.ts +25 -0
  87. package/src/registration.cjs +101 -0
  88. package/src/registration.mjs +79 -0
  89. package/src/registration.ts +111 -0
  90. package/src/serialisers/JSONSerialiser.cjs +230 -0
  91. package/src/serialisers/JSONSerialiser.mjs +221 -0
  92. package/src/serialisers/JSONSerialiser.ts +295 -0
  93. package/src/types.cjs +3 -0
  94. package/src/types.mjs +1 -0
  95. package/src/types.ts +72 -0
@@ -0,0 +1,191 @@
1
+ import Element, { type Meta, type Attributes } from './Element.ts';
2
+ import type ArrayElement from './ArrayElement.ts';
3
+
4
+ /**
5
+ * Condition function for finding elements.
6
+ * @public
7
+ */
8
+ export type FindCondition = (
9
+ item: Element,
10
+ keyOrIndex: Element | number,
11
+ member?: Element,
12
+ ) => boolean;
13
+
14
+ /**
15
+ * Options for finding elements.
16
+ * @public
17
+ */
18
+ export interface FindOptions {
19
+ recursive?: boolean;
20
+ results?: Element[];
21
+ }
22
+
23
+ /**
24
+ * CollectionElement is an abstract base class for collection-like elements.
25
+ * Both ArrayElement and ObjectElement extend this class.
26
+ *
27
+ * This class contains the shared functionality between arrays and objects,
28
+ * while keeping the conflicting methods (get, set, remove, map, filter, etc.)
29
+ * in the respective subclasses.
30
+ *
31
+ * @remarks
32
+ * This is primarily an implementation detail. Use ArrayElement or ObjectElement directly.
33
+ *
34
+ * @typeParam T - The element type contained in the collection, defaults to Element
35
+ * @public
36
+ */
37
+ abstract class CollectionElement<T extends Element = Element> extends Element {
38
+ declare protected _content: T[];
39
+
40
+ constructor(content?: unknown[], meta?: Meta, attributes?: Attributes) {
41
+ super(content || [], meta, attributes);
42
+ }
43
+
44
+ /**
45
+ * Returns the length of the collection.
46
+ */
47
+ get length(): number {
48
+ return this._content.length;
49
+ }
50
+
51
+ /**
52
+ * Returns whether the collection is empty.
53
+ */
54
+ get isEmpty(): boolean {
55
+ return this.length === 0;
56
+ }
57
+
58
+ /**
59
+ * Return the first item in the collection.
60
+ */
61
+ get first(): T | undefined {
62
+ return this._content[0];
63
+ }
64
+
65
+ /**
66
+ * Return the second item in the collection.
67
+ */
68
+ get second(): T | undefined {
69
+ return this._content[1];
70
+ }
71
+
72
+ /**
73
+ * Return the last item in the collection.
74
+ */
75
+ get last(): T | undefined {
76
+ return this._content.at(-1);
77
+ }
78
+
79
+ /**
80
+ * Adds the given elements to the end of the collection.
81
+ */
82
+ push(...values: unknown[]): this {
83
+ for (const value of values) {
84
+ this._content.push(this.refract(value) as T);
85
+ }
86
+ return this;
87
+ }
88
+
89
+ /**
90
+ * Removes the first element from the collection.
91
+ */
92
+ shift(): T | undefined {
93
+ return this._content.shift();
94
+ }
95
+
96
+ /**
97
+ * Adds the given element to the beginning of the collection.
98
+ */
99
+ unshift(value: unknown): void {
100
+ this._content.unshift(this.refract(value) as T);
101
+ }
102
+
103
+ /**
104
+ * Looks for matching children using deep equality.
105
+ */
106
+ includes(value: unknown): boolean {
107
+ return this._content.some((element) => element.equals(value));
108
+ }
109
+
110
+ /**
111
+ * Recursively search all descendants using a condition function.
112
+ */
113
+ findElements(condition: FindCondition, givenOptions?: FindOptions): Element[] {
114
+ const options = givenOptions || {};
115
+ const recursive = !!options.recursive;
116
+ const results = options.results === undefined ? [] : options.results;
117
+
118
+ for (let i = 0; i < this._content.length; i += 1) {
119
+ const item = this._content[i];
120
+
121
+ // We use duck-typing here to support any registered class that
122
+ // may contain other elements.
123
+ type FindElementsFn = (condition: FindCondition, options?: FindOptions) => Element[];
124
+ const itemWithFindElements = item as unknown as { findElements?: FindElementsFn };
125
+ if (recursive && typeof itemWithFindElements.findElements === 'function') {
126
+ itemWithFindElements.findElements(condition, {
127
+ results,
128
+ recursive,
129
+ });
130
+ }
131
+
132
+ if (condition(item, i, undefined)) {
133
+ results.push(item);
134
+ }
135
+ }
136
+
137
+ return results;
138
+ }
139
+
140
+ /**
141
+ * Recursively search all descendants using a condition function.
142
+ */
143
+ find(condition: FindCondition): ArrayElement {
144
+ const results = this.findElements(condition, { recursive: true });
145
+ return new this.ArrayElement(results);
146
+ }
147
+
148
+ /**
149
+ * Find elements by their element type name.
150
+ */
151
+ findByElement(element: string): ArrayElement {
152
+ return this.find((item) => item.element === element);
153
+ }
154
+
155
+ /**
156
+ * Find elements by class name.
157
+ */
158
+ findByClass(className: string): ArrayElement {
159
+ return this.find((item) => {
160
+ const classes = item.classes as unknown as { includes?: (value: unknown) => boolean };
161
+ return typeof classes.includes === 'function' && classes.includes(className);
162
+ });
163
+ }
164
+
165
+ /**
166
+ * Search the tree recursively and find the element with the matching ID.
167
+ */
168
+ getById(id: string): Element | undefined {
169
+ return this.find((item) => item.id === id).first;
170
+ }
171
+
172
+ /**
173
+ * Returns an empty collection element.
174
+ */
175
+ abstract empty(): this;
176
+
177
+ /**
178
+ * Concatenates two collection elements.
179
+ */
180
+ concat(other: CollectionElement<T>): this {
181
+ const Ctor = this.constructor as new (content: T[]) => this;
182
+ return new Ctor(this._content.concat(other._content));
183
+ }
184
+
185
+ // Iterator support
186
+ [Symbol.iterator](): IterableIterator<T> {
187
+ return this._content[Symbol.iterator]();
188
+ }
189
+ }
190
+
191
+ export default CollectionElement;
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _ramda = require("ramda");
7
+ var _Metadata = _interopRequireDefault(require("../Metadata.cjs"));
8
+ exports.Metadata = _Metadata.default;
9
+ var _KeyValuePair = _interopRequireDefault(require("../KeyValuePair.cjs"));
10
+ var _ObjectSlice = _interopRequireDefault(require("../ObjectSlice.cjs"));
11
+ // shared singleton for frozen elements with no meta — avoids allocation on every access
12
+ const FROZEN_EMPTY_METADATA = Object.freeze(new _Metadata.default());
13
+
14
+ /**
15
+ * Valid content types for an Element.
16
+ * @public
17
+ */
18
+
19
+ /**
20
+ * Base Element class that all ApiDOM elements extend.
21
+ *
22
+ * Elements are the core building blocks of ApiDOM. Each element has:
23
+ * - An `element` property identifying its type
24
+ * - Optional `content` holding the element's value
25
+ * - Optional `meta` for metadata (id, classes, title, description, links)
26
+ * - Optional `attributes` for element-specific properties
27
+ *
28
+ * @public
29
+ */
30
+ class Element {
31
+ // ============================================================
32
+ // Public Properties
33
+ // ============================================================
34
+
35
+ /**
36
+ * Parent element reference (set when tree is frozen).
37
+ */
38
+ parent;
39
+
40
+ /**
41
+ * Format-specific style information for round-trip preservation.
42
+ * Each format owns its own namespace (e.g., `yaml`, `json`).
43
+ */
44
+ style;
45
+
46
+ // ============================================================================
47
+ // Source Position (LSP-compatible, TextDocument-compatible, UTF-16 code units)
48
+ // web-tree-sitter automatically provides position data in UTF-16 code units.
49
+ // ============================================================================
50
+
51
+ /**
52
+ * Starting line number (0-based).
53
+ * Compatible with LSP Position.line.
54
+ */
55
+ startLine;
56
+
57
+ /**
58
+ * Starting character offset within the line (0-based, UTF-16 code units).
59
+ * Compatible with LSP Position.character.
60
+ */
61
+ startCharacter;
62
+
63
+ /**
64
+ * Starting offset from beginning of document (UTF-16 code units).
65
+ * Can be used directly as JavaScript string index.
66
+ */
67
+ startOffset;
68
+
69
+ /**
70
+ * Ending line number (0-based).
71
+ * Compatible with LSP Position.line.
72
+ */
73
+ endLine;
74
+
75
+ /**
76
+ * Ending character offset within the line (0-based, UTF-16 code units).
77
+ * Compatible with LSP Position.character.
78
+ */
79
+ endCharacter;
80
+
81
+ /**
82
+ * Ending offset from beginning of document (UTF-16 code units).
83
+ * Can be used directly as JavaScript string index.
84
+ */
85
+ endOffset;
86
+
87
+ // ============================================================
88
+ // Protected Properties
89
+ // ============================================================
90
+
91
+ /**
92
+ * The element type identifier.
93
+ * @internal
94
+ */
95
+ _storedElement = 'element';
96
+
97
+ /**
98
+ * The element's content/value.
99
+ * @internal
100
+ */
101
+ _content;
102
+
103
+ /**
104
+ * Metadata about this element.
105
+ * @internal
106
+ */
107
+ _meta;
108
+
109
+ /**
110
+ * Element-specific attributes.
111
+ * @internal
112
+ */
113
+ _attributes;
114
+
115
+ // ============================================================
116
+ // Prototype-assigned properties (set in registration.ts)
117
+ // Using 'declare' allows TypeScript to know about these
118
+ // without generating runtime code.
119
+ // ============================================================
120
+
121
+ /** @internal ObjectElement constructor for creating meta/attributes */
122
+
123
+ /** @internal ArrayElement constructor for creating arrays */
124
+
125
+ /** @internal MemberElement constructor for creating object members */
126
+
127
+ /** @internal RefElement constructor for creating references */
128
+
129
+ /** @internal Function to convert values to elements */
130
+
131
+ constructor(content, meta, attributes) {
132
+ if (meta !== undefined) {
133
+ this.meta = meta;
134
+ }
135
+ if (attributes !== undefined) {
136
+ this.attributes = attributes;
137
+ }
138
+ if (content !== undefined) {
139
+ this.content = content;
140
+ }
141
+ }
142
+
143
+ // ============================================================
144
+ // Core Properties
145
+ // ============================================================
146
+
147
+ /**
148
+ * The element type identifier (e.g., 'string', 'object', 'array').
149
+ */
150
+ get element() {
151
+ return this._storedElement;
152
+ }
153
+ set element(value) {
154
+ this._storedElement = value;
155
+ }
156
+
157
+ /**
158
+ * The element's content/value.
159
+ */
160
+ get content() {
161
+ return this._content;
162
+ }
163
+ set content(value) {
164
+ // Already an element
165
+ if (value instanceof Element) {
166
+ this._content = value;
167
+ return;
168
+ }
169
+
170
+ // Primitives (inlined for performance - avoids 8 function calls)
171
+ if (value === null || value === undefined || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint' || typeof value === 'symbol') {
172
+ this._content = value;
173
+ return;
174
+ }
175
+
176
+ // KeyValuePair
177
+ if (value instanceof _KeyValuePair.default) {
178
+ this._content = value;
179
+ return;
180
+ }
181
+
182
+ // ObjectSlice - extract elements array
183
+ if (value instanceof _ObjectSlice.default) {
184
+ this._content = value.elements;
185
+ return;
186
+ }
187
+
188
+ // Array - refract each item
189
+ if (Array.isArray(value)) {
190
+ this._content = value.map(item => this.refract(item));
191
+ return;
192
+ }
193
+
194
+ // Plain object - convert to MemberElements
195
+ if (typeof value === 'object') {
196
+ this._content = Object.entries(value).map(([key, val]) => new this.MemberElement(key, val));
197
+ return;
198
+ }
199
+ throw new Error(`Cannot set content to value of type ${typeof value}`);
200
+ }
201
+
202
+ /**
203
+ * Metadata about this element (id, classes, title, description, links).
204
+ * Lazily creates a Metadata instance if not set.
205
+ */
206
+ get meta() {
207
+ if (!this._meta) {
208
+ if (this.isFrozen) return FROZEN_EMPTY_METADATA;
209
+ this._meta = new _Metadata.default();
210
+ }
211
+ return this._meta;
212
+ }
213
+ set meta(value) {
214
+ if (value instanceof _Metadata.default) {
215
+ this._meta = value;
216
+ } else if (value && typeof value === 'object') {
217
+ const meta = new _Metadata.default();
218
+ Object.assign(meta, value);
219
+ this._meta = meta;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Element-specific attributes.
225
+ * Lazily creates an ObjectElement if not set.
226
+ */
227
+ get attributes() {
228
+ if (!this._attributes) {
229
+ if (this.isFrozen) {
230
+ const attributes = new this.ObjectElement();
231
+ attributes.freeze();
232
+ return attributes;
233
+ }
234
+ this._attributes = new this.ObjectElement();
235
+ }
236
+ return this._attributes;
237
+ }
238
+ set attributes(value) {
239
+ if (value instanceof Element) {
240
+ this._attributes = value;
241
+ } else {
242
+ this.attributes.set(value ?? {});
243
+ }
244
+ }
245
+
246
+ // ============================================================
247
+ // Meta Property Shortcuts
248
+ // ============================================================
249
+
250
+ /** Unique identifier for this element. */
251
+ get id() {
252
+ if (!this.hasMetaProperty('id')) {
253
+ if (this.isFrozen) return '';
254
+ this.setMetaProperty('id', '');
255
+ }
256
+ return this.meta.get('id');
257
+ }
258
+ set id(value) {
259
+ this.setMetaProperty('id', value);
260
+ }
261
+
262
+ /** CSS-like class names. */
263
+ get classes() {
264
+ if (!this.hasMetaProperty('classes')) {
265
+ if (this.isFrozen) return [];
266
+ this.setMetaProperty('classes', []);
267
+ }
268
+ return this.meta.get('classes');
269
+ }
270
+ set classes(value) {
271
+ this.setMetaProperty('classes', value);
272
+ }
273
+
274
+ /** Hyperlinks associated with this element. */
275
+ get links() {
276
+ if (!this.hasMetaProperty('links')) {
277
+ if (this.isFrozen) {
278
+ const empty = new this.ArrayElement();
279
+ empty.freeze();
280
+ return empty;
281
+ }
282
+ this.setMetaProperty('links', new this.ArrayElement());
283
+ }
284
+ return this.meta.get('links');
285
+ }
286
+ set links(value) {
287
+ this.setMetaProperty('links', value);
288
+ }
289
+
290
+ // ============================================================
291
+ // Tree Navigation
292
+ // ============================================================
293
+
294
+ /** Returns direct children of this element. */
295
+ get children() {
296
+ const {
297
+ _content: content
298
+ } = this;
299
+ if (Array.isArray(content)) {
300
+ return content;
301
+ }
302
+ if (content instanceof _KeyValuePair.default) {
303
+ const children = [];
304
+ if (content.key) children.push(content.key);
305
+ if (content.value) children.push(content.value);
306
+ return children;
307
+ }
308
+ if (content instanceof Element) {
309
+ return [content];
310
+ }
311
+ return [];
312
+ }
313
+
314
+ // ============================================================
315
+ // Freezable Implementation
316
+ // ============================================================
317
+
318
+ /** Whether this element is frozen (immutable). */
319
+ get isFrozen() {
320
+ return Object.isFrozen(this);
321
+ }
322
+
323
+ /**
324
+ * Freezes the element tree, making it immutable.
325
+ * Sets up parent references for tree traversal.
326
+ */
327
+ freeze() {
328
+ if (this.isFrozen) return;
329
+
330
+ // Freeze meta and attributes
331
+ if (this._meta) {
332
+ this._meta.freeze();
333
+ }
334
+ if (this._attributes) {
335
+ this._attributes.parent = this;
336
+ this._attributes.freeze();
337
+ }
338
+
339
+ // Freeze children
340
+ for (const child of this.children) {
341
+ child.parent = this;
342
+ child.freeze();
343
+ }
344
+
345
+ // Freeze content array if applicable
346
+ if (Array.isArray(this._content)) {
347
+ Object.freeze(this._content);
348
+ }
349
+ Object.freeze(this);
350
+ }
351
+
352
+ // ============================================================
353
+ // ToValue Implementation
354
+ // ============================================================
355
+
356
+ /**
357
+ * Converts the element to its JavaScript value representation.
358
+ */
359
+ toValue() {
360
+ const {
361
+ _content
362
+ } = this;
363
+ if (_content instanceof Element) {
364
+ return _content.toValue();
365
+ }
366
+ if (_content instanceof _KeyValuePair.default) {
367
+ return _content.toValue();
368
+ }
369
+ if (Array.isArray(_content)) {
370
+ return _content.map(el => el.toValue());
371
+ }
372
+ return _content;
373
+ }
374
+
375
+ // ============================================================
376
+ // Equatable Implementation
377
+ // ============================================================
378
+
379
+ /**
380
+ * Checks deep equality with another value.
381
+ */
382
+ equals(value) {
383
+ const compareTo = value instanceof Element ? value.toValue() : value;
384
+ return (0, _ramda.equals)(this.toValue(), compareTo);
385
+ }
386
+
387
+ // ============================================================
388
+ // Element Type
389
+ // ============================================================
390
+
391
+ /**
392
+ * Returns the primitive type name for this element.
393
+ * Override in subclasses (e.g., 'string', 'number', 'array').
394
+ */
395
+ primitive() {
396
+ return undefined;
397
+ }
398
+
399
+ // ============================================================
400
+ // Content Operations
401
+ // ============================================================
402
+
403
+ /**
404
+ * Sets the content of this element.
405
+ * @returns this for chaining
406
+ */
407
+ set(content) {
408
+ this.content = content;
409
+ return this;
410
+ }
411
+
412
+ // ============================================================
413
+ // Reference Creation
414
+ // ============================================================
415
+
416
+ /**
417
+ * Creates a RefElement pointing to this element.
418
+ * @param path - Optional path within the referenced element
419
+ * @throws Error if this element has no ID
420
+ */
421
+ toRef(path) {
422
+ const idValue = this.id;
423
+ if (idValue === '') {
424
+ throw new Error('Cannot create reference to an element without an ID');
425
+ }
426
+ const ref = new this.RefElement(idValue);
427
+ if (typeof path === 'string') {
428
+ ref.path = this.refract(path);
429
+ }
430
+ return ref;
431
+ }
432
+
433
+ /**
434
+ * Gets a meta property value.
435
+ *
436
+ * When the property doesn't exist:
437
+ * - With defaultValue: returns the provided default value
438
+ * - Without defaultValue: returns undefined
439
+ */
440
+
441
+ getMetaProperty(name, defaultValue) {
442
+ if (!this.hasMetaProperty(name)) {
443
+ return defaultValue;
444
+ }
445
+ return this.meta.get(name);
446
+ }
447
+
448
+ /**
449
+ * Sets a meta property.
450
+ */
451
+ setMetaProperty(name, value) {
452
+ this.meta.set(name, value);
453
+ }
454
+
455
+ /**
456
+ * Checks whether a meta property exists.
457
+ */
458
+ hasMetaProperty(name) {
459
+ return this._meta !== undefined && this._meta.hasKey(name);
460
+ }
461
+
462
+ /**
463
+ * Checks if meta is empty.
464
+ */
465
+ get isMetaEmpty() {
466
+ return this._meta === undefined || this._meta.isEmpty;
467
+ }
468
+
469
+ /**
470
+ * Gets an attribute property, creating it with default value if not present.
471
+ */
472
+ getAttributesProperty(name, defaultValue) {
473
+ if (!this.hasAttributesProperty(name)) {
474
+ if (this.isFrozen) {
475
+ const element = this.refract(defaultValue);
476
+ element.freeze();
477
+ return element;
478
+ }
479
+ this.attributes.set(name, defaultValue);
480
+ }
481
+ return this.attributes.get(name);
482
+ }
483
+
484
+ /**
485
+ * Sets an attributes property.
486
+ */
487
+ setAttributesProperty(name, value) {
488
+ this.attributes.set(name, value);
489
+ }
490
+
491
+ /**
492
+ * Checks whether an attributes property exists.
493
+ */
494
+ hasAttributesProperty(name) {
495
+ if (!this.isAttributesEmpty) {
496
+ return this.attributes.hasKey(name);
497
+ }
498
+ return false;
499
+ }
500
+
501
+ /**
502
+ * Checks if attributes is empty.
503
+ */
504
+ get isAttributesEmpty() {
505
+ return this._attributes === undefined || this.attributes.isEmpty;
506
+ }
507
+ }
508
+
509
+ // Re-export types for convenience
510
+ var _default = exports.default = Element;