Няма описание

YAMLMap.js 3.8KB

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