Socket
Socket
Sign inDemoInstall

yaml

Package Overview
Dependencies
0
Maintainers
1
Versions
88
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-9 to 2.0.0-10

browser/dist/compose/util-flow-indent-check.js

1

browser/dist/compose/compose-doc.js

@@ -10,2 +10,3 @@ import { Document } from '../doc/Document.js';

const ctx = {
atRoot: true,
directives: doc.directives,

@@ -12,0 +13,0 @@ options: doc.options,

24

browser/dist/compose/compose-scalar.js

@@ -1,2 +0,2 @@

import { isScalar, SCALAR } from '../nodes/Node.js';
import { SCALAR, isScalar } from '../nodes/Node.js';
import { Scalar } from '../nodes/Scalar.js';

@@ -15,3 +15,5 @@ import { resolveBlockScalar } from './resolve-block-scalar.js';

? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
: findScalarTagByTest(ctx.schema, value, token.type === 'scalar');
: token.type === 'scalar'
? findScalarTagByTest(ctx, value, token, onError)
: ctx.schema[SCALAR];
let scalar;

@@ -65,13 +67,17 @@ try {

}
function findScalarTagByTest(schema, value, apply) {
var _a;
if (apply) {
for (const tag of schema.tags) {
if (tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)))
return tag;
function findScalarTagByTest({ directives, schema }, value, token, onError) {
const tag = schema.tags.find(tag => { var _a; return tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)); }) || schema[SCALAR];
if (schema.compat) {
const compat = schema.compat.find(tag => { var _a; return tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)); }) ||
schema[SCALAR];
if (tag.tag !== compat.tag) {
const ts = directives.tagString(tag.tag);
const cs = directives.tagString(compat.tag);
const msg = `Value may be parsed as either ${ts} or ${cs}`;
onError(token, 'TAG_RESOLVE_FAILED', msg, true);
}
}
return schema[SCALAR];
return tag;
}
export { composeScalar };

@@ -5,2 +5,3 @@ import { Pair } from '../nodes/Pair.js';

import { containsNewline } from './util-contains-newline.js';
import { flowIndentCheck } from './util-flow-indent-check.js';
import { mapIncludes } from './util-map-includes.js';

@@ -12,2 +13,4 @@

const map = new YAMLMap(ctx.schema);
if (ctx.atRoot)
ctx.atRoot = false;
let offset = bm.offset;

@@ -53,2 +56,4 @@ for (const collItem of bm.items) {

: composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
if (ctx.schema.compat)
flowIndentCheck(bm.indent, key, onError);
if (mapIncludes(ctx, map.items, keyNode))

@@ -77,2 +82,4 @@ onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');

: composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
if (ctx.schema.compat)
flowIndentCheck(bm.indent, value, onError);
offset = valueNode.range[2];

@@ -79,0 +86,0 @@ const pair = new Pair(keyNode, valueNode);

import { YAMLSeq } from '../nodes/YAMLSeq.js';
import { resolveProps } from './resolve-props.js';
import { flowIndentCheck } from './util-flow-indent-check.js';
function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
const seq = new YAMLSeq(ctx.schema);
if (ctx.atRoot)
ctx.atRoot = false;
let offset = bs.offset;

@@ -33,2 +36,4 @@ for (const { start, value } of bs.items) {

: composeEmptyNode(ctx, offset, start, null, props, onError);
if (ctx.schema.compat)
flowIndentCheck(bs.indent, value, onError);
offset = node.range[2];

@@ -35,0 +40,0 @@ seq.items.push(node);

@@ -19,3 +19,6 @@ import { isPair } from '../nodes/Node.js';

coll.flow = true;
let offset = fc.offset;
const atRoot = ctx.atRoot;
if (atRoot)
ctx.atRoot = false;
let offset = fc.offset + fc.start.source.length;
for (let i = 0; i < fc.items.length; ++i) {

@@ -44,2 +47,3 @@ const collItem = fc.items[i];

}
offset = props.end;
continue;

@@ -174,3 +178,7 @@ }

else {
onError(offset + 1, 'MISSING_CHAR', `Expected ${fcName} to end with ${expectedEnd}`);
const name = fcName[0].toUpperCase() + fcName.substring(1);
const msg = atRoot
? `${name} must end with a ${expectedEnd}`
: `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
if (ce && ce.source.length !== 1)

@@ -177,0 +185,0 @@ ee.unshift(ce);

@@ -84,2 +84,4 @@ function resolveProps(tokens, { flow, indicator, next, offset, onError, startOnNewline }) {

onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
if (found)
onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow || 'collection'}`);
found = token;

@@ -86,0 +88,0 @@ atNewline = false;

@@ -65,3 +65,4 @@ import { Alias } from '../nodes/Alias.js';

copy.options = Object.assign({}, this.options);
copy.directives = this.directives.clone();
if (this.directives)
copy.directives = this.directives.clone();
copy.schema = this.schema.clone();

@@ -233,22 +234,43 @@ copy.contents = isNode(this.contents)

* Change the YAML version and schema used by the document.
* A `null` version disables support for directives, explicit tags, anchors, and aliases.
* It also requires the `schema` option to be given as a `Schema` instance value.
*
* Overrides all previously set schema options
* Overrides all previously set schema options.
*/
setSchema(version, options) {
let _options;
switch (String(version)) {
setSchema(version, options = {}) {
if (typeof version === 'number')
version = String(version);
let opt;
switch (version) {
case '1.1':
this.directives.yaml.version = '1.1';
_options = Object.assign({ merge: true, resolveKnownTags: false, schema: 'yaml-1.1' }, options);
if (this.directives)
this.directives.yaml.version = '1.1';
else
this.directives = new Directives({ version: '1.1' });
opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
break;
case '1.2':
this.directives.yaml.version = '1.2';
_options = Object.assign({ merge: false, resolveKnownTags: true, schema: 'core' }, options);
if (this.directives)
this.directives.yaml.version = '1.2';
else
this.directives = new Directives({ version: '1.2' });
opt = { merge: false, resolveKnownTags: true, schema: 'core' };
break;
case null:
if (this.directives)
delete this.directives;
opt = null;
break;
default: {
const sv = JSON.stringify(version);
throw new Error(`Expected '1.1' or '1.2' as version, but found: ${sv}`);
throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
}
}
this.schema = new Schema(_options);
// Not using `instanceof Schema` to allow for duck typing
if (options.schema instanceof Object)
this.schema = options.schema;
else if (opt)
this.schema = new Schema(Object.assign(opt, options));
else
throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
}

@@ -255,0 +277,0 @@ // json & jsonArg are only used from toJSON()

@@ -107,3 +107,3 @@ import { stringifyCollection } from '../stringify/stringifyCollection.js';

return stringifyCollection(this, ctx, {
blockItem: n => n.str,
blockItemPrefix: '',
flowChars: { start: '{', end: '}' },

@@ -110,0 +110,0 @@ itemIndent: ctx.indent || '',

@@ -88,3 +88,3 @@ import { stringifyCollection } from '../stringify/stringifyCollection.js';

return stringifyCollection(this, ctx, {
blockItem: n => (n.comment ? n.str : `- ${n.str}`),
blockItemPrefix: '- ',
flowChars: { start: '[', end: ']' },

@@ -91,0 +91,0 @@ itemIndent: (ctx.indent || '') + ' ',

@@ -419,2 +419,3 @@ import { BOM, DOCUMENT, FLOW_END, SCALAR } from './cst.js';

if (this.flowKey || isEmpty(next) || next === ',') {
this.flowKey = false;
yield* this.pushCount(1);

@@ -627,2 +628,4 @@ yield* this.pushSpaces(true);

this.indentNext = this.indentValue + 1;
else if (this.flowKey)
this.flowKey = false;
return ((yield* this.pushCount(1)) +

@@ -629,0 +632,0 @@ (yield* this.pushSpaces(true)) +

@@ -206,2 +206,3 @@ import { tokenType } from './cst.js';

case 'doc-mode':
case 'flow-error-end':
return;

@@ -279,5 +280,10 @@ default:

const top = this.peek(1);
// For these, parent indent is needed instead of own
if (token.type === 'block-scalar' || token.type === 'flow-collection')
token.indent = 'indent' in top ? top.indent : -1;
if (token.type === 'block-scalar') {
// Block scalars use their parent rather than header indent
token.indent = 'indent' in top ? top.indent : 0;
}
else if (token.type === 'flow-collection' && top.type === 'document') {
// Ignore all indent for top-level flow collections
token.indent = 0;
}
if (token.type === 'flow-collection')

@@ -284,0 +290,0 @@ fixFlowSeqItems(token);

@@ -9,6 +9,4 @@ import { Composer } from './compose/composer.js';

function parseOptions(options) {
const prettyErrors = !options || options.prettyErrors !== false;
const lineCounter = (options && options.lineCounter) ||
(prettyErrors && new LineCounter()) ||
null;
const prettyErrors = options.prettyErrors !== false;
const lineCounter = options.lineCounter || (prettyErrors && new LineCounter()) || null;
return { lineCounter, prettyErrors };

@@ -15,0 +13,0 @@ }

@@ -23,3 +23,6 @@ import { Scalar } from '../../nodes/Scalar.js';

resolve: str => parseFloat(str),
stringify: ({ value }) => Number(value).toExponential()
stringify(node) {
const num = Number(node.value);
return isFinite(num) ? num.toExponential() : stringifyNumber(node);
}
};

@@ -26,0 +29,0 @@ const float = {

@@ -5,11 +5,17 @@ import { MAP, SCALAR, SEQ } from '../nodes/Node.js';

import { string } from './common/string.js';
import { coreKnownTags, getTags } from './tags.js';
import { getTags, coreKnownTags } from './tags.js';
const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
class Schema {
constructor({ customTags, merge, resolveKnownTags, schema, sortMapEntries }) {
constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
this.compat = Array.isArray(compat)
? getTags(compat, 'compat')
: compat
? getTags(null, compat)
: null;
this.merge = !!merge;
this.name = schema || 'core';
this.name = (typeof schema === 'string' && schema) || 'core';
this.knownTags = resolveKnownTags ? coreKnownTags : {};
this.tags = getTags(customTags, this.name);
this.toStringOptions = toStringDefaults || null;
Object.defineProperty(this, MAP, { value: map });

@@ -16,0 +22,0 @@ Object.defineProperty(this, SCALAR, { value: string });

@@ -17,9 +17,9 @@ import { map } from './common/map.js';

const schemas = {
core: schema,
failsafe: [map, seq, string],
json: schema$1,
yaml11: schema$2,
'yaml-1.1': schema$2
};
const schemas = new Map([
['core', schema],
['failsafe', [map, seq, string]],
['json', schema$1],
['yaml11', schema$2],
['yaml-1.1', schema$2]
]);
const tagsByName = {

@@ -52,3 +52,3 @@ binary,

function getTags(customTags, schemaName) {
let tags = schemas[schemaName];
let tags = schemas.get(schemaName);
if (!tags) {

@@ -58,3 +58,3 @@ if (Array.isArray(customTags))

else {
const keys = Object.keys(schemas)
const keys = Array.from(schemas.keys())
.filter(key => key !== 'yaml11')

@@ -61,0 +61,0 @@ .map(key => JSON.stringify(key))

@@ -23,3 +23,6 @@ import { Scalar } from '../../nodes/Scalar.js';

resolve: (str) => parseFloat(str.replace(/_/g, '')),
stringify: ({ value }) => Number(value).toExponential()
stringify(node) {
const num = Number(node.value);
return isFinite(num) ? num.toExponential() : stringifyNumber(node);
}
};

@@ -26,0 +29,0 @@ const float = {

import { anchorIsValid } from '../doc/anchors.js';
import { isPair, isAlias, isNode, isScalar, isCollection } from '../nodes/Node.js';
import { stringifyComment } from './stringifyComment.js';
import { stringifyString } from './stringifyString.js';
const createStringifyContext = (doc, options) => ({
anchors: new Set(),
doc,
indent: '',
indentStep: typeof options.indent === 'number' ? ' '.repeat(options.indent) : ' ',
options: Object.assign({
function createStringifyContext(doc, options) {
const opt = Object.assign({
blockQuote: true,
commentString: stringifyComment,
defaultKeyType: null,

@@ -26,4 +24,23 @@ defaultStringType: 'PLAIN',

verifyAliasOrder: true
}, options)
});
}, 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,
indent: '',
indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ',
inFlow,
options: opt
};
}
function getTagObject(tags, item) {

@@ -56,2 +73,4 @@ if (item.tag) {

function stringifyProps(node, tagObj, { anchors, doc }) {
if (!doc.directives)
return '';
const props = [];

@@ -63,15 +82,25 @@ const anchor = (isScalar(node) || isCollection(node)) && node.anchor;

}
if (node.tag) {
props.push(doc.directives.tagString(node.tag));
}
else if (!tagObj.default) {
props.push(doc.directives.tagString(tagObj.tag));
}
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) {
var _a;
if (isPair(item))
return item.toString(ctx, onComment, onChompKeep);
if (isAlias(item))
return item.toString(ctx);
if (isAlias(item)) {
if (ctx.doc.directives)
return item.toString(ctx);
if ((_a = ctx.resolvedAliases) === null || _a === void 0 ? void 0 : _a.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;

@@ -78,0 +107,0 @@ const node = isNode(item)

import { Collection } from '../nodes/Collection.js';
import { isNode, isPair } from '../nodes/Node.js';
import { stringify } from './stringify.js';
import { addComment, stringifyComment } from './stringifyComment.js';
import { lineComment, indentComment } from './stringifyComment.js';
function stringifyCollection({ comment, flow, items }, ctx, { blockItem, flowChars, itemIndent, onChompKeep, onComment }) {
const { indent, indentStep } = ctx;
const inFlow = flow || ctx.inFlow;
if (inFlow)
itemIndent += indentStep;
ctx = Object.assign({}, ctx, { indent: itemIndent, inFlow, type: null });
let singleLineOutput = true;
function stringifyCollection(collection, ctx, options) {
var _a;
const flow = (_a = ctx.inFlow) !== null && _a !== void 0 ? _a : collection.flow;
const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
return stringify(collection, ctx, options);
}
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
const { indent, options: { commentString } } = ctx;
const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
let chompKeep = false; // flag for the preceding node's status
const nodes = items.reduce((nodes, item, i) => {
const lines = [];
for (let i = 0; i < items.length; ++i) {
const item = items[i];
let comment = null;
if (isNode(item)) {
if (!chompKeep && item.spaceBefore)
nodes.push({ comment: true, str: '' });
let cb = item.commentBefore;
if (cb && chompKeep)
cb = cb.replace(/^\n+/, '');
if (cb) {
if (/^\n+$/.test(cb))
cb = cb.substring(1);
// This match will always succeed on a non-empty string
for (const line of cb.match(/^.*$/gm)) {
const str = line === ' ' ? '#' : line ? `#${line}` : '';
nodes.push({ comment: true, str });
}
}
if (item.comment) {
lines.push('');
addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
if (item.comment)
comment = item.comment;
singleLineOutput = false;
}
}

@@ -40,84 +31,123 @@ else if (isPair(item)) {

if (!chompKeep && ik.spaceBefore)
nodes.push({ comment: true, str: '' });
let cb = ik.commentBefore;
if (cb && chompKeep)
cb = cb.replace(/^\n+/, '');
if (cb) {
if (/^\n+$/.test(cb))
cb = cb.substring(1);
// This match will always succeed on a non-empty string
for (const line of cb.match(/^.*$/gm)) {
const str = line === ' ' ? '#' : line ? `#${line}` : '';
nodes.push({ comment: true, str });
}
}
if (ik.comment)
singleLineOutput = false;
lines.push('');
addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
}
if (inFlow) {
const iv = isNode(item.value) ? item.value : null;
if (iv) {
if (iv.comment)
comment = iv.comment;
if (iv.comment || iv.commentBefore)
singleLineOutput = false;
}
else if (item.value == null && ik && ik.comment) {
comment = ik.comment;
}
}
}
chompKeep = false;
let str = stringify(item, ctx, () => (comment = null), () => (chompKeep = true));
if (inFlow && i < items.length - 1)
str += ',';
str = addComment(str, itemIndent, comment);
if (chompKeep && (comment || inFlow))
let str = stringify(item, itemCtx, () => (comment = null), () => (chompKeep = true));
if (comment)
str += lineComment(str, itemIndent, commentString(comment));
if (chompKeep && comment)
chompKeep = false;
nodes.push({ comment: false, str });
return nodes;
}, []);
lines.push(blockItemPrefix + str);
}
let str;
if (nodes.length === 0) {
if (lines.length === 0) {
str = flowChars.start + flowChars.end;
}
else if (inFlow) {
const { start, end } = flowChars;
const strings = nodes.map(n => n.str);
let singleLineLength = 2;
for (const node of nodes) {
if (node.comment || node.str.includes('\n')) {
singleLineOutput = false;
break;
else {
str = lines[0];
for (let i = 1; i < lines.length; ++i) {
const line = lines[i];
str += line ? `\n${indent}${line}` : '\n';
}
}
if (comment) {
str += '\n' + indentComment(commentString(comment), indent);
if (onComment)
onComment();
}
else if (chompKeep && onChompKeep)
onChompKeep();
return str;
}
function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemIndent, onComment }) {
const { indent, indentStep, options: { commentString } } = ctx;
itemIndent += indentStep;
const itemCtx = Object.assign({}, ctx, {
indent: itemIndent,
inFlow: true,
type: null
});
let reqNewline = false;
let linesAtValue = 0;
const lines = [];
for (let i = 0; i < items.length; ++i) {
const item = items[i];
let comment = null;
if (isNode(item)) {
if (item.spaceBefore)
lines.push('');
addCommentBefore(ctx, lines, item.commentBefore, false);
if (item.comment)
comment = item.comment;
}
else if (isPair(item)) {
const ik = isNode(item.key) ? item.key : null;
if (ik) {
if (ik.spaceBefore)
lines.push('');
addCommentBefore(ctx, lines, ik.commentBefore, false);
if (ik.comment)
reqNewline = true;
}
singleLineLength += node.str.length + 2;
const iv = isNode(item.value) ? item.value : null;
if (iv) {
if (iv.comment)
comment = iv.comment;
if (iv.commentBefore)
reqNewline = true;
}
else if (item.value == null && ik && ik.comment) {
comment = ik.comment;
}
}
if (!singleLineOutput ||
singleLineLength > Collection.maxFlowStringSingleLineLength) {
if (comment)
reqNewline = true;
let str = stringify(item, itemCtx, () => (comment = null));
if (i < items.length - 1)
str += ',';
if (comment)
str += lineComment(str, itemIndent, commentString(comment));
if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
reqNewline = true;
lines.push(str);
linesAtValue = lines.length;
}
let str;
const { start, end } = flowChars;
if (lines.length === 0) {
str = start + end;
}
else {
if (!reqNewline) {
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
reqNewline = len > Collection.maxFlowStringSingleLineLength;
}
if (reqNewline) {
str = start;
for (const s of strings) {
str += s ? `\n${indentStep}${indent}${s}` : '\n';
}
for (const line of lines)
str += line ? `\n${indentStep}${indent}${line}` : '\n';
str += `\n${indent}${end}`;
}
else {
str = `${start} ${strings.join(' ')} ${end}`;
str = `${start} ${lines.join(' ')} ${end}`;
}
}
else {
const strings = nodes.map(blockItem);
str = strings.shift() || '';
for (const s of strings)
str += s ? `\n${indent}${s}` : '\n';
}
if (comment) {
str += '\n' + stringifyComment(comment, indent);
str += lineComment(str, commentString(comment), indent);
if (onComment)
onComment();
}
else if (chompKeep && onChompKeep)
onChompKeep();
return str;
}
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
if (comment && chompKeep)
comment = comment.replace(/^\n+/, '');
if (comment) {
const ic = indentComment(commentString(comment), indent);
lines.push(ic.trimStart()); // Avoid double indent on first line
}
}
export { stringifyCollection };

@@ -1,14 +0,18 @@

const stringifyComment = (comment, indent) => /^\n+$/.test(comment)
? comment.substring(1)
: comment.replace(/^(?!$)(?: $)?/gm, `${indent}#`);
function addComment(str, indent, comment) {
return !comment
? str
: comment.includes('\n')
? `${str}\n` + stringifyComment(comment, indent)
: str.endsWith(' ')
? `${str}#${comment}`
: `${str} #${comment}`;
/**
* Stringifies a comment.
*
* Empty comment lines are left empty,
* lines consisting of a single space are replaced by `#`,
* and all other lines are prefixed with a `#`.
*/
const stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, '#');
function indentComment(comment, indent) {
if (/^\n+$/.test(comment))
return comment.substring(1);
return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
}
const lineComment = (str, indent, comment) => comment.includes('\n')
? '\n' + indentComment(comment, indent)
: (str.endsWith(' ') ? '' : ' ') + comment;
export { addComment, stringifyComment };
export { indentComment, lineComment, stringifyComment };
import { isNode } from '../nodes/Node.js';
import { createStringifyContext, stringify } from './stringify.js';
import { stringifyComment, addComment } from './stringifyComment.js';
import { indentComment, lineComment } from './stringifyComment.js';

@@ -8,3 +8,3 @@ function stringifyDocument(doc, options) {

let hasDirectives = options.directives === true;
if (options.directives !== false) {
if (options.directives !== false && doc.directives) {
const dir = doc.directives.toString(doc);

@@ -20,8 +20,10 @@ if (dir) {

lines.push('---');
const ctx = createStringifyContext(doc, options);
const { commentString } = ctx.options;
if (doc.commentBefore) {
if (lines.length !== 1)
lines.unshift('');
lines.unshift(stringifyComment(doc.commentBefore, ''));
const cs = commentString(doc.commentBefore);
lines.unshift(indentComment(cs, ''));
}
const ctx = createStringifyContext(doc, options);
let chompKeep = false;

@@ -33,4 +35,6 @@ let contentComment = null;

lines.push('');
if (doc.contents.commentBefore)
lines.push(stringifyComment(doc.contents.commentBefore, ''));
if (doc.contents.commentBefore) {
const cs = commentString(doc.contents.commentBefore);
lines.push(indentComment(cs, ''));
}
// top-level block scalars need to be indented if followed by a comment

@@ -43,3 +47,3 @@ ctx.forceBlockIndent = !!doc.comment;

if (contentComment)
body = addComment(body, '', contentComment);
body += lineComment(body, '', commentString(contentComment));
if ((body[0] === '|' || body[0] === '>') &&

@@ -63,3 +67,3 @@ lines[lines.length - 1] === '---') {

lines.push('');
lines.push(stringifyComment(dc, ''));
lines.push(indentComment(commentString(dc), ''));
}

@@ -66,0 +70,0 @@ return lines.join('\n') + '\n';

import { isCollection, isNode, isScalar, isSeq } from '../nodes/Node.js';
import { Scalar } from '../nodes/Scalar.js';
import { stringify } from './stringify.js';
import { addComment, stringifyComment } from './stringifyComment.js';
import { lineComment, indentComment } from './stringifyComment.js';
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
const { allNullValues, doc, indent, indentStep, options: { indentSeq, simpleKeys } } = ctx;
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
let keyComment = (isNode(key) && key.comment) || null;

@@ -46,13 +46,22 @@ if (simpleKeys) {

else if ((allNullValues && !simpleKeys) || (value == null && explicitKey)) {
if (keyCommentDone)
keyComment = null;
if (chompKeep && !keyComment && onChompKeep)
str = `? ${str}`;
if (keyComment && !keyCommentDone) {
str += lineComment(str, ctx.indent, commentString(keyComment));
}
else if (chompKeep && onChompKeep)
onChompKeep();
return addComment(`? ${str}`, ctx.indent, keyComment);
return str;
}
if (keyCommentDone)
keyComment = null;
str = explicitKey
? `? ${addComment(str, ctx.indent, keyComment)}\n${indent}:`
: addComment(`${str}:`, ctx.indent, keyComment);
if (explicitKey) {
if (keyComment)
str += lineComment(str, ctx.indent, commentString(keyComment));
str = `? ${str}\n${indent}:`;
}
else {
str = `${str}:`;
if (keyComment)
str += lineComment(str, ctx.indent, commentString(keyComment));
}
let vcb = '';

@@ -63,4 +72,6 @@ let valueComment = null;

vcb = '\n';
if (value.commentBefore)
vcb += `\n${stringifyComment(value.commentBefore, ctx.indent)}`;
if (value.commentBefore) {
const cs = commentString(value.commentBefore);
vcb += `\n${indentComment(cs, ctx.indent)}`;
}
valueComment = value.comment;

@@ -99,16 +110,16 @@ }

ws = '';
str += ws + valueStr;
if (ctx.inFlow) {
if (valueCommentDone && onComment)
onComment();
return str + ws + valueStr;
}
else {
if (valueCommentDone)
valueComment = null;
if (chompKeep && !valueComment && onChompKeep)
onChompKeep();
return addComment(str + ws + valueStr, ctx.indent, valueComment);
else if (valueComment && !valueCommentDone) {
str += lineComment(str, ctx.indent, commentString(valueComment));
}
else if (chompKeep && onChompKeep) {
onChompKeep();
}
return str;
}
export { stringifyPair };

@@ -150,3 +150,3 @@ import { Scalar } from '../nodes/Scalar.js';

function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
const { lineWidth, blockQuote } = ctx.options;
const { blockQuote, commentString, lineWidth } = ctx.options;
// 1. Block can't end in whitespace unless the last line is non-empty.

@@ -216,3 +216,3 @@ // 2. Strings consisting of only whitespace are best rendered explicitly.

if (comment) {
header += ' #' + comment.replace(/ ?[\r\n]+/g, ' ');
header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' '));
if (onComment)

@@ -234,3 +234,2 @@ onComment();

function plainString(item, ctx, onComment, onChompKeep) {
var _a;
const { type, value } = item;

@@ -270,8 +269,6 @@ const { actualString, implicitKey, indent, inFlow } = ctx;

if (actualString) {
for (const tag of ctx.doc.schema.tags) {
if (tag.default &&
tag.tag !== 'tag:yaml.org,2002:str' &&
((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(str)))
return quotedString(value, ctx);
}
const test = (tag) => { var _a; return tag.default && tag.tag !== 'tag:yaml.org,2002:str' && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(str)); };
const { compat, tags } = ctx.doc.schema;
if (tags.some(test) || (compat === null || compat === void 0 ? void 0 : compat.some(test)))
return quotedString(value, ctx);
}

@@ -278,0 +275,0 @@ return implicitKey

@@ -12,2 +12,3 @@ 'use strict';

const ctx = {
atRoot: true,
directives: doc.directives,

@@ -14,0 +15,0 @@ options: doc.options,

@@ -8,2 +8,3 @@ import type { Directives } from '../doc/directives.js';

export interface ComposeContext {
atRoot: boolean;
directives: Directives;

@@ -10,0 +11,0 @@ options: Readonly<Required<Omit<ParseOptions, 'lineCounter'>>>;

@@ -17,3 +17,5 @@ 'use strict';

? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
: findScalarTagByTest(ctx.schema, value, token.type === 'scalar');
: token.type === 'scalar'
? findScalarTagByTest(ctx, value, token, onError)
: ctx.schema[Node.SCALAR];
let scalar;

@@ -67,13 +69,17 @@ try {

}
function findScalarTagByTest(schema, value, apply) {
var _a;
if (apply) {
for (const tag of schema.tags) {
if (tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)))
return tag;
function findScalarTagByTest({ directives, schema }, value, token, onError) {
const tag = schema.tags.find(tag => { var _a; return tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)); }) || schema[Node.SCALAR];
if (schema.compat) {
const compat = schema.compat.find(tag => { var _a; return tag.default && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(value)); }) ||
schema[Node.SCALAR];
if (tag.tag !== compat.tag) {
const ts = directives.tagString(tag.tag);
const cs = directives.tagString(compat.tag);
const msg = `Value may be parsed as either ${ts} or ${cs}`;
onError(token, 'TAG_RESOLVE_FAILED', msg, true);
}
}
return schema[Node.SCALAR];
return tag;
}
exports.composeScalar = composeScalar;

@@ -7,2 +7,3 @@ 'use strict';

var utilContainsNewline = require('./util-contains-newline.js');
var utilFlowIndentCheck = require('./util-flow-indent-check.js');
var utilMapIncludes = require('./util-map-includes.js');

@@ -14,2 +15,4 @@

const map = new YAMLMap.YAMLMap(ctx.schema);
if (ctx.atRoot)
ctx.atRoot = false;
let offset = bm.offset;

@@ -55,2 +58,4 @@ for (const collItem of bm.items) {

: composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
if (ctx.schema.compat)
utilFlowIndentCheck.flowIndentCheck(bm.indent, key, onError);
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))

@@ -79,2 +84,4 @@ onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');

: composeEmptyNode(ctx, offset, sep, null, valueProps, onError);
if (ctx.schema.compat)
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
offset = valueNode.range[2];

@@ -81,0 +88,0 @@ const pair = new Pair.Pair(keyNode, valueNode);

@@ -5,5 +5,8 @@ 'use strict';

var resolveProps = require('./resolve-props.js');
var utilFlowIndentCheck = require('./util-flow-indent-check.js');
function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) {
const seq = new YAMLSeq.YAMLSeq(ctx.schema);
if (ctx.atRoot)
ctx.atRoot = false;
let offset = bs.offset;

@@ -36,2 +39,4 @@ for (const { start, value } of bs.items) {

: composeEmptyNode(ctx, offset, start, null, props, onError);
if (ctx.schema.compat)
utilFlowIndentCheck.flowIndentCheck(bs.indent, value, onError);
offset = node.range[2];

@@ -38,0 +43,0 @@ seq.items.push(node);

@@ -21,3 +21,6 @@ 'use strict';

coll.flow = true;
let offset = fc.offset;
const atRoot = ctx.atRoot;
if (atRoot)
ctx.atRoot = false;
let offset = fc.offset + fc.start.source.length;
for (let i = 0; i < fc.items.length; ++i) {

@@ -46,2 +49,3 @@ const collItem = fc.items[i];

}
offset = props.end;
continue;

@@ -176,3 +180,7 @@ }

else {
onError(offset + 1, 'MISSING_CHAR', `Expected ${fcName} to end with ${expectedEnd}`);
const name = fcName[0].toUpperCase() + fcName.substring(1);
const msg = atRoot
? `${name} must end with a ${expectedEnd}`
: `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
onError(offset, atRoot ? 'MISSING_CHAR' : 'BAD_INDENT', msg);
if (ce && ce.source.length !== 1)

@@ -179,0 +187,0 @@ ee.unshift(ce);

@@ -86,2 +86,4 @@ 'use strict';

onError(token, 'BAD_PROP_ORDER', `Anchors and tags must be after the ${token.source} indicator`);
if (found)
onError(token, 'UNEXPECTED_TOKEN', `Unexpected ${token.source} in ${flow || 'collection'}`);
found = token;

@@ -88,0 +90,0 @@ atNewline = false;

@@ -14,2 +14,3 @@ import type { YAMLError, YAMLWarning } from '../errors.js';

interface Parsed<T extends ParsedNode = ParsedNode> extends Document<T> {
directives: Directives;
range: Range;

@@ -26,3 +27,3 @@ }

contents: T | null;
directives: Directives;
directives?: Directives;
/** Errors encountered during parsing. */

@@ -121,6 +122,8 @@ errors: YAMLError[];

* Change the YAML version and schema used by the document.
* A `null` version disables support for directives, explicit tags, anchors, and aliases.
* It also requires the `schema` option to be given as a `Schema` instance value.
*
* Overrides all previously set schema options
* Overrides all previously set schema options.
*/
setSchema(version: '1.1' | '1.2', options?: SchemaOptions): void;
setSchema(version: '1.1' | '1.2' | null, options?: SchemaOptions): void;
/** A plain JavaScript representation of the document `contents`. */

@@ -127,0 +130,0 @@ toJS(opt?: ToJSOptions & {

@@ -67,3 +67,4 @@ 'use strict';

copy.options = Object.assign({}, this.options);
copy.directives = this.directives.clone();
if (this.directives)
copy.directives = this.directives.clone();
copy.schema = this.schema.clone();

@@ -235,22 +236,43 @@ copy.contents = Node.isNode(this.contents)

* Change the YAML version and schema used by the document.
* A `null` version disables support for directives, explicit tags, anchors, and aliases.
* It also requires the `schema` option to be given as a `Schema` instance value.
*
* Overrides all previously set schema options
* Overrides all previously set schema options.
*/
setSchema(version, options) {
let _options;
switch (String(version)) {
setSchema(version, options = {}) {
if (typeof version === 'number')
version = String(version);
let opt;
switch (version) {
case '1.1':
this.directives.yaml.version = '1.1';
_options = Object.assign({ merge: true, resolveKnownTags: false, schema: 'yaml-1.1' }, options);
if (this.directives)
this.directives.yaml.version = '1.1';
else
this.directives = new directives.Directives({ version: '1.1' });
opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
break;
case '1.2':
this.directives.yaml.version = '1.2';
_options = Object.assign({ merge: false, resolveKnownTags: true, schema: 'core' }, options);
if (this.directives)
this.directives.yaml.version = '1.2';
else
this.directives = new directives.Directives({ version: '1.2' });
opt = { merge: false, resolveKnownTags: true, schema: 'core' };
break;
case null:
if (this.directives)
delete this.directives;
opt = null;
break;
default: {
const sv = JSON.stringify(version);
throw new Error(`Expected '1.1' or '1.2' as version, but found: ${sv}`);
throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
}
}
this.schema = new Schema.Schema(_options);
// Not using `instanceof Schema` to allow for duck typing
if (options.schema instanceof Object)
this.schema = options.schema;
else if (opt)
this.schema = new Schema.Schema(Object.assign(opt, options));
else
throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
}

@@ -257,0 +279,0 @@ // json & jsonArg are only used from toJSON()

@@ -109,3 +109,3 @@ 'use strict';

return stringifyCollection.stringifyCollection(this, ctx, {
blockItem: n => n.str,
blockItemPrefix: '',
flowChars: { start: '{', end: '}' },

@@ -112,0 +112,0 @@ itemIndent: ctx.indent || '',

@@ -90,3 +90,3 @@ 'use strict';

return stringifyCollection.stringifyCollection(this, ctx, {
blockItem: n => (n.comment ? n.str : `- ${n.str}`),
blockItemPrefix: '- ',
flowChars: { start: '[', end: ']' },

@@ -93,0 +93,0 @@ itemIndent: (ctx.indent || '') + ' ',

@@ -8,3 +8,3 @@ import type { Reviver } from './doc/applyReviver.js';

import type { LineCounter } from './parse/line-counter.js';
import type { SchemaName } from './schema/Schema.js';
import type { Schema } from './schema/Schema.js';
import type { Tags } from './schema/tags.js';

@@ -81,2 +81,10 @@ import type { CollectionTag, ScalarTag } from './schema/types.js';

/**
* When parsing, warn about compatibility issues with the given schema.
* When stringifying, use scalar styles that are parsed correctly
* by the `compat` schema as well as the actual schema.
*
* Default: `null`
*/
compat?: string | Tags | null;
/**
* Array of additional tags to include in the schema, or a function that may

@@ -104,5 +112,14 @@ * modify the schema's base tag array.

*
* Default: `"core"` for YAML 1.2, `"yaml-1.1"` for earlier versions
* The core library has built-in support for the following:
* - `'failsafe'`: A minimal schema that parses all scalars as strings
* - `'core'`: The YAML 1.2 core schema
* - `'json'`: The YAML 1.2 JSON schema, with minimal rules for JSON compatibility
* - `'yaml-1.1'`: The YAML 1.1 schema
*
* If using another (custom) schema, the `customTags` array needs to
* fully define the schema's tags.
*
* Default: `'core'` for YAML 1.2, `'yaml-1.1'` for earlier versions
*/
schema?: SchemaName;
schema?: string | Schema;
/**

@@ -116,2 +133,6 @@ * When adding to or stringifying a map, sort the entries.

sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
/**
* Override default values for `toString()` options.
*/
toStringDefaults?: ToStringOptions;
};

@@ -183,2 +204,19 @@ export declare type CreateNodeOptions = {

/**
* Enforce `'block'` or `'flow'` style on maps and sequences.
* Empty collections will always be stringified as `{}` or `[]`.
*
* Default: `'any'`, allowing each node to set its style separately
* with its `flow: boolean` (default `false`) property.
*/
collectionStyle?: 'any' | 'block' | 'flow';
/**
* Comment stringifier.
* Output should be valid for the current schema.
*
* By default, empty comment lines are left empty,
* lines consisting of a single space are replaced by `#`,
* and all other lines are prefixed with a `#`.
*/
commentString?: (comment: string) => string;
/**
* The default type of string literal used to stringify implicit key values.

@@ -185,0 +223,0 @@ * Output may use other types if required to fully represent the value.

@@ -421,2 +421,3 @@ 'use strict';

if (this.flowKey || isEmpty(next) || next === ',') {
this.flowKey = false;
yield* this.pushCount(1);

@@ -629,2 +630,4 @@ yield* this.pushSpaces(true);

this.indentNext = this.indentValue + 1;
else if (this.flowKey)
this.flowKey = false;
return ((yield* this.pushCount(1)) +

@@ -631,0 +634,0 @@ (yield* this.pushSpaces(true)) +

@@ -210,2 +210,3 @@ 'use strict';

case 'doc-mode':
case 'flow-error-end':
return;

@@ -283,5 +284,10 @@ default:

const top = this.peek(1);
// For these, parent indent is needed instead of own
if (token.type === 'block-scalar' || token.type === 'flow-collection')
token.indent = 'indent' in top ? top.indent : -1;
if (token.type === 'block-scalar') {
// Block scalars use their parent rather than header indent
token.indent = 'indent' in top ? top.indent : 0;
}
else if (token.type === 'flow-collection' && top.type === 'document') {
// Ignore all indent for top-level flow collections
token.indent = 0;
}
if (token.type === 'flow-collection')

@@ -288,0 +294,0 @@ fixFlowSeqItems(token);

@@ -11,6 +11,4 @@ 'use strict';

function parseOptions(options) {
const prettyErrors = !options || options.prettyErrors !== false;
const lineCounter$1 = (options && options.lineCounter) ||
(prettyErrors && new lineCounter.LineCounter()) ||
null;
const prettyErrors = options.prettyErrors !== false;
const lineCounter$1 = options.lineCounter || (prettyErrors && new lineCounter.LineCounter()) || null;
return { lineCounter: lineCounter$1, prettyErrors };

@@ -17,0 +15,0 @@ }

@@ -25,3 +25,6 @@ 'use strict';

resolve: str => parseFloat(str),
stringify: ({ value }) => Number(value).toExponential()
stringify(node) {
const num = Number(node.value);
return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node);
}
};

@@ -28,0 +31,0 @@ const float = {

import { MAP, SCALAR, SEQ } from '../nodes/Node.js';
import type { Pair } from '../nodes/Pair.js';
import type { SchemaOptions } from '../options.js';
import type { SchemaOptions, ToStringOptions } from '../options.js';
import type { CollectionTag, ScalarTag } from './types.js';
export declare type SchemaName = 'core' | 'failsafe' | 'json' | 'yaml-1.1';
export declare class Schema {
compat: Array<CollectionTag | ScalarTag> | null;
knownTags: Record<string, CollectionTag | ScalarTag>;
merge: boolean;
name: SchemaName;
name: string;
sortMapEntries: ((a: Pair, b: Pair) => number) | null;
tags: Array<CollectionTag | ScalarTag>;
toStringOptions: Readonly<ToStringOptions> | null;
[MAP]: CollectionTag;
[SCALAR]: ScalarTag;
[SEQ]: CollectionTag;
constructor({ customTags, merge, resolveKnownTags, schema, sortMapEntries }: SchemaOptions);
constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }: SchemaOptions);
clone(): Schema;
}

@@ -11,7 +11,13 @@ 'use strict';

class Schema {
constructor({ customTags, merge, resolveKnownTags, schema, sortMapEntries }) {
constructor({ compat, customTags, merge, resolveKnownTags, schema, sortMapEntries, toStringDefaults }) {
this.compat = Array.isArray(compat)
? tags.getTags(compat, 'compat')
: compat
? tags.getTags(null, compat)
: null;
this.merge = !!merge;
this.name = schema || 'core';
this.name = (typeof schema === 'string' && schema) || 'core';
this.knownTags = resolveKnownTags ? tags.coreKnownTags : {};
this.tags = tags.getTags(customTags, this.name);
this.toStringOptions = toStringDefaults || null;
Object.defineProperty(this, Node.MAP, { value: map.map });

@@ -18,0 +24,0 @@ Object.defineProperty(this, Node.SCALAR, { value: string.string });

import { SchemaOptions } from '../options.js';
import type { SchemaName } from './Schema.js';
import type { CollectionTag, ScalarTag } from './types.js';

@@ -40,3 +39,3 @@ declare const tagsByName: {

};
export declare function getTags(customTags: SchemaOptions['customTags'] | undefined, schemaName: SchemaName): (ScalarTag | CollectionTag)[];
export declare function getTags(customTags: SchemaOptions['customTags'] | undefined, schemaName: string): (ScalarTag | CollectionTag)[];
export {};

@@ -19,9 +19,9 @@ 'use strict';

const schemas = {
core: schema.schema,
failsafe: [map.map, seq.seq, string.string],
json: schema$1.schema,
yaml11: schema$2.schema,
'yaml-1.1': schema$2.schema
};
const schemas = new Map([
['core', schema.schema],
['failsafe', [map.map, seq.seq, string.string]],
['json', schema$1.schema],
['yaml11', schema$2.schema],
['yaml-1.1', schema$2.schema]
]);
const tagsByName = {

@@ -54,3 +54,3 @@ binary: binary.binary,

function getTags(customTags, schemaName) {
let tags = schemas[schemaName];
let tags = schemas.get(schemaName);
if (!tags) {

@@ -60,3 +60,3 @@ if (Array.isArray(customTags))

else {
const keys = Object.keys(schemas)
const keys = Array.from(schemas.keys())
.filter(key => key !== 'yaml11')

@@ -63,0 +63,0 @@ .map(key => JSON.stringify(key))

@@ -25,3 +25,6 @@ 'use strict';

resolve: (str) => parseFloat(str.replace(/_/g, '')),
stringify: ({ value }) => Number(value).toExponential()
stringify(node) {
const num = Number(node.value);
return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node);
}
};

@@ -28,0 +31,0 @@ const float = {

import type { Document } from '../doc/Document.js';
import type { Alias } from '../nodes/Alias.js';
import type { ToStringOptions } from '../options.js';

@@ -13,7 +14,8 @@ export declare type StringifyContext = {

indentAtStart?: number;
inFlow?: boolean;
inFlow: boolean | null;
inStringifyKey?: boolean;
options: Readonly<Required<Omit<ToStringOptions, 'indent'>>>;
options: Readonly<Required<Omit<ToStringOptions, 'collectionStyle' | 'indent'>>>;
resolvedAliases?: Set<Alias>;
};
export declare const createStringifyContext: (doc: Document, options: ToStringOptions) => StringifyContext;
export declare function createStringifyContext(doc: Document, options: ToStringOptions): StringifyContext;
export declare function stringify(item: unknown, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string;

@@ -5,11 +5,9 @@ 'use strict';

var Node = require('../nodes/Node.js');
var stringifyComment = require('./stringifyComment.js');
var stringifyString = require('./stringifyString.js');
const createStringifyContext = (doc, options) => ({
anchors: new Set(),
doc,
indent: '',
indentStep: typeof options.indent === 'number' ? ' '.repeat(options.indent) : ' ',
options: Object.assign({
function createStringifyContext(doc, options) {
const opt = Object.assign({
blockQuote: true,
commentString: stringifyComment.stringifyComment,
defaultKeyType: null,

@@ -29,4 +27,23 @@ defaultStringType: 'PLAIN',

verifyAliasOrder: true
}, options)
});
}, 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,
indent: '',
indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ',
inFlow,
options: opt
};
}
function getTagObject(tags, item) {

@@ -59,2 +76,4 @@ if (item.tag) {

function stringifyProps(node, tagObj, { anchors: anchors$1, doc }) {
if (!doc.directives)
return '';
const props = [];

@@ -66,15 +85,25 @@ const anchor = (Node.isScalar(node) || Node.isCollection(node)) && node.anchor;

}
if (node.tag) {
props.push(doc.directives.tagString(node.tag));
}
else if (!tagObj.default) {
props.push(doc.directives.tagString(tagObj.tag));
}
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) {
var _a;
if (Node.isPair(item))
return item.toString(ctx, onComment, onChompKeep);
if (Node.isAlias(item))
return item.toString(ctx);
if (Node.isAlias(item)) {
if (ctx.doc.directives)
return item.toString(ctx);
if ((_a = ctx.resolvedAliases) === null || _a === void 0 ? void 0 : _a.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;

@@ -81,0 +110,0 @@ const node = Node.isNode(item)

import { Collection } from '../nodes/Collection.js';
import { StringifyContext } from './stringify.js';
declare type StringifyNode = {
comment: boolean;
str: string;
};
interface StringifyCollectionOptions {
blockItem(node: StringifyNode): string;
blockItemPrefix: string;
flowChars: {

@@ -20,3 +16,3 @@ start: '{';

}
export declare function stringifyCollection({ comment, flow, items }: Readonly<Collection>, ctx: StringifyContext, { blockItem, flowChars, itemIndent, onChompKeep, onComment }: StringifyCollectionOptions): string;
export declare function stringifyCollection(collection: Readonly<Collection>, ctx: StringifyContext, options: StringifyCollectionOptions): string;
export {};

@@ -8,31 +8,22 @@ 'use strict';

function stringifyCollection({ comment, flow, items }, ctx, { blockItem, flowChars, itemIndent, onChompKeep, onComment }) {
const { indent, indentStep } = ctx;
const inFlow = flow || ctx.inFlow;
if (inFlow)
itemIndent += indentStep;
ctx = Object.assign({}, ctx, { indent: itemIndent, inFlow, type: null });
let singleLineOutput = true;
function stringifyCollection(collection, ctx, options) {
var _a;
const flow = (_a = ctx.inFlow) !== null && _a !== void 0 ? _a : collection.flow;
const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
return stringify(collection, ctx, options);
}
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
const { indent, options: { commentString } } = ctx;
const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
let chompKeep = false; // flag for the preceding node's status
const nodes = items.reduce((nodes, item, i) => {
const lines = [];
for (let i = 0; i < items.length; ++i) {
const item = items[i];
let comment = null;
if (Node.isNode(item)) {
if (!chompKeep && item.spaceBefore)
nodes.push({ comment: true, str: '' });
let cb = item.commentBefore;
if (cb && chompKeep)
cb = cb.replace(/^\n+/, '');
if (cb) {
if (/^\n+$/.test(cb))
cb = cb.substring(1);
// This match will always succeed on a non-empty string
for (const line of cb.match(/^.*$/gm)) {
const str = line === ' ' ? '#' : line ? `#${line}` : '';
nodes.push({ comment: true, str });
}
}
if (item.comment) {
lines.push('');
addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
if (item.comment)
comment = item.comment;
singleLineOutput = false;
}
}

@@ -43,84 +34,123 @@ else if (Node.isPair(item)) {

if (!chompKeep && ik.spaceBefore)
nodes.push({ comment: true, str: '' });
let cb = ik.commentBefore;
if (cb && chompKeep)
cb = cb.replace(/^\n+/, '');
if (cb) {
if (/^\n+$/.test(cb))
cb = cb.substring(1);
// This match will always succeed on a non-empty string
for (const line of cb.match(/^.*$/gm)) {
const str = line === ' ' ? '#' : line ? `#${line}` : '';
nodes.push({ comment: true, str });
}
}
if (ik.comment)
singleLineOutput = false;
lines.push('');
addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
}
if (inFlow) {
const iv = Node.isNode(item.value) ? item.value : null;
if (iv) {
if (iv.comment)
comment = iv.comment;
if (iv.comment || iv.commentBefore)
singleLineOutput = false;
}
else if (item.value == null && ik && ik.comment) {
comment = ik.comment;
}
}
}
chompKeep = false;
let str = stringify.stringify(item, ctx, () => (comment = null), () => (chompKeep = true));
if (inFlow && i < items.length - 1)
str += ',';
str = stringifyComment.addComment(str, itemIndent, comment);
if (chompKeep && (comment || inFlow))
let str = stringify.stringify(item, itemCtx, () => (comment = null), () => (chompKeep = true));
if (comment)
str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
if (chompKeep && comment)
chompKeep = false;
nodes.push({ comment: false, str });
return nodes;
}, []);
lines.push(blockItemPrefix + str);
}
let str;
if (nodes.length === 0) {
if (lines.length === 0) {
str = flowChars.start + flowChars.end;
}
else if (inFlow) {
const { start, end } = flowChars;
const strings = nodes.map(n => n.str);
let singleLineLength = 2;
for (const node of nodes) {
if (node.comment || node.str.includes('\n')) {
singleLineOutput = false;
break;
else {
str = lines[0];
for (let i = 1; i < lines.length; ++i) {
const line = lines[i];
str += line ? `\n${indent}${line}` : '\n';
}
}
if (comment) {
str += '\n' + stringifyComment.indentComment(commentString(comment), indent);
if (onComment)
onComment();
}
else if (chompKeep && onChompKeep)
onChompKeep();
return str;
}
function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemIndent, onComment }) {
const { indent, indentStep, options: { commentString } } = ctx;
itemIndent += indentStep;
const itemCtx = Object.assign({}, ctx, {
indent: itemIndent,
inFlow: true,
type: null
});
let reqNewline = false;
let linesAtValue = 0;
const lines = [];
for (let i = 0; i < items.length; ++i) {
const item = items[i];
let comment = null;
if (Node.isNode(item)) {
if (item.spaceBefore)
lines.push('');
addCommentBefore(ctx, lines, item.commentBefore, false);
if (item.comment)
comment = item.comment;
}
else if (Node.isPair(item)) {
const ik = Node.isNode(item.key) ? item.key : null;
if (ik) {
if (ik.spaceBefore)
lines.push('');
addCommentBefore(ctx, lines, ik.commentBefore, false);
if (ik.comment)
reqNewline = true;
}
singleLineLength += node.str.length + 2;
const iv = Node.isNode(item.value) ? item.value : null;
if (iv) {
if (iv.comment)
comment = iv.comment;
if (iv.commentBefore)
reqNewline = true;
}
else if (item.value == null && ik && ik.comment) {
comment = ik.comment;
}
}
if (!singleLineOutput ||
singleLineLength > Collection.Collection.maxFlowStringSingleLineLength) {
if (comment)
reqNewline = true;
let str = stringify.stringify(item, itemCtx, () => (comment = null));
if (i < items.length - 1)
str += ',';
if (comment)
str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
reqNewline = true;
lines.push(str);
linesAtValue = lines.length;
}
let str;
const { start, end } = flowChars;
if (lines.length === 0) {
str = start + end;
}
else {
if (!reqNewline) {
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
reqNewline = len > Collection.Collection.maxFlowStringSingleLineLength;
}
if (reqNewline) {
str = start;
for (const s of strings) {
str += s ? `\n${indentStep}${indent}${s}` : '\n';
}
for (const line of lines)
str += line ? `\n${indentStep}${indent}${line}` : '\n';
str += `\n${indent}${end}`;
}
else {
str = `${start} ${strings.join(' ')} ${end}`;
str = `${start} ${lines.join(' ')} ${end}`;
}
}
else {
const strings = nodes.map(blockItem);
str = strings.shift() || '';
for (const s of strings)
str += s ? `\n${indent}${s}` : '\n';
}
if (comment) {
str += '\n' + stringifyComment.stringifyComment(comment, indent);
str += stringifyComment.lineComment(str, commentString(comment), indent);
if (onComment)
onComment();
}
else if (chompKeep && onChompKeep)
onChompKeep();
return str;
}
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
if (comment && chompKeep)
comment = comment.replace(/^\n+/, '');
if (comment) {
const ic = stringifyComment.indentComment(commentString(comment), indent);
lines.push(ic.trimStart()); // Avoid double indent on first line
}
}
exports.stringifyCollection = stringifyCollection;

@@ -1,2 +0,10 @@

export declare const stringifyComment: (comment: string, indent: string) => string;
export declare function addComment(str: string, indent: string, comment?: string | null): string;
/**
* Stringifies a comment.
*
* Empty comment lines are left empty,
* lines consisting of a single space are replaced by `#`,
* and all other lines are prefixed with a `#`.
*/
export declare const stringifyComment: (str: string) => string;
export declare function indentComment(comment: string, indent: string): string;
export declare const lineComment: (str: string, indent: string, comment: string) => string;
'use strict';
const stringifyComment = (comment, indent) => /^\n+$/.test(comment)
? comment.substring(1)
: comment.replace(/^(?!$)(?: $)?/gm, `${indent}#`);
function addComment(str, indent, comment) {
return !comment
? str
: comment.includes('\n')
? `${str}\n` + stringifyComment(comment, indent)
: str.endsWith(' ')
? `${str}#${comment}`
: `${str} #${comment}`;
/**
* Stringifies a comment.
*
* Empty comment lines are left empty,
* lines consisting of a single space are replaced by `#`,
* and all other lines are prefixed with a `#`.
*/
const stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, '#');
function indentComment(comment, indent) {
if (/^\n+$/.test(comment))
return comment.substring(1);
return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
}
const lineComment = (str, indent, comment) => comment.includes('\n')
? '\n' + indentComment(comment, indent)
: (str.endsWith(' ') ? '' : ' ') + comment;
exports.addComment = addComment;
exports.indentComment = indentComment;
exports.lineComment = lineComment;
exports.stringifyComment = stringifyComment;

@@ -10,3 +10,3 @@ 'use strict';

let hasDirectives = options.directives === true;
if (options.directives !== false) {
if (options.directives !== false && doc.directives) {
const dir = doc.directives.toString(doc);

@@ -22,8 +22,10 @@ if (dir) {

lines.push('---');
const ctx = stringify.createStringifyContext(doc, options);
const { commentString } = ctx.options;
if (doc.commentBefore) {
if (lines.length !== 1)
lines.unshift('');
lines.unshift(stringifyComment.stringifyComment(doc.commentBefore, ''));
const cs = commentString(doc.commentBefore);
lines.unshift(stringifyComment.indentComment(cs, ''));
}
const ctx = stringify.createStringifyContext(doc, options);
let chompKeep = false;

@@ -35,4 +37,6 @@ let contentComment = null;

lines.push('');
if (doc.contents.commentBefore)
lines.push(stringifyComment.stringifyComment(doc.contents.commentBefore, ''));
if (doc.contents.commentBefore) {
const cs = commentString(doc.contents.commentBefore);
lines.push(stringifyComment.indentComment(cs, ''));
}
// top-level block scalars need to be indented if followed by a comment

@@ -45,3 +49,3 @@ ctx.forceBlockIndent = !!doc.comment;

if (contentComment)
body = stringifyComment.addComment(body, '', contentComment);
body += stringifyComment.lineComment(body, '', commentString(contentComment));
if ((body[0] === '|' || body[0] === '>') &&

@@ -65,3 +69,3 @@ lines[lines.length - 1] === '---') {

lines.push('');
lines.push(stringifyComment.stringifyComment(dc, ''));
lines.push(stringifyComment.indentComment(commentString(dc), ''));
}

@@ -68,0 +72,0 @@ return lines.join('\n') + '\n';

@@ -9,3 +9,3 @@ 'use strict';

function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
const { allNullValues, doc, indent, indentStep, options: { indentSeq, simpleKeys } } = ctx;
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
let keyComment = (Node.isNode(key) && key.comment) || null;

@@ -49,13 +49,22 @@ if (simpleKeys) {

else if ((allNullValues && !simpleKeys) || (value == null && explicitKey)) {
if (keyCommentDone)
keyComment = null;
if (chompKeep && !keyComment && onChompKeep)
str = `? ${str}`;
if (keyComment && !keyCommentDone) {
str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
}
else if (chompKeep && onChompKeep)
onChompKeep();
return stringifyComment.addComment(`? ${str}`, ctx.indent, keyComment);
return str;
}
if (keyCommentDone)
keyComment = null;
str = explicitKey
? `? ${stringifyComment.addComment(str, ctx.indent, keyComment)}\n${indent}:`
: stringifyComment.addComment(`${str}:`, ctx.indent, keyComment);
if (explicitKey) {
if (keyComment)
str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
str = `? ${str}\n${indent}:`;
}
else {
str = `${str}:`;
if (keyComment)
str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
}
let vcb = '';

@@ -66,4 +75,6 @@ let valueComment = null;

vcb = '\n';
if (value.commentBefore)
vcb += `\n${stringifyComment.stringifyComment(value.commentBefore, ctx.indent)}`;
if (value.commentBefore) {
const cs = commentString(value.commentBefore);
vcb += `\n${stringifyComment.indentComment(cs, ctx.indent)}`;
}
valueComment = value.comment;

@@ -102,16 +113,16 @@ }

ws = '';
str += ws + valueStr;
if (ctx.inFlow) {
if (valueCommentDone && onComment)
onComment();
return str + ws + valueStr;
}
else {
if (valueCommentDone)
valueComment = null;
if (chompKeep && !valueComment && onChompKeep)
onChompKeep();
return stringifyComment.addComment(str + ws + valueStr, ctx.indent, valueComment);
else if (valueComment && !valueCommentDone) {
str += stringifyComment.lineComment(str, ctx.indent, commentString(valueComment));
}
else if (chompKeep && onChompKeep) {
onChompKeep();
}
return str;
}
exports.stringifyPair = stringifyPair;

@@ -152,3 +152,3 @@ 'use strict';

function blockString({ comment, type, value }, ctx, onComment, onChompKeep) {
const { lineWidth, blockQuote } = ctx.options;
const { blockQuote, commentString, lineWidth } = ctx.options;
// 1. Block can't end in whitespace unless the last line is non-empty.

@@ -218,3 +218,3 @@ // 2. Strings consisting of only whitespace are best rendered explicitly.

if (comment) {
header += ' #' + comment.replace(/ ?[\r\n]+/g, ' ');
header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' '));
if (onComment)

@@ -236,3 +236,2 @@ onComment();

function plainString(item, ctx, onComment, onChompKeep) {
var _a;
const { type, value } = item;

@@ -272,8 +271,6 @@ const { actualString, implicitKey, indent, inFlow } = ctx;

if (actualString) {
for (const tag of ctx.doc.schema.tags) {
if (tag.default &&
tag.tag !== 'tag:yaml.org,2002:str' &&
((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(str)))
return quotedString(value, ctx);
}
const test = (tag) => { var _a; return tag.default && tag.tag !== 'tag:yaml.org,2002:str' && ((_a = tag.test) === null || _a === void 0 ? void 0 : _a.test(str)); };
const { compat, tags } = ctx.doc.schema;
if (tags.some(test) || (compat === null || compat === void 0 ? void 0 : compat.some(test)))
return quotedString(value, ctx);
}

@@ -280,0 +277,0 @@ return implicitKey

@@ -86,3 +86,4 @@ 'use strict';

if (Node.isMap(node)) {
events.push(`+MAP${props}`);
const ev = node.flow ? '+MAP {}' : '+MAP';
events.push(`${ev}${props}`);
node.items.forEach(({ key, value }) => {

@@ -95,3 +96,4 @@ addEvents(events, doc, errPos, key);

else if (Node.isSeq(node)) {
events.push(`+SEQ${props}`);
const ev = node.flow ? '+SEQ []' : '+SEQ';
events.push(`${ev}${props}`);
node.items.forEach(item => {

@@ -98,0 +100,0 @@ addEvents(events, doc, errPos, item);

{
"name": "yaml",
"version": "2.0.0-9",
"version": "2.0.0-10",
"license": "ISC",

@@ -48,5 +48,6 @@ "author": "Eemeli Aro <eemeli@gmail.com>",

"test": "jest --config config/jest.config.js",
"test:all": "npm test && npm run test:types && npm run test:dist && npm run test:dist:types",
"test:browsers": "cd playground && npm test",
"test:dist": "npm run build:node && jest --config config/jest.config.js",
"test:dist:types": "tsc --allowJs --moduleResolution node --noEmit --target es2017 dist/index.js",
"test:dist:types": "tsc --allowJs --moduleResolution node --noEmit --target es5 dist/index.js",
"test:types": "tsc --noEmit",

@@ -77,7 +78,7 @@ "docs:install": "cd docs-slate && bundle install",

"@types/node": "^16.9.1",
"@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2",
"@typescript-eslint/eslint-plugin": "^5.3.1",
"@typescript-eslint/parser": "^5.3.1",
"babel-jest": "^27.0.1",
"cross-env": "^7.0.3",
"eslint": "^7.20.0",
"eslint": "^8.2.0",
"eslint-config-prettier": "^8.1.0",

@@ -84,0 +85,0 @@ "fast-check": "^2.12.0",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc