UNPKG

3.15 kBJavaScriptView Raw
1'use strict';
2
3var Alias = require('../nodes/Alias.js');
4var identity = require('../nodes/identity.js');
5var Scalar = require('../nodes/Scalar.js');
6
7const defaultTagPrefix = 'tag:yaml.org,2002:';
8function findTagObject(value, tagName, tags) {
9 if (tagName) {
10 const match = tags.filter(t => t.tag === tagName);
11 const tagObj = match.find(t => !t.format) ?? match[0];
12 if (!tagObj)
13 throw new Error(`Tag ${tagName} not found`);
14 return tagObj;
15 }
16 return tags.find(t => t.identify?.(value) && !t.format);
17}
18function createNode(value, tagName, ctx) {
19 if (identity.isDocument(value))
20 value = value.contents;
21 if (identity.isNode(value))
22 return value;
23 if (identity.isPair(value)) {
24 const map = ctx.schema[identity.MAP].createNode?.(ctx.schema, null, ctx);
25 map.items.push(value);
26 return map;
27 }
28 if (value instanceof String ||
29 value instanceof Number ||
30 value instanceof Boolean ||
31 (typeof BigInt !== 'undefined' && value instanceof BigInt) // not supported everywhere
32 ) {
33 // https://tc39.es/ecma262/#sec-serializejsonproperty
34 value = value.valueOf();
35 }
36 const { aliasDuplicateObjects, onAnchor, onTagObj, schema, sourceObjects } = ctx;
37 // Detect duplicate references to the same object & use Alias nodes for all
38 // after first. The `ref` wrapper allows for circular references to resolve.
39 let ref = undefined;
40 if (aliasDuplicateObjects && value && typeof value === 'object') {
41 ref = sourceObjects.get(value);
42 if (ref) {
43 if (!ref.anchor)
44 ref.anchor = onAnchor(value);
45 return new Alias.Alias(ref.anchor);
46 }
47 else {
48 ref = { anchor: null, node: null };
49 sourceObjects.set(value, ref);
50 }
51 }
52 if (tagName?.startsWith('!!'))
53 tagName = defaultTagPrefix + tagName.slice(2);
54 let tagObj = findTagObject(value, tagName, schema.tags);
55 if (!tagObj) {
56 if (value && typeof value.toJSON === 'function') {
57 // eslint-disable-next-line @typescript-eslint/no-unsafe-call
58 value = value.toJSON();
59 }
60 if (!value || typeof value !== 'object') {
61 const node = new Scalar.Scalar(value);
62 if (ref)
63 ref.node = node;
64 return node;
65 }
66 tagObj =
67 value instanceof Map
68 ? schema[identity.MAP]
69 : Symbol.iterator in Object(value)
70 ? schema[identity.SEQ]
71 : schema[identity.MAP];
72 }
73 if (onTagObj) {
74 onTagObj(tagObj);
75 delete ctx.onTagObj;
76 }
77 const node = tagObj?.createNode
78 ? tagObj.createNode(ctx.schema, value, ctx)
79 : typeof tagObj?.nodeClass?.from === 'function'
80 ? tagObj.nodeClass.from(ctx.schema, value, ctx)
81 : new Scalar.Scalar(value);
82 if (tagName)
83 node.tag = tagName;
84 else if (!tagObj.default)
85 node.tag = tagObj.tag;
86 if (ref)
87 ref.node = node;
88 return node;
89}
90
91exports.createNode = createNode;