You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.9 KiB
119 lines
3.9 KiB
'use strict'; |
|
|
|
var stringifyCollection = require('../stringify/stringifyCollection.js'); |
|
var addPairToJSMap = require('./addPairToJSMap.js'); |
|
var Collection = require('./Collection.js'); |
|
var Node = require('./Node.js'); |
|
var Pair = require('./Pair.js'); |
|
var Scalar = require('./Scalar.js'); |
|
|
|
function findPair(items, key) { |
|
const k = Node.isScalar(key) ? key.value : key; |
|
for (const it of items) { |
|
if (Node.isPair(it)) { |
|
if (it.key === key || it.key === k) |
|
return it; |
|
if (Node.isScalar(it.key) && it.key.value === k) |
|
return it; |
|
} |
|
} |
|
return undefined; |
|
} |
|
class YAMLMap extends Collection.Collection { |
|
constructor(schema) { |
|
super(Node.MAP, schema); |
|
this.items = []; |
|
} |
|
static get tagName() { |
|
return 'tag:yaml.org,2002:map'; |
|
} |
|
/** |
|
* Adds a value to the collection. |
|
* |
|
* @param overwrite - If not set `true`, using a key that is already in the |
|
* collection will throw. Otherwise, overwrites the previous value. |
|
*/ |
|
add(pair, overwrite) { |
|
let _pair; |
|
if (Node.isPair(pair)) |
|
_pair = pair; |
|
else if (!pair || typeof pair !== 'object' || !('key' in pair)) { |
|
// In TypeScript, this never happens. |
|
_pair = new Pair.Pair(pair, pair?.value); |
|
} |
|
else |
|
_pair = new Pair.Pair(pair.key, pair.value); |
|
const prev = findPair(this.items, _pair.key); |
|
const sortEntries = this.schema?.sortMapEntries; |
|
if (prev) { |
|
if (!overwrite) |
|
throw new Error(`Key ${_pair.key} already set`); |
|
// For scalars, keep the old node & its comments and anchors |
|
if (Node.isScalar(prev.value) && Scalar.isScalarValue(_pair.value)) |
|
prev.value.value = _pair.value; |
|
else |
|
prev.value = _pair.value; |
|
} |
|
else if (sortEntries) { |
|
const i = this.items.findIndex(item => sortEntries(_pair, item) < 0); |
|
if (i === -1) |
|
this.items.push(_pair); |
|
else |
|
this.items.splice(i, 0, _pair); |
|
} |
|
else { |
|
this.items.push(_pair); |
|
} |
|
} |
|
delete(key) { |
|
const it = findPair(this.items, key); |
|
if (!it) |
|
return false; |
|
const del = this.items.splice(this.items.indexOf(it), 1); |
|
return del.length > 0; |
|
} |
|
get(key, keepScalar) { |
|
const it = findPair(this.items, key); |
|
const node = it?.value; |
|
return (!keepScalar && Node.isScalar(node) ? node.value : node) ?? undefined; |
|
} |
|
has(key) { |
|
return !!findPair(this.items, key); |
|
} |
|
set(key, value) { |
|
this.add(new Pair.Pair(key, value), true); |
|
} |
|
/** |
|
* @param ctx - Conversion context, originally set in Document#toJS() |
|
* @param {Class} Type - If set, forces the returned collection type |
|
* @returns Instance of Type, Map, or Object |
|
*/ |
|
toJSON(_, ctx, Type) { |
|
const map = Type ? new Type() : ctx?.mapAsMap ? new Map() : {}; |
|
if (ctx?.onCreate) |
|
ctx.onCreate(map); |
|
for (const item of this.items) |
|
addPairToJSMap.addPairToJSMap(ctx, map, item); |
|
return map; |
|
} |
|
toString(ctx, onComment, onChompKeep) { |
|
if (!ctx) |
|
return JSON.stringify(this); |
|
for (const item of this.items) { |
|
if (!Node.isPair(item)) |
|
throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`); |
|
} |
|
if (!ctx.allNullValues && this.hasAllNullValues(false)) |
|
ctx = Object.assign({}, ctx, { allNullValues: true }); |
|
return stringifyCollection.stringifyCollection(this, ctx, { |
|
blockItemPrefix: '', |
|
flowChars: { start: '{', end: '}' }, |
|
itemIndent: ctx.indent || '', |
|
onChompKeep, |
|
onComment |
|
}); |
|
} |
|
} |
|
|
|
exports.YAMLMap = YAMLMap; |
|
exports.findPair = findPair;
|
|
|