@stoplight/yaml
Advanced tools
Comparing version 4.2.3 to 4.3.0
@@ -6,6 +6,6 @@ export * from './buildJsonPath'; | ||
export * from './lineForPosition'; | ||
export * from './parse'; | ||
export * from './parseWithPointers'; | ||
export { parse } from './parse'; | ||
export { parseWithPointers } from './parseWithPointers'; | ||
export * from './safeStringify'; | ||
export * from './types'; | ||
export * from './trapAccess'; |
@@ -9,4 +9,6 @@ "use strict"; | ||
tslib_1.__exportStar(require("./lineForPosition"), exports); | ||
tslib_1.__exportStar(require("./parse"), exports); | ||
tslib_1.__exportStar(require("./parseWithPointers"), exports); | ||
var parse_1 = require("./parse"); | ||
exports.parse = parse_1.parse; | ||
var parseWithPointers_1 = require("./parseWithPointers"); | ||
exports.parseWithPointers = parseWithPointers_1.parseWithPointers; | ||
tslib_1.__exportStar(require("./safeStringify"), exports); | ||
@@ -13,0 +15,0 @@ tslib_1.__exportStar(require("./types"), exports); |
{ | ||
"name": "@stoplight/yaml", | ||
"version": "4.2.3", | ||
"version": "4.3.0", | ||
"description": "Useful functions when working with YAML.", | ||
@@ -27,5 +27,5 @@ "keywords": [ | ||
"dependencies": { | ||
"@stoplight/ordered-object-literal": "^1.0.1", | ||
"@stoplight/types": "^13.0.0", | ||
"@stoplight/yaml-ast-parser": "0.0.48", | ||
"@stoplight/ordered-object-literal": "^1.0.5", | ||
"@stoplight/types": "^14.1.1", | ||
"@stoplight/yaml-ast-parser": "0.0.50", | ||
"tslib": "^2.2.0" | ||
@@ -32,0 +32,0 @@ }, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const yaml_ast_parser_1 = require("@stoplight/yaml-ast-parser"); | ||
const parseWithPointers_1 = require("./parseWithPointers"); | ||
exports.parse = (value) => parseWithPointers_1.walkAST(yaml_ast_parser_1.load(value), void 0, [], []); | ||
exports.parse = (value) => parseWithPointers_1.parseWithPointers(value).data; | ||
//# sourceMappingURL=parse.js.map |
@@ -1,4 +0,2 @@ | ||
import { IDiagnostic } from '@stoplight/types'; | ||
import { IParseOptions, Kind, YAMLMapping, YAMLNode, YAMLScalar } from './types'; | ||
export declare const parseWithPointers: <T>(value: string, options?: IParseOptions | undefined) => import("@stoplight/types").IParserResult<T | undefined, YAMLNode, number[], IParseOptions>; | ||
export declare const walkAST: (node: import("./types").YAMLAnchorReference | import("./types").YAMLBaseNode<Kind.INCLUDE_REF> | YAMLScalar | import("./types").YAMLMap | YAMLMapping | import("./types").YAMLSequence | null, options: IParseOptions | undefined, lineMap: number[], diagnostics: IDiagnostic[]) => unknown; | ||
import { IParseOptions, YamlParserResult } from './types'; | ||
export declare const parseWithPointers: <T>(value: string, options?: IParseOptions | undefined) => YamlParserResult<T | undefined>; |
@@ -20,6 +20,13 @@ "use strict"; | ||
metadata: options, | ||
comments: {}, | ||
}; | ||
if (!ast) | ||
return parsed; | ||
parsed.data = exports.walkAST(ast, options, lineMap, parsed.diagnostics); | ||
const normalizedOptions = normalizeOptions(options); | ||
const comments = new Comments(parsed.comments, Comments.mapComments(normalizedOptions.attachComments && ast.comments ? ast.comments : [], lineMap), ast, lineMap, '#'); | ||
const ctx = { | ||
lineMap, | ||
diagnostics: parsed.diagnostics, | ||
}; | ||
parsed.data = walkAST(ctx, ast, comments, normalizedOptions); | ||
if (ast.errors) { | ||
@@ -36,12 +43,19 @@ parsed.diagnostics.push(...transformErrors(ast.errors, lineMap)); | ||
}; | ||
exports.walkAST = (node, options, lineMap, diagnostics) => { | ||
const TILDE_REGEXP = /~/g; | ||
const SLASH_REGEXP = /\//g; | ||
function encodeSegment(input) { | ||
return input.replace(TILDE_REGEXP, '~0').replace(SLASH_REGEXP, '~1'); | ||
} | ||
const walkAST = (ctx, node, comments, options) => { | ||
if (node) { | ||
switch (node.kind) { | ||
case types_2.Kind.MAP: { | ||
const preserveKeyOrder = options !== void 0 && options.preserveKeyOrder === true; | ||
const mapComments = comments.enter(node); | ||
const { lineMap, diagnostics } = ctx; | ||
const { preserveKeyOrder, ignoreDuplicateKeys, json, mergeKeys } = options; | ||
const container = createMapContainer(preserveKeyOrder); | ||
const seenKeys = []; | ||
const handleMergeKeys = options !== void 0 && options.mergeKeys === true; | ||
const yamlMode = options !== void 0 && options.json === false; | ||
const handleDuplicates = options !== void 0 && options.ignoreDuplicateKeys === false; | ||
const handleMergeKeys = mergeKeys; | ||
const yamlMode = !json; | ||
const handleDuplicates = !ignoreDuplicateKeys; | ||
for (const mapping of node.mappings) { | ||
@@ -51,2 +65,3 @@ if (!validateMappingKey(mapping, lineMap, diagnostics, yamlMode)) | ||
const key = String(getScalarValue(mapping.key)); | ||
const mappingComments = mapComments.enter(mapping, encodeSegment(key)); | ||
if ((yamlMode || handleDuplicates) && (!handleMergeKeys || key !== "<<")) { | ||
@@ -66,7 +81,7 @@ if (seenKeys.includes(key)) { | ||
if (handleMergeKeys && key === "<<") { | ||
const reduced = reduceMergeKeys(exports.walkAST(mapping.value, options, lineMap, diagnostics), preserveKeyOrder); | ||
const reduced = reduceMergeKeys(walkAST(ctx, mapping.value, mappingComments, options), preserveKeyOrder); | ||
Object.assign(container, reduced); | ||
} | ||
else { | ||
container[key] = exports.walkAST(mapping.value, options, lineMap, diagnostics); | ||
container[key] = walkAST(ctx, mapping.value, mappingComments, options); | ||
if (preserveKeyOrder) { | ||
@@ -76,11 +91,26 @@ pushKey(container, key); | ||
} | ||
mappingComments.attachComments(); | ||
} | ||
mapComments.attachComments(); | ||
return container; | ||
} | ||
case types_2.Kind.SEQ: | ||
return node.items.map(item => exports.walkAST(item, options, lineMap, diagnostics)); | ||
case types_2.Kind.SEQ: { | ||
const nodeComments = comments.enter(node); | ||
const container = node.items.map((item, i) => { | ||
if (item !== null) { | ||
const sequenceItemComments = nodeComments.enter(item, i); | ||
const walked = walkAST(ctx, item, sequenceItemComments, options); | ||
sequenceItemComments.attachComments(); | ||
return walked; | ||
} | ||
else { | ||
return null; | ||
} | ||
}); | ||
nodeComments.attachComments(); | ||
return container; | ||
} | ||
case types_2.Kind.SCALAR: { | ||
const bigInt = options !== void 0 && options.bigInt === true; | ||
const value = getScalarValue(node); | ||
return !bigInt && typeof value === 'bigint' ? Number(value) : value; | ||
return !options.bigInt && typeof value === 'bigint' ? Number(value) : value; | ||
} | ||
@@ -91,3 +121,3 @@ case types_2.Kind.ANCHOR_REF: { | ||
} | ||
return exports.walkAST(node.value, options, lineMap, diagnostics); | ||
return walkAST(ctx, node.value, comments, options); | ||
} | ||
@@ -225,4 +255,2 @@ default: | ||
function createYAMLException(node, lineMap, message) { | ||
const startLine = lineForPosition_1.lineForPosition(node.startPosition, lineMap); | ||
const endLine = lineForPosition_1.lineForPosition(node.endPosition, lineMap); | ||
return { | ||
@@ -233,14 +261,204 @@ code: 'YAMLException', | ||
path: buildJsonPath_1.buildJsonPath(node), | ||
range: { | ||
start: { | ||
line: startLine, | ||
character: startLine === 0 ? node.startPosition : node.startPosition - lineMap[startLine - 1], | ||
}, | ||
end: { | ||
line: endLine, | ||
character: endLine === 0 ? node.endPosition : node.endPosition - lineMap[endLine - 1], | ||
}, | ||
range: getRange(lineMap, node.startPosition, node.endPosition), | ||
}; | ||
} | ||
function getRange(lineMap, startPosition, endPosition) { | ||
const startLine = lineForPosition_1.lineForPosition(startPosition, lineMap); | ||
const endLine = lineForPosition_1.lineForPosition(endPosition, lineMap); | ||
return { | ||
start: { | ||
line: startLine, | ||
character: startLine === 0 ? startPosition : startPosition - lineMap[startLine - 1], | ||
}, | ||
end: { | ||
line: endLine, | ||
character: endLine === 0 ? endPosition : endPosition - lineMap[endLine - 1], | ||
}, | ||
}; | ||
} | ||
class Comments { | ||
constructor(attachedComments, comments, node, lineMap, pointer) { | ||
this.attachedComments = attachedComments; | ||
this.node = node; | ||
this.lineMap = lineMap; | ||
this.pointer = pointer; | ||
if (comments.length === 0) { | ||
this.comments = []; | ||
} | ||
else { | ||
const startPosition = this.getStartPosition(node); | ||
const endPosition = this.getEndPosition(node); | ||
const startLine = lineForPosition_1.lineForPosition(startPosition, this.lineMap); | ||
const endLine = lineForPosition_1.lineForPosition(endPosition, this.lineMap); | ||
const matchingComments = []; | ||
for (let i = comments.length - 1; i >= 0; i--) { | ||
const comment = comments[i]; | ||
if (comment.range.start.line >= startLine && comment.range.end.line <= endLine) { | ||
matchingComments.push(comment); | ||
comments.splice(i, 1); | ||
} | ||
} | ||
this.comments = matchingComments; | ||
} | ||
} | ||
getStartPosition(node) { | ||
if (node.parent === null) { | ||
return 0; | ||
} | ||
return node.kind === types_2.Kind.MAPPING ? node.key.startPosition : node.startPosition; | ||
} | ||
getEndPosition(node) { | ||
switch (node.kind) { | ||
case types_2.Kind.MAPPING: | ||
return node.value === null ? node.endPosition : this.getEndPosition(node.value); | ||
case types_2.Kind.MAP: | ||
return node.mappings.length === 0 ? node.endPosition : node.mappings[node.mappings.length - 1].endPosition; | ||
case types_2.Kind.SEQ: { | ||
if (node.items.length === 0) { | ||
return node.endPosition; | ||
} | ||
const lastItem = node.items[node.items.length - 1]; | ||
return lastItem === null ? node.endPosition : lastItem.endPosition; | ||
} | ||
default: | ||
return node.endPosition; | ||
} | ||
} | ||
static mapComments(comments, lineMap) { | ||
return comments.map(comment => ({ | ||
value: comment.value, | ||
range: getRange(lineMap, comment.startPosition, comment.endPosition), | ||
startPosition: comment.startPosition, | ||
endPosition: comment.endPosition, | ||
})); | ||
} | ||
enter(node, key) { | ||
return new Comments(this.attachedComments, this.comments, node, this.lineMap, key === void 0 ? this.pointer : `${this.pointer}/${key}`); | ||
} | ||
static isLeading(node, startPosition) { | ||
switch (node.kind) { | ||
case types_2.Kind.MAP: | ||
return node.mappings.length === 0 || node.mappings[0].startPosition > startPosition; | ||
case types_2.Kind.SEQ: { | ||
if (node.items.length === 0) { | ||
return true; | ||
} | ||
const firstItem = node.items[0]; | ||
return firstItem === null || firstItem.startPosition > startPosition; | ||
} | ||
case types_2.Kind.MAPPING: | ||
return node.value === null || node.value.startPosition > startPosition; | ||
default: | ||
return false; | ||
} | ||
} | ||
static isTrailing(node, endPosition) { | ||
switch (node.kind) { | ||
case types_2.Kind.MAP: | ||
return node.mappings.length > 0 && endPosition > node.mappings[node.mappings.length - 1].endPosition; | ||
case types_2.Kind.SEQ: | ||
if (node.items.length === 0) { | ||
return false; | ||
} | ||
const lastItem = node.items[node.items.length - 1]; | ||
return lastItem !== null && endPosition > lastItem.endPosition; | ||
case types_2.Kind.MAPPING: | ||
return node.value !== null && endPosition > node.value.endPosition; | ||
default: | ||
return false; | ||
} | ||
} | ||
static findBetween(node, startPosition, endPosition) { | ||
switch (node.kind) { | ||
case types_2.Kind.MAP: { | ||
let left; | ||
for (const mapping of node.mappings) { | ||
if (startPosition > mapping.startPosition) { | ||
left = mapping.key.value; | ||
} | ||
else if (left !== void 0 && mapping.startPosition > endPosition) { | ||
return [left, mapping.key.value]; | ||
} | ||
} | ||
return null; | ||
} | ||
case types_2.Kind.SEQ: { | ||
let left; | ||
for (let i = 0; i < node.items.length; i++) { | ||
const item = node.items[i]; | ||
if (item === null) | ||
continue; | ||
if (startPosition > item.startPosition) { | ||
left = String(i); | ||
} | ||
else if (left !== void 0 && item.startPosition > endPosition) { | ||
return [left, String(i)]; | ||
} | ||
} | ||
return null; | ||
} | ||
default: | ||
return null; | ||
} | ||
} | ||
isBeforeEOL(comment) { | ||
return (this.node.kind === types_2.Kind.SCALAR || | ||
(this.node.kind === types_2.Kind.MAPPING && | ||
comment.range.end.line === lineForPosition_1.lineForPosition(this.node.key.endPosition, this.lineMap))); | ||
} | ||
attachComments() { | ||
if (this.comments.length === 0) | ||
return; | ||
const attachedComments = (this.attachedComments[this.pointer] = this.attachedComments[this.pointer] || []); | ||
for (const comment of this.comments) { | ||
if (this.isBeforeEOL(comment)) { | ||
attachedComments.push({ | ||
value: comment.value, | ||
placement: 'before-eol', | ||
}); | ||
} | ||
else if (Comments.isLeading(this.node, comment.startPosition)) { | ||
attachedComments.push({ | ||
value: comment.value, | ||
placement: 'leading', | ||
}); | ||
} | ||
else if (Comments.isTrailing(this.node, comment.endPosition)) { | ||
attachedComments.push({ | ||
value: comment.value, | ||
placement: 'trailing', | ||
}); | ||
} | ||
else { | ||
const between = Comments.findBetween(this.node, comment.startPosition, comment.endPosition); | ||
if (between !== null) { | ||
attachedComments.push({ | ||
value: comment.value, | ||
placement: 'between', | ||
between, | ||
}); | ||
} | ||
else { | ||
attachedComments.push({ | ||
value: comment.value, | ||
placement: 'trailing', | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
function normalizeOptions(options) { | ||
if (options === void 0) { | ||
return { | ||
attachComments: false, | ||
preserveKeyOrder: false, | ||
bigInt: false, | ||
mergeKeys: false, | ||
json: true, | ||
ignoreDuplicateKeys: false, | ||
}; | ||
} | ||
return Object.assign({}, options, { attachComments: options.attachComments === true, preserveKeyOrder: options.preserveKeyOrder === true, bigInt: options.bigInt === true, mergeKeys: options.mergeKeys === true, json: options.json !== false, ignoreDuplicateKeys: options.ignoreDuplicateKeys !== false }); | ||
} | ||
//# sourceMappingURL=parseWithPointers.js.map |
import { IParserResult, Optional } from '@stoplight/types'; | ||
import * as YAMLAstParser from '@stoplight/yaml-ast-parser'; | ||
import { Kind, ScalarType } from '@stoplight/yaml-ast-parser'; | ||
import { DumpOptions, Kind, ScalarType } from '@stoplight/yaml-ast-parser'; | ||
export interface IParseOptions extends YAMLAstParser.LoadOptions { | ||
@@ -9,2 +9,3 @@ json?: boolean; | ||
preserveKeyOrder?: boolean; | ||
attachComments?: boolean; | ||
} | ||
@@ -43,3 +44,6 @@ export declare type YAMLBaseNode<K extends Kind> = Omit<YAMLAstParser.YAMLNode, 'kind' | 'parent'> & { | ||
export declare type YAMLNode = YAMLAnchorReference | YAMLIncludeReference | YAMLScalar | YAMLMap | YAMLMapping | YAMLSequence; | ||
export declare type YamlParserResult<T> = IParserResult<T, YAMLNode, number[], IParseOptions>; | ||
export declare type YamlComments = NonNullable<DumpOptions['comments']>; | ||
export declare type YamlParserResult<T> = IParserResult<T, YAMLNode, number[], IParseOptions> & { | ||
comments: YamlComments; | ||
}; | ||
export { Kind, ScalarType }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
81309
928
0
+ Added@stoplight/types@14.1.1(transitive)
+ Added@stoplight/yaml-ast-parser@0.0.50(transitive)
- Removed@stoplight/types@13.20.0(transitive)
- Removed@stoplight/yaml-ast-parser@0.0.48(transitive)
Updated@stoplight/types@^14.1.1