| import { anchorIsValid } from '../doc/anchors.js'; | |
| import { isPair, isAlias, isNode, isScalar, isCollection } from '../nodes/identity.js'; | |
| import { stringifyComment } from './stringifyComment.js'; | |
| import { stringifyString } from './stringifyString.js'; | |
| function createStringifyContext(doc, options) { | |
| const opt = Object.assign({ | |
| blockQuote: true, | |
| commentString: stringifyComment, | |
| defaultKeyType: null, | |
| defaultStringType: 'PLAIN', | |
| directives: null, | |
| doubleQuotedAsJSON: false, | |
| doubleQuotedMinMultiLineLength: 40, | |
| falseStr: 'false', | |
| flowCollectionPadding: true, | |
| indentSeq: true, | |
| lineWidth: 80, | |
| minContentWidth: 20, | |
| nullStr: 'null', | |
| simpleKeys: false, | |
| singleQuote: null, | |
| trailingComma: false, | |
| trueStr: 'true', | |
| verifyAliasOrder: true | |
| }, doc.schema.toStringOptions, options); | |
| let inFlow; | |
| switch (opt.collectionStyle) { | |
| case 'block': | |
| inFlow = false; | |
| break; | |
| case 'flow': | |
| inFlow = true; | |
| break; | |
| default: | |
| inFlow = null; | |
| } | |
| return { | |
| anchors: new Set(), | |
| doc, | |
| flowCollectionPadding: opt.flowCollectionPadding ? ' ' : '', | |
| indent: '', | |
| indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ', | |
| inFlow, | |
| options: opt | |
| }; | |
| } | |
| function getTagObject(tags, item) { | |
| if (item.tag) { | |
| const match = tags.filter(t => t.tag === item.tag); | |
| if (match.length > 0) | |
| return match.find(t => t.format === item.format) ?? match[0]; | |
| } | |
| let tagObj = undefined; | |
| let obj; | |
| if (isScalar(item)) { | |
| obj = item.value; | |
| let match = tags.filter(t => t.identify?.(obj)); | |
| if (match.length > 1) { | |
| const testMatch = match.filter(t => t.test); | |
| if (testMatch.length > 0) | |
| match = testMatch; | |
| } | |
| tagObj = | |
| match.find(t => t.format === item.format) ?? match.find(t => !t.format); | |
| } | |
| else { | |
| obj = item; | |
| tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass); | |
| } | |
| if (!tagObj) { | |
| const name = obj?.constructor?.name ?? (obj === null ? 'null' : typeof obj); | |
| throw new Error(`Tag not resolved for ${name} value`); | |
| } | |
| return tagObj; | |
| } | |
| // needs to be called before value stringifier to allow for circular anchor refs | |
| function stringifyProps(node, tagObj, { anchors, doc }) { | |
| if (!doc.directives) | |
| return ''; | |
| const props = []; | |
| const anchor = (isScalar(node) || isCollection(node)) && node.anchor; | |
| if (anchor && anchorIsValid(anchor)) { | |
| anchors.add(anchor); | |
| props.push(`&${anchor}`); | |
| } | |
| const tag = node.tag ?? (tagObj.default ? null : tagObj.tag); | |
| if (tag) | |
| props.push(doc.directives.tagString(tag)); | |
| return props.join(' '); | |
| } | |
| function stringify(item, ctx, onComment, onChompKeep) { | |
| if (isPair(item)) | |
| return item.toString(ctx, onComment, onChompKeep); | |
| if (isAlias(item)) { | |
| if (ctx.doc.directives) | |
| return item.toString(ctx); | |
| if (ctx.resolvedAliases?.has(item)) { | |
| throw new TypeError(`Cannot stringify circular structure without alias nodes`); | |
| } | |
| else { | |
| if (ctx.resolvedAliases) | |
| ctx.resolvedAliases.add(item); | |
| else | |
| ctx.resolvedAliases = new Set([item]); | |
| item = item.resolve(ctx.doc); | |
| } | |
| } | |
| let tagObj = undefined; | |
| const node = isNode(item) | |
| ? item | |
| : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) }); | |
| tagObj ?? (tagObj = getTagObject(ctx.doc.schema.tags, node)); | |
| const props = stringifyProps(node, tagObj, ctx); | |
| if (props.length > 0) | |
| ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1; | |
| const str = typeof tagObj.stringify === 'function' | |
| ? tagObj.stringify(node, ctx, onComment, onChompKeep) | |
| : isScalar(node) | |
| ? stringifyString(node, ctx, onComment, onChompKeep) | |
| : node.toString(ctx, onComment, onChompKeep); | |
| if (!props) | |
| return str; | |
| return isScalar(node) || str[0] === '{' || str[0] === '[' | |
| ? `${props} ${str}` | |
| : `${props}\n${ctx.indent}${str}`; | |
| } | |
| export { createStringifyContext, stringify }; | |
Xet Storage Details
- Size:
- 4.4 kB
- Xet hash:
- 11576b2befc1f3fa36215081bb44014f044732abc8cfbe2b57d74810aa034cf7
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.