@speclynx/apidom-datamodel 4.0.3 → 4.0.5
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/CHANGELOG.md +10 -0
- package/package.json +5 -4
- package/src/KeyValuePair.ts +0 -31
- package/src/Metadata.ts +0 -100
- package/src/Namespace.ts +0 -260
- package/src/ObjectSlice.ts +0 -228
- package/src/clone/errors/CloneError.ts +0 -26
- package/src/clone/errors/DeepCloneError.ts +0 -8
- package/src/clone/errors/ShallowCloneError.ts +0 -8
- package/src/clone/index.ts +0 -195
- package/src/elements/Annotation.ts +0 -35
- package/src/elements/Comment.ts +0 -16
- package/src/elements/LinkElement.ts +0 -49
- package/src/elements/ParseResult.ts +0 -94
- package/src/elements/RefElement.ts +0 -33
- package/src/elements/SourceMap.ts +0 -170
- package/src/elements/Style.ts +0 -56
- package/src/index.ts +0 -79
- package/src/predicates/elements.ts +0 -42
- package/src/predicates/index.ts +0 -89
- package/src/predicates/primitives.ts +0 -79
- package/src/primitives/ArrayElement.ts +0 -161
- package/src/primitives/BooleanElement.ts +0 -18
- package/src/primitives/CollectionElement.ts +0 -191
- package/src/primitives/Element.ts +0 -556
- package/src/primitives/MemberElement.ts +0 -61
- package/src/primitives/NullElement.ts +0 -26
- package/src/primitives/NumberElement.ts +0 -18
- package/src/primitives/ObjectElement.ts +0 -263
- package/src/primitives/StringElement.ts +0 -25
- package/src/registration.ts +0 -111
- package/src/serialisers/JSONSerialiser.ts +0 -295
- package/src/types.ts +0 -72
package/src/clone/index.ts
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import { clone } from 'ramda';
|
|
2
|
-
|
|
3
|
-
import ObjectSlice from '../ObjectSlice.ts';
|
|
4
|
-
import KeyValuePair from '../KeyValuePair.ts';
|
|
5
|
-
import Element from '../primitives/Element.ts';
|
|
6
|
-
import MemberElement from '../primitives/MemberElement.ts';
|
|
7
|
-
import { isElement, hasElementSourceMap, hasElementStyle } from '../predicates/index.ts';
|
|
8
|
-
import SourceMapElement from '../elements/SourceMap.ts';
|
|
9
|
-
import DeepCloneError from './errors/DeepCloneError.ts';
|
|
10
|
-
import ShallowCloneError from './errors/ShallowCloneError.ts';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @public
|
|
14
|
-
*/
|
|
15
|
-
export type FinalCloneTypes = KeyValuePair | ObjectSlice;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
export type DeepCloneOptions = {
|
|
21
|
-
visited?: WeakMap<object, object>;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const cloneDeepElement = (element: Element, options: DeepCloneOptions): Element => {
|
|
25
|
-
const { visited = new WeakMap<object, object>() } = options;
|
|
26
|
-
const passThroughOptions = { ...options, visited };
|
|
27
|
-
|
|
28
|
-
// detect cycle and return memoized value
|
|
29
|
-
if (visited.has(element)) {
|
|
30
|
-
return visited.get(element) as Element;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const copy = cloneShallowElement(element);
|
|
34
|
-
visited.set(element, copy);
|
|
35
|
-
|
|
36
|
-
const { content } = element;
|
|
37
|
-
if (Array.isArray(content)) {
|
|
38
|
-
copy.content = content.map((el: Element) => cloneDeepElement(el, passThroughOptions));
|
|
39
|
-
} else if (isElement(content)) {
|
|
40
|
-
copy.content = cloneDeepElement(content as Element, passThroughOptions);
|
|
41
|
-
} else if ((content as unknown) instanceof KeyValuePair) {
|
|
42
|
-
copy.content = cloneDeepKeyValuePair(content as KeyValuePair, passThroughOptions);
|
|
43
|
-
} else {
|
|
44
|
-
copy.content = content;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return copy;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const cloneDeepKeyValuePair = (kvp: KeyValuePair, options: DeepCloneOptions): KeyValuePair => {
|
|
51
|
-
const { visited = new WeakMap<object, object>() } = options;
|
|
52
|
-
const passThroughOptions = { ...options, visited };
|
|
53
|
-
|
|
54
|
-
if (visited.has(kvp)) {
|
|
55
|
-
return visited.get(kvp) as KeyValuePair;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const { key, value } = kvp;
|
|
59
|
-
const keyCopy = key !== undefined ? cloneDeepElement(key, passThroughOptions) : undefined;
|
|
60
|
-
const valueCopy = value !== undefined ? cloneDeepElement(value, passThroughOptions) : undefined;
|
|
61
|
-
const copy = new KeyValuePair(keyCopy, valueCopy);
|
|
62
|
-
visited.set(kvp, copy);
|
|
63
|
-
return copy;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const cloneDeepObjectSlice = (slice: ObjectSlice, options: DeepCloneOptions): ObjectSlice => {
|
|
67
|
-
const { visited = new WeakMap<object, object>() } = options;
|
|
68
|
-
const passThroughOptions = { ...options, visited };
|
|
69
|
-
|
|
70
|
-
if (visited.has(slice)) {
|
|
71
|
-
return visited.get(slice) as ObjectSlice;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const items = [...slice].map(
|
|
75
|
-
(element) => cloneDeepElement(element, passThroughOptions) as MemberElement,
|
|
76
|
-
);
|
|
77
|
-
const copy = new ObjectSlice(items);
|
|
78
|
-
visited.set(slice, copy);
|
|
79
|
-
return copy;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Creates a deep clone of an ApiDOM Element, KeyValuePair, or ObjectSlice.
|
|
84
|
-
* Handles cycles by memoizing visited objects.
|
|
85
|
-
* @public
|
|
86
|
-
*/
|
|
87
|
-
export const cloneDeep = <T extends Element | FinalCloneTypes>(
|
|
88
|
-
value: T,
|
|
89
|
-
options: DeepCloneOptions = {},
|
|
90
|
-
): T => {
|
|
91
|
-
if (value instanceof KeyValuePair) {
|
|
92
|
-
return cloneDeepKeyValuePair(value, options) as T;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (value instanceof ObjectSlice) {
|
|
96
|
-
return cloneDeepObjectSlice(value, options) as T;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (isElement(value)) {
|
|
100
|
-
return cloneDeepElement(value, options) as T;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
throw new DeepCloneError("Value provided to cloneDeep function couldn't be cloned", {
|
|
104
|
-
value,
|
|
105
|
-
});
|
|
106
|
-
};
|
|
107
|
-
cloneDeep.safe = <T>(value: T): T => {
|
|
108
|
-
try {
|
|
109
|
-
return cloneDeep(value as Element | FinalCloneTypes) as T;
|
|
110
|
-
} catch {
|
|
111
|
-
return value;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const cloneShallowKeyValuePair = (keyValuePair: KeyValuePair): KeyValuePair => {
|
|
116
|
-
const { key, value } = keyValuePair;
|
|
117
|
-
return new KeyValuePair(key, value);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const cloneShallowObjectSlice = (objectSlice: ObjectSlice): ObjectSlice => {
|
|
121
|
-
const items = [...objectSlice];
|
|
122
|
-
return new ObjectSlice(items);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const cloneShallowElement = <T extends Element>(element: T): T => {
|
|
126
|
-
const Ctor = element.constructor as new () => T;
|
|
127
|
-
const copy = new Ctor();
|
|
128
|
-
|
|
129
|
-
copy.element = element.element;
|
|
130
|
-
|
|
131
|
-
if (!element.isMetaEmpty) {
|
|
132
|
-
copy.meta = element.meta.cloneDeep();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (!element.isAttributesEmpty) {
|
|
136
|
-
copy.attributes = cloneDeep(element.attributes);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (hasElementSourceMap(element)) {
|
|
140
|
-
SourceMapElement.transfer(element, copy);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (hasElementStyle(element)) {
|
|
144
|
-
copy.style = clone(element.style);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const { content } = element;
|
|
148
|
-
if (isElement(content)) {
|
|
149
|
-
copy.content = cloneShallowElement(content as Element);
|
|
150
|
-
} else if (Array.isArray(content)) {
|
|
151
|
-
copy.content = [...content];
|
|
152
|
-
} else if ((content as unknown) instanceof KeyValuePair) {
|
|
153
|
-
copy.content = cloneShallowKeyValuePair(content as KeyValuePair);
|
|
154
|
-
} else {
|
|
155
|
-
copy.content = content;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return copy;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Creates a shallow clone of an ApiDOM Element, KeyValuePair, or ObjectSlice.
|
|
163
|
-
* The element itself is cloned, but content references are shared.
|
|
164
|
-
* Meta and attributes are deep cloned to preserve semantic information.
|
|
165
|
-
* @public
|
|
166
|
-
*/
|
|
167
|
-
export const cloneShallow = <T extends Element | FinalCloneTypes>(value: T): T => {
|
|
168
|
-
if (value instanceof KeyValuePair) {
|
|
169
|
-
return cloneShallowKeyValuePair(value) as T;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (value instanceof ObjectSlice) {
|
|
173
|
-
return cloneShallowObjectSlice(value) as T;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (isElement(value)) {
|
|
177
|
-
return cloneShallowElement(value) as T;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
throw new ShallowCloneError("Value provided to cloneShallow function couldn't be cloned", {
|
|
181
|
-
value,
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
cloneShallow.safe = <T>(value: T): T => {
|
|
185
|
-
try {
|
|
186
|
-
return cloneShallow(value as Element | FinalCloneTypes) as T;
|
|
187
|
-
} catch {
|
|
188
|
-
return value;
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
export { default as CloneError } from './errors/CloneError.ts';
|
|
193
|
-
export type { CloneErrorOptions } from './errors/CloneError.ts';
|
|
194
|
-
export { default as DeepCloneError } from './errors/DeepCloneError.ts';
|
|
195
|
-
export { default as ShallowCloneError } from './errors/ShallowCloneError.ts';
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import StringElement from '../primitives/StringElement.ts';
|
|
2
|
-
import type Element from '../primitives/Element.ts';
|
|
3
|
-
import type { Meta, Attributes } from '../types.ts';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* AnnotationElement represents a parsing annotation (warning or error).
|
|
7
|
-
*
|
|
8
|
-
* The annotation's class indicates its severity:
|
|
9
|
-
* - 'warning' - A non-fatal issue
|
|
10
|
-
* - 'error' - A fatal issue
|
|
11
|
-
*
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
class AnnotationElement extends StringElement {
|
|
15
|
-
constructor(content?: string, meta?: Meta, attributes?: Attributes) {
|
|
16
|
-
super(content, meta, attributes);
|
|
17
|
-
this.element = 'annotation';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The annotation code identifying the type of annotation.
|
|
22
|
-
*/
|
|
23
|
-
get code(): Element | undefined {
|
|
24
|
-
if (this.hasAttributesProperty('code')) {
|
|
25
|
-
return this.attributes.get('code') as Element;
|
|
26
|
-
}
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
set code(value: unknown) {
|
|
31
|
-
this.attributes.set('code', value);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export default AnnotationElement;
|
package/src/elements/Comment.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import StringElement from '../primitives/StringElement.ts';
|
|
2
|
-
import type { Meta, Attributes } from '../types.ts';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* CommentElement represents a comment in the source document.
|
|
6
|
-
*
|
|
7
|
-
* @public
|
|
8
|
-
*/
|
|
9
|
-
class CommentElement extends StringElement {
|
|
10
|
-
constructor(content?: string, meta?: Meta, attributes?: Attributes) {
|
|
11
|
-
super(content, meta, attributes);
|
|
12
|
-
this.element = 'comment';
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default CommentElement;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import Element, { type Meta, type Attributes } from '../primitives/Element.ts';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* LinkElement represents a hyperlink in ApiDOM.
|
|
5
|
-
*
|
|
6
|
-
* Hyperlinking MAY be used to link to other resources, provide links to
|
|
7
|
-
* instructions on how to process a given element (by way of a profile or
|
|
8
|
-
* other means), and may be used to provide meta data about the element in
|
|
9
|
-
* which it's found. The meaning and purpose of the hyperlink is defined by
|
|
10
|
-
* the link relation according to RFC 5988.
|
|
11
|
-
*
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
class LinkElement extends Element {
|
|
15
|
-
constructor(content?: unknown, meta?: Meta, attributes?: Attributes) {
|
|
16
|
-
super(content || [], meta, attributes);
|
|
17
|
-
this.element = 'link';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The relation identifier for the link, as defined in RFC 5988.
|
|
22
|
-
*/
|
|
23
|
-
get relation(): Element | undefined {
|
|
24
|
-
if (this.hasAttributesProperty('relation')) {
|
|
25
|
-
return this.attributes.get('relation');
|
|
26
|
-
}
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
set relation(relation: string | Element | undefined) {
|
|
31
|
-
this.attributes.set('relation', relation);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The URI for the given link.
|
|
36
|
-
*/
|
|
37
|
-
get href(): Element | undefined {
|
|
38
|
-
if (this.hasAttributesProperty('href')) {
|
|
39
|
-
return this.attributes.get('href');
|
|
40
|
-
}
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
set href(href: string | Element | undefined) {
|
|
45
|
-
this.attributes.set('href', href);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export default LinkElement;
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import ArrayElement from '../primitives/ArrayElement.ts';
|
|
2
|
-
import type Element from '../primitives/Element.ts';
|
|
3
|
-
import { includesClasses } from '../predicates/index.ts';
|
|
4
|
-
import type { Meta, Attributes } from '../primitives/Element.ts';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* ParseResultElement represents the result of parsing a document.
|
|
8
|
-
*
|
|
9
|
-
* Contains the parsed API element, any result elements, and annotations
|
|
10
|
-
* (warnings and errors) from the parsing process.
|
|
11
|
-
*
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
class ParseResultElement extends ArrayElement {
|
|
15
|
-
constructor(content?: unknown[], meta?: Meta, attributes?: Attributes) {
|
|
16
|
-
super(content, meta, attributes);
|
|
17
|
-
this.element = 'parseResult';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The main API element from the parse result.
|
|
22
|
-
*/
|
|
23
|
-
get api(): Element | undefined {
|
|
24
|
-
return this.filter((item) => includesClasses(item, ['api'])).first;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* All result elements from the parse result.
|
|
29
|
-
*/
|
|
30
|
-
get results(): ArrayElement {
|
|
31
|
-
return this.filter((item) => includesClasses(item, ['result']));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* The first result element.
|
|
36
|
-
*/
|
|
37
|
-
get result(): Element | undefined {
|
|
38
|
-
return this.results.first;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* All annotation elements (warnings and errors).
|
|
43
|
-
*/
|
|
44
|
-
get annotations(): ArrayElement {
|
|
45
|
-
return this.filter((item) => item.element === 'annotation');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* All warning annotations.
|
|
50
|
-
*/
|
|
51
|
-
get warnings(): ArrayElement {
|
|
52
|
-
return this.filter(
|
|
53
|
-
(item) => item.element === 'annotation' && includesClasses(item, ['warning']),
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* All error annotations.
|
|
59
|
-
*/
|
|
60
|
-
get errors(): ArrayElement {
|
|
61
|
-
return this.filter((item) => item.element === 'annotation' && includesClasses(item, ['error']));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Whether the parse result is empty (contains only annotations).
|
|
66
|
-
*/
|
|
67
|
-
override get isEmpty(): boolean {
|
|
68
|
-
return this.reject((item) => item.element === 'annotation').length === 0;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Replaces the first result element with the given replacement.
|
|
73
|
-
* @returns true if replacement was successful, false otherwise
|
|
74
|
-
*/
|
|
75
|
-
replaceResult(replacement: Element): boolean {
|
|
76
|
-
const { result } = this;
|
|
77
|
-
|
|
78
|
-
if (result === undefined) {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const content = this._content as Element[];
|
|
83
|
-
const searchIndex = content.findIndex((e) => e === result);
|
|
84
|
-
if (searchIndex === -1) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
content[searchIndex] = replacement;
|
|
89
|
-
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export default ParseResultElement;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import Element, { type Meta, type Attributes } from '../primitives/Element.ts';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* RefElement represents a reference to another element in ApiDOM.
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
class RefElement extends Element {
|
|
8
|
-
constructor(content?: unknown, meta?: Meta, attributes?: Attributes) {
|
|
9
|
-
super(content || [], meta, attributes);
|
|
10
|
-
this.element = 'ref';
|
|
11
|
-
|
|
12
|
-
if (!this.path) {
|
|
13
|
-
this.path = 'element';
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Path of referenced element to transclude instead of element itself.
|
|
19
|
-
* @defaultValue 'element'
|
|
20
|
-
*/
|
|
21
|
-
get path(): Element | undefined {
|
|
22
|
-
if (this.hasAttributesProperty('path')) {
|
|
23
|
-
return this.attributes.get('path');
|
|
24
|
-
}
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
set path(newValue: string | Element | undefined) {
|
|
29
|
-
this.attributes.set('path', newValue);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default RefElement;
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import StringElement from '../primitives/StringElement.ts';
|
|
2
|
-
import type { Meta, Attributes } from '../types.ts';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Shape with optional source position properties.
|
|
6
|
-
* @public
|
|
7
|
-
*/
|
|
8
|
-
interface SourceMapShape {
|
|
9
|
-
startLine?: number;
|
|
10
|
-
startCharacter?: number;
|
|
11
|
-
startOffset?: number;
|
|
12
|
-
endLine?: number;
|
|
13
|
-
endCharacter?: number;
|
|
14
|
-
endOffset?: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* SourceMapElement stores source position as a compact VLQ-encoded string.
|
|
19
|
-
*
|
|
20
|
-
* The encoded string contains 6 values: startLine, startCharacter, startOffset,
|
|
21
|
-
* endLine, endCharacter, endOffset. All values use UTF-16 code units,
|
|
22
|
-
* compatible with LSP, TextDocument, and JavaScript string indexing.
|
|
23
|
-
*
|
|
24
|
-
* web-tree-sitter automatically provides position data in UTF-16 code units.
|
|
25
|
-
*
|
|
26
|
-
* @public
|
|
27
|
-
*/
|
|
28
|
-
class SourceMapElement extends StringElement {
|
|
29
|
-
constructor(content?: string, meta?: Meta, attributes?: Attributes) {
|
|
30
|
-
super(content, meta, attributes);
|
|
31
|
-
this.element = 'sourceMap';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Transfers source position properties from one object to another.
|
|
36
|
-
*/
|
|
37
|
-
static transfer(from: SourceMapShape, to: SourceMapShape): void {
|
|
38
|
-
to.startLine = from.startLine;
|
|
39
|
-
to.startCharacter = from.startCharacter;
|
|
40
|
-
to.startOffset = from.startOffset;
|
|
41
|
-
to.endLine = from.endLine;
|
|
42
|
-
to.endCharacter = from.endCharacter;
|
|
43
|
-
to.endOffset = from.endOffset;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Creates a SourceMapElement from source position properties.
|
|
48
|
-
* Returns undefined if any position property is not a number.
|
|
49
|
-
* Also assigns position properties to the instance for inspection.
|
|
50
|
-
*/
|
|
51
|
-
static from(source: SourceMapShape): SourceMapElement | undefined {
|
|
52
|
-
const { startLine, startCharacter, startOffset, endLine, endCharacter, endOffset } = source;
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
typeof startLine !== 'number' ||
|
|
56
|
-
typeof startCharacter !== 'number' ||
|
|
57
|
-
typeof startOffset !== 'number' ||
|
|
58
|
-
typeof endLine !== 'number' ||
|
|
59
|
-
typeof endCharacter !== 'number' ||
|
|
60
|
-
typeof endOffset !== 'number'
|
|
61
|
-
) {
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const packed = packSourceMap([
|
|
66
|
-
startLine,
|
|
67
|
-
startCharacter,
|
|
68
|
-
startOffset,
|
|
69
|
-
endLine,
|
|
70
|
-
endCharacter,
|
|
71
|
-
endOffset,
|
|
72
|
-
]);
|
|
73
|
-
|
|
74
|
-
const sourceMap = new SourceMapElement(packed);
|
|
75
|
-
sourceMap.startLine = startLine;
|
|
76
|
-
sourceMap.startCharacter = startCharacter;
|
|
77
|
-
sourceMap.startOffset = startOffset;
|
|
78
|
-
sourceMap.endLine = endLine;
|
|
79
|
-
sourceMap.endCharacter = endCharacter;
|
|
80
|
-
sourceMap.endOffset = endOffset;
|
|
81
|
-
|
|
82
|
-
return sourceMap;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Decodes the VLQ string and applies source position properties to the target.
|
|
87
|
-
*/
|
|
88
|
-
public applyTo(target: SourceMapShape): void {
|
|
89
|
-
if (!this.content) return;
|
|
90
|
-
[
|
|
91
|
-
target.startLine,
|
|
92
|
-
target.startCharacter,
|
|
93
|
-
target.startOffset,
|
|
94
|
-
target.endLine,
|
|
95
|
-
target.endCharacter,
|
|
96
|
-
target.endOffset,
|
|
97
|
-
] = unpackSourceMap(this.content as string);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
102
|
-
|
|
103
|
-
// Encode one unsigned integer to Base64-VLQ
|
|
104
|
-
function vlqEncodeInt(value: number): string {
|
|
105
|
-
let vlq = value >>> 0; // ensure unsigned 32-bit
|
|
106
|
-
let out = '';
|
|
107
|
-
|
|
108
|
-
do {
|
|
109
|
-
let digit = vlq & 31; // 5 bits
|
|
110
|
-
vlq >>>= 5;
|
|
111
|
-
if (vlq !== 0) digit |= 32; // continuation bit
|
|
112
|
-
out += BASE64[digit];
|
|
113
|
-
} while (vlq !== 0);
|
|
114
|
-
|
|
115
|
-
return out;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Decode one unsigned integer from Base64-VLQ, starting at `index`
|
|
119
|
-
function vlqDecodeInt(str: string, index = 0): { value: number; next: number } {
|
|
120
|
-
let result = 0;
|
|
121
|
-
let shift = 0;
|
|
122
|
-
let i = index;
|
|
123
|
-
|
|
124
|
-
while (true) {
|
|
125
|
-
const ch = str[i++];
|
|
126
|
-
const digit = BASE64.indexOf(ch);
|
|
127
|
-
if (digit === -1) throw new Error(`Invalid Base64 VLQ char: ${ch}`);
|
|
128
|
-
|
|
129
|
-
const cont = (digit & 32) !== 0;
|
|
130
|
-
result |= (digit & 31) << shift;
|
|
131
|
-
shift += 5;
|
|
132
|
-
|
|
133
|
-
if (!cont) break;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return { value: result >>> 0, next: i };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Span of 6 position values: [startLine, startCharacter, startOffset, endLine, endCharacter, endOffset]
|
|
141
|
-
* @public
|
|
142
|
-
*/
|
|
143
|
-
type Span6 = [number, number, number, number, number, number];
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Encodes 6 position values into a compact VLQ string.
|
|
147
|
-
* @public
|
|
148
|
-
*/
|
|
149
|
-
function packSourceMap(v: Span6): string {
|
|
150
|
-
return 'sm1:' + v.map(vlqEncodeInt).join('');
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Decodes a VLQ string into 6 position values.
|
|
155
|
-
* @public
|
|
156
|
-
*/
|
|
157
|
-
function unpackSourceMap(packed: string): Span6 {
|
|
158
|
-
const s = packed.startsWith('sm1:') ? packed.slice(4) : packed;
|
|
159
|
-
const out: number[] = [];
|
|
160
|
-
let i = 0;
|
|
161
|
-
for (let k = 0; k < 6; k++) {
|
|
162
|
-
const r = vlqDecodeInt(s, i);
|
|
163
|
-
out.push(r.value);
|
|
164
|
-
i = r.next;
|
|
165
|
-
}
|
|
166
|
-
return out as Span6;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export default SourceMapElement;
|
|
170
|
-
export type { Span6, SourceMapShape };
|
package/src/elements/Style.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import ObjectElement from '../primitives/ObjectElement.ts';
|
|
2
|
-
import type { Meta, Attributes } from '../types.ts';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Shape with optional style property.
|
|
6
|
-
* @public
|
|
7
|
-
*/
|
|
8
|
-
interface StyleShape {
|
|
9
|
-
style?: Record<string, unknown>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* StyleElement stores format-specific style information for round-trip preservation.
|
|
14
|
-
*
|
|
15
|
-
* The style data is stored as a plain object with format-specific namespaces
|
|
16
|
-
* (e.g., `yaml`, `json`). This element exists only during serialization/deserialization
|
|
17
|
-
* (refract format) - in memory, style lives directly on `element.style`.
|
|
18
|
-
*
|
|
19
|
-
* Follows the same pattern as SourceMapElement with __mappings__.
|
|
20
|
-
*
|
|
21
|
-
* @public
|
|
22
|
-
*/
|
|
23
|
-
class StyleElement extends ObjectElement {
|
|
24
|
-
constructor(content?: Record<string, unknown>, meta?: Meta, attributes?: Attributes) {
|
|
25
|
-
super(content, meta, attributes);
|
|
26
|
-
this.element = '__styles__';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Transfers style property from one element to another.
|
|
31
|
-
*/
|
|
32
|
-
static transfer(from: StyleShape, to: StyleShape): void {
|
|
33
|
-
to.style = from.style;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Creates a StyleElement from an element's style property.
|
|
38
|
-
* Returns undefined if the element has no style.
|
|
39
|
-
*/
|
|
40
|
-
static from(source: StyleShape): StyleElement | undefined {
|
|
41
|
-
if (!source.style) {
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
return new StyleElement(source.style);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Restores the style property on the target element from this StyleElement.
|
|
49
|
-
*/
|
|
50
|
-
public applyTo(target: StyleShape): void {
|
|
51
|
-
target.style = this.toValue() as Record<string, unknown>;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export default StyleElement;
|
|
56
|
-
export type { StyleShape };
|