UNPKG

4.33 kBJavaScriptView Raw
1'use strict';
2
3var anchors = require('../doc/anchors.js');
4var identity = require('../nodes/identity.js');
5var stringifyComment = require('./stringifyComment.js');
6var stringifyString = require('./stringifyString.js');
7
8function createStringifyContext(doc, options) {
9 const opt = Object.assign({
10 blockQuote: true,
11 commentString: stringifyComment.stringifyComment,
12 defaultKeyType: null,
13 defaultStringType: 'PLAIN',
14 directives: null,
15 doubleQuotedAsJSON: false,
16 doubleQuotedMinMultiLineLength: 40,
17 falseStr: 'false',
18 flowCollectionPadding: true,
19 indentSeq: true,
20 lineWidth: 80,
21 minContentWidth: 20,
22 nullStr: 'null',
23 simpleKeys: false,
24 singleQuote: null,
25 trueStr: 'true',
26 verifyAliasOrder: true
27 }, doc.schema.toStringOptions, options);
28 let inFlow;
29 switch (opt.collectionStyle) {
30 case 'block':
31 inFlow = false;
32 break;
33 case 'flow':
34 inFlow = true;
35 break;
36 default:
37 inFlow = null;
38 }
39 return {
40 anchors: new Set(),
41 doc,
42 flowCollectionPadding: opt.flowCollectionPadding ? ' ' : '',
43 indent: '',
44 indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ',
45 inFlow,
46 options: opt
47 };
48}
49function getTagObject(tags, item) {
50 if (item.tag) {
51 const match = tags.filter(t => t.tag === item.tag);
52 if (match.length > 0)
53 return match.find(t => t.format === item.format) ?? match[0];
54 }
55 let tagObj = undefined;
56 let obj;
57 if (identity.isScalar(item)) {
58 obj = item.value;
59 const match = tags.filter(t => t.identify?.(obj));
60 tagObj =
61 match.find(t => t.format === item.format) ?? match.find(t => !t.format);
62 }
63 else {
64 obj = item;
65 tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
66 }
67 if (!tagObj) {
68 const name = obj?.constructor?.name ?? typeof obj;
69 throw new Error(`Tag not resolved for ${name} value`);
70 }
71 return tagObj;
72}
73// needs to be called before value stringifier to allow for circular anchor refs
74function stringifyProps(node, tagObj, { anchors: anchors$1, doc }) {
75 if (!doc.directives)
76 return '';
77 const props = [];
78 const anchor = (identity.isScalar(node) || identity.isCollection(node)) && node.anchor;
79 if (anchor && anchors.anchorIsValid(anchor)) {
80 anchors$1.add(anchor);
81 props.push(`&${anchor}`);
82 }
83 const tag = node.tag ? node.tag : tagObj.default ? null : tagObj.tag;
84 if (tag)
85 props.push(doc.directives.tagString(tag));
86 return props.join(' ');
87}
88function stringify(item, ctx, onComment, onChompKeep) {
89 if (identity.isPair(item))
90 return item.toString(ctx, onComment, onChompKeep);
91 if (identity.isAlias(item)) {
92 if (ctx.doc.directives)
93 return item.toString(ctx);
94 if (ctx.resolvedAliases?.has(item)) {
95 throw new TypeError(`Cannot stringify circular structure without alias nodes`);
96 }
97 else {
98 if (ctx.resolvedAliases)
99 ctx.resolvedAliases.add(item);
100 else
101 ctx.resolvedAliases = new Set([item]);
102 item = item.resolve(ctx.doc);
103 }
104 }
105 let tagObj = undefined;
106 const node = identity.isNode(item)
107 ? item
108 : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
109 if (!tagObj)
110 tagObj = getTagObject(ctx.doc.schema.tags, node);
111 const props = stringifyProps(node, tagObj, ctx);
112 if (props.length > 0)
113 ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
114 const str = typeof tagObj.stringify === 'function'
115 ? tagObj.stringify(node, ctx, onComment, onChompKeep)
116 : identity.isScalar(node)
117 ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep)
118 : node.toString(ctx, onComment, onChompKeep);
119 if (!props)
120 return str;
121 return identity.isScalar(node) || str[0] === '{' || str[0] === '['
122 ? `${props} ${str}`
123 : `${props}\n${ctx.indent}${str}`;
124}
125
126exports.createStringifyContext = createStringifyContext;
127exports.stringify = stringify;