set.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { isMap, isPair, isScalar } from '../../nodes/identity.js';
  2. import { Pair, createPair } from '../../nodes/Pair.js';
  3. import { YAMLMap, findPair } from '../../nodes/YAMLMap.js';
  4. class YAMLSet extends YAMLMap {
  5. constructor(schema) {
  6. super(schema);
  7. this.tag = YAMLSet.tag;
  8. }
  9. add(key) {
  10. let pair;
  11. if (isPair(key))
  12. pair = key;
  13. else if (key &&
  14. typeof key === 'object' &&
  15. 'key' in key &&
  16. 'value' in key &&
  17. key.value === null)
  18. pair = new Pair(key.key, null);
  19. else
  20. pair = new Pair(key, null);
  21. const prev = findPair(this.items, pair.key);
  22. if (!prev)
  23. this.items.push(pair);
  24. }
  25. /**
  26. * If `keepPair` is `true`, returns the Pair matching `key`.
  27. * Otherwise, returns the value of that Pair's key.
  28. */
  29. get(key, keepPair) {
  30. const pair = findPair(this.items, key);
  31. return !keepPair && isPair(pair)
  32. ? isScalar(pair.key)
  33. ? pair.key.value
  34. : pair.key
  35. : pair;
  36. }
  37. set(key, value) {
  38. if (typeof value !== 'boolean')
  39. throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
  40. const prev = findPair(this.items, key);
  41. if (prev && !value) {
  42. this.items.splice(this.items.indexOf(prev), 1);
  43. }
  44. else if (!prev && value) {
  45. this.items.push(new Pair(key));
  46. }
  47. }
  48. toJSON(_, ctx) {
  49. return super.toJSON(_, ctx, Set);
  50. }
  51. toString(ctx, onComment, onChompKeep) {
  52. if (!ctx)
  53. return JSON.stringify(this);
  54. if (this.hasAllNullValues(true))
  55. return super.toString(Object.assign({}, ctx, { allNullValues: true }), onComment, onChompKeep);
  56. else
  57. throw new Error('Set items must all have null values');
  58. }
  59. static from(schema, iterable, ctx) {
  60. const { replacer } = ctx;
  61. const set = new this(schema);
  62. if (iterable && Symbol.iterator in Object(iterable))
  63. for (let value of iterable) {
  64. if (typeof replacer === 'function')
  65. value = replacer.call(iterable, value, value);
  66. set.items.push(createPair(value, null, ctx));
  67. }
  68. return set;
  69. }
  70. }
  71. YAMLSet.tag = 'tag:yaml.org,2002:set';
  72. const set = {
  73. collection: 'map',
  74. identify: value => value instanceof Set,
  75. nodeClass: YAMLSet,
  76. default: false,
  77. tag: 'tag:yaml.org,2002:set',
  78. createNode: (schema, iterable, ctx) => YAMLSet.from(schema, iterable, ctx),
  79. resolve(map, onError) {
  80. if (isMap(map)) {
  81. if (map.hasAllNullValues(true))
  82. return Object.assign(new YAMLSet(), map);
  83. else
  84. onError('Set items must all have null values');
  85. }
  86. else
  87. onError('Expected a mapping for this tag');
  88. return map;
  89. }
  90. };
  91. export { YAMLSet, set };