UNPKG

5.11 kBJavaScriptView Raw
1'use strict';
2
3var stringifyCollection = require('../stringify/stringifyCollection.js');
4var addPairToJSMap = require('./addPairToJSMap.js');
5var Collection = require('./Collection.js');
6var identity = require('./identity.js');
7var Pair = require('./Pair.js');
8var Scalar = require('./Scalar.js');
9
10function findPair(items, key) {
11 const k = identity.isScalar(key) ? key.value : key;
12 for (const it of items) {
13 if (identity.isPair(it)) {
14 if (it.key === key || it.key === k)
15 return it;
16 if (identity.isScalar(it.key) && it.key.value === k)
17 return it;
18 }
19 }
20 return undefined;
21}
22class YAMLMap extends Collection.Collection {
23 static get tagName() {
24 return 'tag:yaml.org,2002:map';
25 }
26 constructor(schema) {
27 super(identity.MAP, schema);
28 this.items = [];
29 }
30 /**
31 * A generic collection parsing method that can be extended
32 * to other node classes that inherit from YAMLMap
33 */
34 static from(schema, obj, ctx) {
35 const { keepUndefined, replacer } = ctx;
36 const map = new this(schema);
37 const add = (key, value) => {
38 if (typeof replacer === 'function')
39 value = replacer.call(obj, key, value);
40 else if (Array.isArray(replacer) && !replacer.includes(key))
41 return;
42 if (value !== undefined || keepUndefined)
43 map.items.push(Pair.createPair(key, value, ctx));
44 };
45 if (obj instanceof Map) {
46 for (const [key, value] of obj)
47 add(key, value);
48 }
49 else if (obj && typeof obj === 'object') {
50 for (const key of Object.keys(obj))
51 add(key, obj[key]);
52 }
53 if (typeof schema.sortMapEntries === 'function') {
54 map.items.sort(schema.sortMapEntries);
55 }
56 return map;
57 }
58 /**
59 * Adds a value to the collection.
60 *
61 * @param overwrite - If not set `true`, using a key that is already in the
62 * collection will throw. Otherwise, overwrites the previous value.
63 */
64 add(pair, overwrite) {
65 let _pair;
66 if (identity.isPair(pair))
67 _pair = pair;
68 else if (!pair || typeof pair !== 'object' || !('key' in pair)) {
69 // In TypeScript, this never happens.
70 _pair = new Pair.Pair(pair, pair?.value);
71 }
72 else
73 _pair = new Pair.Pair(pair.key, pair.value);
74 const prev = findPair(this.items, _pair.key);
75 const sortEntries = this.schema?.sortMapEntries;
76 if (prev) {
77 if (!overwrite)
78 throw new Error(`Key ${_pair.key} already set`);
79 // For scalars, keep the old node & its comments and anchors
80 if (identity.isScalar(prev.value) && Scalar.isScalarValue(_pair.value))
81 prev.value.value = _pair.value;
82 else
83 prev.value = _pair.value;
84 }
85 else if (sortEntries) {
86 const i = this.items.findIndex(item => sortEntries(_pair, item) < 0);
87 if (i === -1)
88 this.items.push(_pair);
89 else
90 this.items.splice(i, 0, _pair);
91 }
92 else {
93 this.items.push(_pair);
94 }
95 }
96 delete(key) {
97 const it = findPair(this.items, key);
98 if (!it)
99 return false;
100 const del = this.items.splice(this.items.indexOf(it), 1);
101 return del.length > 0;
102 }
103 get(key, keepScalar) {
104 const it = findPair(this.items, key);
105 const node = it?.value;
106 return (!keepScalar && identity.isScalar(node) ? node.value : node) ?? undefined;
107 }
108 has(key) {
109 return !!findPair(this.items, key);
110 }
111 set(key, value) {
112 this.add(new Pair.Pair(key, value), true);
113 }
114 /**
115 * @param ctx - Conversion context, originally set in Document#toJS()
116 * @param {Class} Type - If set, forces the returned collection type
117 * @returns Instance of Type, Map, or Object
118 */
119 toJSON(_, ctx, Type) {
120 const map = Type ? new Type() : ctx?.mapAsMap ? new Map() : {};
121 if (ctx?.onCreate)
122 ctx.onCreate(map);
123 for (const item of this.items)
124 addPairToJSMap.addPairToJSMap(ctx, map, item);
125 return map;
126 }
127 toString(ctx, onComment, onChompKeep) {
128 if (!ctx)
129 return JSON.stringify(this);
130 for (const item of this.items) {
131 if (!identity.isPair(item))
132 throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
133 }
134 if (!ctx.allNullValues && this.hasAllNullValues(false))
135 ctx = Object.assign({}, ctx, { allNullValues: true });
136 return stringifyCollection.stringifyCollection(this, ctx, {
137 blockItemPrefix: '',
138 flowChars: { start: '{', end: '}' },
139 itemIndent: ctx.indent || '',
140 onChompKeep,
141 onComment
142 });
143 }
144}
145
146exports.YAMLMap = YAMLMap;
147exports.findPair = findPair;