@speclynx/apidom-core 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/dist/apidom-core.browser.js +28 -4
- package/dist/apidom-core.browser.min.js +1 -1
- package/package.json +7 -6
- package/src/fields/fixed-fields.ts +0 -61
- package/src/fields/index.ts +0 -2
- package/src/identity/errors/ElementIdentityError.ts +0 -26
- package/src/identity/index.ts +0 -64
- package/src/index.ts +0 -81
- package/src/media-types.ts +0 -24
- package/src/merge/deepmerge.ts +0 -274
- package/src/merge/merge-left.ts +0 -14
- package/src/merge/merge-right.ts +0 -42
- package/src/namespace.ts +0 -8
- package/src/refractor/plugins/dispatcher/index.ts +0 -102
- package/src/refractor/plugins/element-identity.ts +0 -31
- package/src/refractor/plugins/semantic-element-identity.ts +0 -32
- package/src/refractor/toolbox.ts +0 -88
- package/src/specification.ts +0 -68
- package/src/transcluder/Transcluder.ts +0 -147
- package/src/transcluder/index.ts +0 -15
- package/src/transformers/dehydrate.ts +0 -14
- package/src/transformers/from.ts +0 -34
- package/src/transformers/serializers/json.ts +0 -107
- package/src/transformers/serializers/value.ts +0 -70
- package/src/transformers/serializers/yaml-1-2.ts +0 -205
- package/src/transformers/sexprs.ts +0 -30
- package/src/transformers/to-string.ts +0 -15
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Element,
|
|
3
|
-
isElement,
|
|
4
|
-
isObjectElement,
|
|
5
|
-
isArrayElement,
|
|
6
|
-
isRefElement,
|
|
7
|
-
isLinkElement,
|
|
8
|
-
isStringElement,
|
|
9
|
-
isBooleanElement,
|
|
10
|
-
isNumberElement,
|
|
11
|
-
isNullElement,
|
|
12
|
-
} from '@speclynx/apidom-datamodel';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Transforms the ApiDOM into JavaScript POJO.
|
|
16
|
-
* This POJO would be the result of interpreting the ApiDOM
|
|
17
|
-
* into JavaScript structure.
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
const serializer = <T extends Element | unknown>(element: T): unknown => {
|
|
21
|
-
if (!isElement(element)) return element;
|
|
22
|
-
|
|
23
|
-
// Shortcut optimization for primitive element types
|
|
24
|
-
if (
|
|
25
|
-
isStringElement(element) ||
|
|
26
|
-
isNumberElement(element) ||
|
|
27
|
-
isBooleanElement(element) ||
|
|
28
|
-
isNullElement(element)
|
|
29
|
-
) {
|
|
30
|
-
return element.toValue();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// WeakMap for cycle handling - stores references to already-visited elements
|
|
34
|
-
const references = new WeakMap<Element, object | unknown[]>();
|
|
35
|
-
|
|
36
|
-
const serialize = (node: unknown): unknown => {
|
|
37
|
-
if (!isElement(node)) return node;
|
|
38
|
-
|
|
39
|
-
if (isObjectElement(node)) {
|
|
40
|
-
if (references.has(node)) return references.get(node);
|
|
41
|
-
const obj: Record<string, unknown> = {};
|
|
42
|
-
references.set(node, obj);
|
|
43
|
-
node.forEach((value, key) => {
|
|
44
|
-
const k = serialize(key);
|
|
45
|
-
const v = serialize(value);
|
|
46
|
-
if (typeof k === 'string') obj[k] = v;
|
|
47
|
-
});
|
|
48
|
-
return obj;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (isArrayElement(node)) {
|
|
52
|
-
if (references.has(node)) return references.get(node);
|
|
53
|
-
const arr: unknown[] = [];
|
|
54
|
-
references.set(node, arr);
|
|
55
|
-
node.forEach((item) => arr.push(serialize(item)));
|
|
56
|
-
return arr;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (isRefElement(node)) return String(node.toValue());
|
|
60
|
-
if (isLinkElement(node)) {
|
|
61
|
-
return isStringElement(node.href) ? node.href.toValue() : '';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return node.toValue();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
return serialize(element);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export default serializer;
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Document,
|
|
3
|
-
stringify,
|
|
4
|
-
isNode,
|
|
5
|
-
Scalar,
|
|
6
|
-
YAMLMap,
|
|
7
|
-
YAMLSeq,
|
|
8
|
-
Pair,
|
|
9
|
-
type Node as YAMLNode,
|
|
10
|
-
type CreateNodeOptions,
|
|
11
|
-
type DocumentOptions,
|
|
12
|
-
type SchemaOptions,
|
|
13
|
-
type ToStringOptions,
|
|
14
|
-
} from 'yaml';
|
|
15
|
-
import {
|
|
16
|
-
Element,
|
|
17
|
-
isElement,
|
|
18
|
-
isObjectElement,
|
|
19
|
-
isArrayElement,
|
|
20
|
-
isRefElement,
|
|
21
|
-
isLinkElement,
|
|
22
|
-
isStringElement,
|
|
23
|
-
isMemberElement,
|
|
24
|
-
} from '@speclynx/apidom-datamodel';
|
|
25
|
-
|
|
26
|
-
import toValue from './value.ts';
|
|
27
|
-
|
|
28
|
-
interface YAMLElementStyle {
|
|
29
|
-
scalarStyle?: string;
|
|
30
|
-
styleGroup?: string;
|
|
31
|
-
rawContent?: string;
|
|
32
|
-
indent?: number;
|
|
33
|
-
flowCollectionPadding?: boolean;
|
|
34
|
-
comment?: string;
|
|
35
|
-
commentBefore?: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const getStyle = (element: Element): YAMLElementStyle => {
|
|
39
|
-
return (element.style?.yaml ?? {}) as YAMLElementStyle;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// map our scalarStyle strings to YAML library Scalar.Type constants
|
|
43
|
-
const scalarStyleMap: Record<string, Scalar.Type> = {
|
|
44
|
-
Plain: Scalar.PLAIN,
|
|
45
|
-
SingleQuoted: Scalar.QUOTE_SINGLE,
|
|
46
|
-
DoubleQuoted: Scalar.QUOTE_DOUBLE,
|
|
47
|
-
Literal: Scalar.BLOCK_LITERAL,
|
|
48
|
-
Folded: Scalar.BLOCK_FOLDED,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// the YAML library prefixes comments with '#' only (no space), so we add ' ' to get '# comment'
|
|
52
|
-
const applyComments = (node: YAMLNode, style: YAMLElementStyle): void => {
|
|
53
|
-
if (style.comment) node.comment = ` ${style.comment}`;
|
|
54
|
-
if (style.commentBefore) node.commentBefore = ` ${style.commentBefore}`;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @public
|
|
59
|
-
*/
|
|
60
|
-
export interface YAMLSerializerOptions
|
|
61
|
-
extends
|
|
62
|
-
DocumentOptions,
|
|
63
|
-
Pick<CreateNodeOptions, 'aliasDuplicateObjects'>,
|
|
64
|
-
Pick<SchemaOptions, 'sortMapEntries'>,
|
|
65
|
-
ToStringOptions {
|
|
66
|
-
/** Include %YAML directive and document marker */
|
|
67
|
-
directive?: boolean;
|
|
68
|
-
/** Preserve original formatting styles from `element.style.yaml` */
|
|
69
|
-
preserveStyle?: boolean;
|
|
70
|
-
/** Padding inside flow collections (e.g. `{ a: 1 }` vs `{a: 1}`) */
|
|
71
|
-
flowCollectionPadding?: boolean;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Converts an ApiDOM element tree to YAML library AST nodes,
|
|
76
|
-
* preserving style information from `element.style.yaml`.
|
|
77
|
-
*/
|
|
78
|
-
const toYAMLNode = (element: unknown, visited: WeakSet<object>): unknown => {
|
|
79
|
-
if (!isElement(element)) return element;
|
|
80
|
-
|
|
81
|
-
// cycle detection
|
|
82
|
-
if (visited.has(element as object)) return undefined;
|
|
83
|
-
visited.add(element as object);
|
|
84
|
-
|
|
85
|
-
const style = getStyle(element);
|
|
86
|
-
|
|
87
|
-
if (isObjectElement(element)) {
|
|
88
|
-
const map = new YAMLMap();
|
|
89
|
-
map.flow = style.styleGroup === 'Flow';
|
|
90
|
-
applyComments(map, style);
|
|
91
|
-
|
|
92
|
-
element.forEach((value, key, member) => {
|
|
93
|
-
const memberStyle = isMemberElement(member) ? getStyle(member) : {};
|
|
94
|
-
const keyNode = toYAMLNode(key, visited);
|
|
95
|
-
const valueNode = toYAMLNode(value, visited);
|
|
96
|
-
const pair = new Pair(keyNode, valueNode);
|
|
97
|
-
|
|
98
|
-
if (memberStyle.commentBefore && isNode(keyNode)) {
|
|
99
|
-
keyNode.commentBefore = ` ${memberStyle.commentBefore}`;
|
|
100
|
-
}
|
|
101
|
-
if (memberStyle.comment && isNode(valueNode)) {
|
|
102
|
-
valueNode.comment = ` ${memberStyle.comment}`;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
map.items.push(pair);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
return map;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (isArrayElement(element)) {
|
|
112
|
-
const seq = new YAMLSeq();
|
|
113
|
-
seq.flow = style.styleGroup === 'Flow';
|
|
114
|
-
applyComments(seq, style);
|
|
115
|
-
|
|
116
|
-
element.forEach((item) => {
|
|
117
|
-
seq.items.push(toYAMLNode(item, visited));
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
return seq;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (isRefElement(element)) {
|
|
124
|
-
return new Scalar(String(toValue(element)));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (isLinkElement(element)) {
|
|
128
|
-
return new Scalar(isStringElement(element.href) ? toValue(element.href) : '');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// scalar element (string, number, boolean, null)
|
|
132
|
-
const scalarType = style.scalarStyle ? scalarStyleMap[style.scalarStyle] : undefined;
|
|
133
|
-
|
|
134
|
-
const scalar = new Scalar(toValue(element));
|
|
135
|
-
if (scalarType) {
|
|
136
|
-
scalar.type = scalarType;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// use rawContent to infer YAML library format hints for plain scalars that resolved to numbers;
|
|
140
|
-
// only applies to Plain style — quoted scalars are always strings in YAML.
|
|
141
|
-
// note: the YAML library may normalize the representation (e.g. 1.0e10 -> 1e+10, 0x1A -> 0x1a)
|
|
142
|
-
// while preserving the format category (exponential, hex, octal, fractional digits)
|
|
143
|
-
if (style.rawContent && style.scalarStyle === 'Plain' && typeof scalar.value === 'number') {
|
|
144
|
-
if (/[eE]/.test(style.rawContent)) {
|
|
145
|
-
scalar.format = 'EXP';
|
|
146
|
-
} else if (/^0x/i.test(style.rawContent)) {
|
|
147
|
-
scalar.format = 'HEX';
|
|
148
|
-
} else if (/^0o/i.test(style.rawContent)) {
|
|
149
|
-
scalar.format = 'OCT';
|
|
150
|
-
}
|
|
151
|
-
const dotMatch = style.rawContent.match(/\.(\d+)/);
|
|
152
|
-
if (dotMatch) {
|
|
153
|
-
scalar.minFractionDigits = dotMatch[1].length;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
applyComments(scalar, style);
|
|
158
|
-
|
|
159
|
-
return scalar;
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* @public
|
|
164
|
-
*/
|
|
165
|
-
const serializer = (
|
|
166
|
-
element: Element,
|
|
167
|
-
{
|
|
168
|
-
directive = false,
|
|
169
|
-
preserveStyle = false,
|
|
170
|
-
aliasDuplicateObjects = false,
|
|
171
|
-
...options
|
|
172
|
-
}: YAMLSerializerOptions = {},
|
|
173
|
-
): string => {
|
|
174
|
-
const allOptions: YAMLSerializerOptions = { aliasDuplicateObjects, ...options };
|
|
175
|
-
|
|
176
|
-
if (preserveStyle) {
|
|
177
|
-
const style = getStyle(element);
|
|
178
|
-
if (options.indent === undefined && typeof style.indent === 'number') {
|
|
179
|
-
allOptions.indent = style.indent;
|
|
180
|
-
}
|
|
181
|
-
if (typeof style.flowCollectionPadding === 'boolean') {
|
|
182
|
-
allOptions.flowCollectionPadding = style.flowCollectionPadding;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const rootNode = toYAMLNode(element, new WeakSet());
|
|
186
|
-
const doc = new Document(undefined, allOptions);
|
|
187
|
-
doc.contents = rootNode as YAMLNode;
|
|
188
|
-
|
|
189
|
-
if (directive) {
|
|
190
|
-
doc.directives!.yaml.explicit = true;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return doc.toString(allOptions);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (directive) {
|
|
197
|
-
const doc = new Document(toValue(element), allOptions);
|
|
198
|
-
doc.directives!.yaml.explicit = true;
|
|
199
|
-
return doc.toString(allOptions);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return stringify(toValue(element), allOptions);
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
export default serializer;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Element } from '@speclynx/apidom-datamodel';
|
|
2
|
-
import { traverse, type Path } from '@speclynx/apidom-traverse';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Transforms ApiDOM into S-expressions (Symbolic Expressions).
|
|
6
|
-
* @public
|
|
7
|
-
*/
|
|
8
|
-
const sexprs = (element: Element): string => {
|
|
9
|
-
let result = '';
|
|
10
|
-
let nestingLevel = 0;
|
|
11
|
-
|
|
12
|
-
traverse(element, {
|
|
13
|
-
enter(path: Path<Element>) {
|
|
14
|
-
const { element: elementName } = path.node;
|
|
15
|
-
const capitalizedElementName = elementName.charAt(0).toUpperCase() + elementName.slice(1);
|
|
16
|
-
const indent = ' '.repeat(nestingLevel);
|
|
17
|
-
result += nestingLevel > 0 ? '\n' : '';
|
|
18
|
-
result += `${indent}(${capitalizedElementName}Element`;
|
|
19
|
-
nestingLevel += 1;
|
|
20
|
-
},
|
|
21
|
-
leave() {
|
|
22
|
-
nestingLevel -= 1;
|
|
23
|
-
result += ')';
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return result;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export default sexprs;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Element, Namespace } from '@speclynx/apidom-datamodel';
|
|
2
|
-
|
|
3
|
-
import defaultNamespace from '../namespace.ts';
|
|
4
|
-
import dehydrate from './dehydrate.ts';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Create a refracted string representation of an Element.
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
const toString = (element: Element, namespace: Namespace = defaultNamespace): string => {
|
|
11
|
-
const refractStructure = dehydrate(element, namespace);
|
|
12
|
-
return JSON.stringify(refractStructure);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default toString;
|