compose-node.js 3.5 KB

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