YAMLSeq.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. var createNode = require('../doc/createNode.js');
  3. var stringifyCollection = require('../stringify/stringifyCollection.js');
  4. var Collection = require('./Collection.js');
  5. var identity = require('./identity.js');
  6. var Scalar = require('./Scalar.js');
  7. var toJS = require('./toJS.js');
  8. class YAMLSeq extends Collection.Collection {
  9. static get tagName() {
  10. return 'tag:yaml.org,2002:seq';
  11. }
  12. constructor(schema) {
  13. super(identity.SEQ, schema);
  14. this.items = [];
  15. }
  16. add(value) {
  17. this.items.push(value);
  18. }
  19. /**
  20. * Removes a value from the collection.
  21. *
  22. * `key` must contain a representation of an integer for this to succeed.
  23. * It may be wrapped in a `Scalar`.
  24. *
  25. * @returns `true` if the item was found and removed.
  26. */
  27. delete(key) {
  28. const idx = asItemIndex(key);
  29. if (typeof idx !== 'number')
  30. return false;
  31. const del = this.items.splice(idx, 1);
  32. return del.length > 0;
  33. }
  34. get(key, keepScalar) {
  35. const idx = asItemIndex(key);
  36. if (typeof idx !== 'number')
  37. return undefined;
  38. const it = this.items[idx];
  39. return !keepScalar && identity.isScalar(it) ? it.value : it;
  40. }
  41. /**
  42. * Checks if the collection includes a value with the key `key`.
  43. *
  44. * `key` must contain a representation of an integer for this to succeed.
  45. * It may be wrapped in a `Scalar`.
  46. */
  47. has(key) {
  48. const idx = asItemIndex(key);
  49. return typeof idx === 'number' && idx < this.items.length;
  50. }
  51. /**
  52. * Sets a value in this collection. For `!!set`, `value` needs to be a
  53. * boolean to add/remove the item from the set.
  54. *
  55. * If `key` does not contain a representation of an integer, this will throw.
  56. * It may be wrapped in a `Scalar`.
  57. */
  58. set(key, value) {
  59. const idx = asItemIndex(key);
  60. if (typeof idx !== 'number')
  61. throw new Error(`Expected a valid index, not ${key}.`);
  62. const prev = this.items[idx];
  63. if (identity.isScalar(prev) && Scalar.isScalarValue(value))
  64. prev.value = value;
  65. else
  66. this.items[idx] = value;
  67. }
  68. toJSON(_, ctx) {
  69. const seq = [];
  70. if (ctx?.onCreate)
  71. ctx.onCreate(seq);
  72. let i = 0;
  73. for (const item of this.items)
  74. seq.push(toJS.toJS(item, String(i++), ctx));
  75. return seq;
  76. }
  77. toString(ctx, onComment, onChompKeep) {
  78. if (!ctx)
  79. return JSON.stringify(this);
  80. return stringifyCollection.stringifyCollection(this, ctx, {
  81. blockItemPrefix: '- ',
  82. flowChars: { start: '[', end: ']' },
  83. itemIndent: (ctx.indent || '') + ' ',
  84. onChompKeep,
  85. onComment
  86. });
  87. }
  88. static from(schema, obj, ctx) {
  89. const { replacer } = ctx;
  90. const seq = new this(schema);
  91. if (obj && Symbol.iterator in Object(obj)) {
  92. let i = 0;
  93. for (let it of obj) {
  94. if (typeof replacer === 'function') {
  95. const key = obj instanceof Set ? it : String(i++);
  96. it = replacer.call(obj, key, it);
  97. }
  98. seq.items.push(createNode.createNode(it, undefined, ctx));
  99. }
  100. }
  101. return seq;
  102. }
  103. }
  104. function asItemIndex(key) {
  105. let idx = identity.isScalar(key) ? key.value : key;
  106. if (idx && typeof idx === 'string')
  107. idx = Number(idx);
  108. return typeof idx === 'number' && Number.isInteger(idx) && idx >= 0
  109. ? idx
  110. : null;
  111. }
  112. exports.YAMLSeq = YAMLSeq;