compose-node.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. 'use strict';
  2. var Alias = require('../nodes/Alias.js');
  3. var identity = require('../nodes/identity.js');
  4. var composeCollection = require('./compose-collection.js');
  5. var composeScalar = require('./compose-scalar.js');
  6. var resolveEnd = require('./resolve-end.js');
  7. var utilEmptyScalarPosition = require('./util-empty-scalar-position.js');
  8. const CN = { composeNode, composeEmptyNode };
  9. function composeNode(ctx, token, props, onError) {
  10. const atKey = ctx.atKey;
  11. const { spaceBefore, comment, anchor, tag } = props;
  12. let node;
  13. let isSrcToken = true;
  14. switch (token.type) {
  15. case 'alias':
  16. node = composeAlias(ctx, token, onError);
  17. if (anchor || tag)
  18. onError(token, 'ALIAS_PROPS', 'An alias node must not specify any properties');
  19. break;
  20. case 'scalar':
  21. case 'single-quoted-scalar':
  22. case 'double-quoted-scalar':
  23. case 'block-scalar':
  24. node = composeScalar.composeScalar(ctx, token, tag, onError);
  25. if (anchor)
  26. node.anchor = anchor.source.substring(1);
  27. break;
  28. case 'block-map':
  29. case 'block-seq':
  30. case 'flow-collection':
  31. node = composeCollection.composeCollection(CN, ctx, token, props, onError);
  32. if (anchor)
  33. node.anchor = anchor.source.substring(1);
  34. break;
  35. default: {
  36. const message = token.type === 'error'
  37. ? token.message
  38. : `Unsupported token (type: ${token.type})`;
  39. onError(token, 'UNEXPECTED_TOKEN', message);
  40. node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
  41. isSrcToken = false;
  42. }
  43. }
  44. if (anchor && node.anchor === '')
  45. onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
  46. if (atKey &&
  47. ctx.options.stringKeys &&
  48. (!identity.isScalar(node) ||
  49. typeof node.value !== 'string' ||
  50. (node.tag && node.tag !== 'tag:yaml.org,2002:str'))) {
  51. const msg = 'With stringKeys, all keys must be strings';
  52. onError(tag ?? token, 'NON_STRING_KEY', msg);
  53. }
  54. if (spaceBefore)
  55. node.spaceBefore = true;
  56. if (comment) {
  57. if (token.type === 'scalar' && token.source === '')
  58. node.comment = comment;
  59. else
  60. node.commentBefore = comment;
  61. }
  62. // @ts-expect-error Type checking misses meaning of isSrcToken
  63. if (ctx.options.keepSourceTokens && isSrcToken)
  64. node.srcToken = token;
  65. return node;
  66. }
  67. function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor, tag, end }, onError) {
  68. const token = {
  69. type: 'scalar',
  70. offset: utilEmptyScalarPosition.emptyScalarPosition(offset, before, pos),
  71. indent: -1,
  72. source: ''
  73. };
  74. const node = composeScalar.composeScalar(ctx, token, tag, onError);
  75. if (anchor) {
  76. node.anchor = anchor.source.substring(1);
  77. if (node.anchor === '')
  78. onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
  79. }
  80. if (spaceBefore)
  81. node.spaceBefore = true;
  82. if (comment) {
  83. node.comment = comment;
  84. node.range[2] = end;
  85. }
  86. return node;
  87. }
  88. function composeAlias({ options }, { offset, source, end }, onError) {
  89. const alias = new Alias.Alias(source.substring(1));
  90. if (alias.source === '')
  91. onError(offset, 'BAD_ALIAS', 'Alias cannot be an empty string');
  92. if (alias.source.endsWith(':'))
  93. onError(offset + source.length - 1, 'BAD_ALIAS', 'Alias ending in : is ambiguous', true);
  94. const valueEnd = offset + source.length;
  95. const re = resolveEnd.resolveEnd(end, valueEnd, options.strict, onError);
  96. alias.range = [offset, valueEnd, re.offset];
  97. if (re.comment)
  98. alias.comment = re.comment;
  99. return alias;
  100. }
  101. exports.composeEmptyNode = composeEmptyNode;
  102. exports.composeNode = composeNode;