Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: eemeli/yaml
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.4.4
Choose a base ref
...
head repository: eemeli/yaml
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1b8fde6717c096446d4b1cf9e21ef1fb87090385
Choose a head ref
  • 3 commits
  • 12 files changed
  • 1 contributor

Commits on Jun 8, 2024

  1. Copy the full SHA
    4e66d72 View commit details
  2. test: Obey yaml-test-suite skip instructions

    eemeli committed Jun 8, 2024
    Copy the full SHA
    f3c7d03 View commit details
  3. 2.4.5

    eemeli committed Jun 8, 2024
    Copy the full SHA
    1b8fde6 View commit details
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yaml",
"version": "2.4.4",
"version": "2.4.5",
"license": "ISC",
"author": "Eemeli Aro <eemeli@gmail.com>",
"repository": "github:eemeli/yaml",
1 change: 1 addition & 0 deletions src/compose/compose-doc.ts
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ export function composeDoc<
next: value ?? end?.[0],
offset,
onError,
parentIndent: 0,
startOnNewline: true
})
if (props.found) {
2 changes: 1 addition & 1 deletion src/compose/compose-scalar.ts
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ export function composeScalar(
) {
const { value, type, comment, range } =
token.type === 'block-scalar'
? resolveBlockScalar(token, ctx.options.strict, onError)
? resolveBlockScalar(ctx, token, onError)
: resolveFlowScalar(token, ctx.options.strict, onError)

const tagName = tagToken
2 changes: 2 additions & 0 deletions src/compose/resolve-block-map.ts
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ export function resolveBlockMap(
next: key ?? sep?.[0],
offset,
onError,
parentIndent: bm.indent,
startOnNewline: true
})
const implicitKey = !keyProps.found
@@ -83,6 +84,7 @@ export function resolveBlockMap(
next: value,
offset: keyNode.range[2],
onError,
parentIndent: bm.indent,
startOnNewline: !key || key.type === 'block-scalar'
})
offset = valueProps.end
9 changes: 7 additions & 2 deletions src/compose/resolve-block-scalar.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Range } from '../nodes/Node.js'
import { Scalar } from '../nodes/Scalar.js'
import type { BlockScalar } from '../parse/cst.js'
import type { ComposeContext } from './compose-node.js'
import type { ComposeErrorHandler } from './composer.js'

export function resolveBlockScalar(
ctx: ComposeContext,
scalar: BlockScalar,
strict: boolean,
onError: ComposeErrorHandler
): {
value: string
@@ -14,7 +15,7 @@ export function resolveBlockScalar(
range: Range
} {
const start = scalar.offset
const header = parseBlockScalarHeader(scalar, strict, onError)
const header = parseBlockScalarHeader(scalar, ctx.options.strict, onError)
if (!header)
return { value: '', type: null, comment: '', range: [start, start, start] }
const type = header.mode === '>' ? Scalar.BLOCK_FOLDED : Scalar.BLOCK_LITERAL
@@ -56,6 +57,10 @@ export function resolveBlockScalar(
}
if (header.indent === 0) trimIndent = indent.length
contentStart = i
if (trimIndent === 0 && !ctx.atRoot) {
const message = 'Block scalar values in collections must be indented'
onError(offset, 'BAD_INDENT', message)
}
break
}
offset += indent.length + content.length + 1
1 change: 1 addition & 0 deletions src/compose/resolve-block-seq.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ export function resolveBlockSeq(
next: value,
offset,
onError,
parentIndent: bs.indent,
startOnNewline: true
})
if (!props.found) {
2 changes: 2 additions & 0 deletions src/compose/resolve-flow-collection.ts
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@ export function resolveFlowCollection(
next: key ?? sep?.[0],
offset,
onError,
parentIndent: fc.indent,
startOnNewline: false
})
if (!props.found) {
@@ -130,6 +131,7 @@ export function resolveFlowCollection(
next: value,
offset: keyNode.range[2],
onError,
parentIndent: fc.indent,
startOnNewline: false
})

27 changes: 21 additions & 6 deletions src/compose/resolve-props.ts
Original file line number Diff line number Diff line change
@@ -7,12 +7,21 @@ export interface ResolvePropsArg {
next: Token | null | undefined
offset: number
onError: ComposeErrorHandler
parentIndent: number
startOnNewline: boolean
}

export function resolveProps(
tokens: SourceToken[],
{ flow, indicator, next, offset, onError, startOnNewline }: ResolvePropsArg
{
flow,
indicator,
next,
offset,
onError,
parentIndent,
startOnNewline
}: ResolvePropsArg
) {
let spaceBefore = false
let atNewline = startOnNewline
@@ -43,7 +52,7 @@ export function resolveProps(
reqSpace = false
}
if (tab) {
if (token.type !== 'comment') {
if (atNewline && token.type !== 'comment' && token.type !== 'newline') {
onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation')
}
tab = null
@@ -55,9 +64,8 @@ export function resolveProps(
// In a flow collection, only the parser handles indent.
if (
!flow &&
atNewline &&
(indicator !== 'doc-start' || next?.type !== 'flow-collection') &&
token.source[0] === '\t'
token.source.includes('\t')
) {
tab = token
}
@@ -132,7 +140,8 @@ export function resolveProps(
`Unexpected ${token.source} in ${flow ?? 'collection'}`
)
found = token
atNewline = false
atNewline =
indicator === 'seq-item-ind' || indicator === 'explicit-key-ind'
hasSpace = false
break
case 'comma':
@@ -167,7 +176,13 @@ export function resolveProps(
'Tags and anchors must be separated from the next token by white space'
)
}
if (tab) onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation')
if (
tab &&
((atNewline && tab.indent <= parentIndent) ||
next?.type === 'block-map' ||
next?.type === 'block-seq')
)
onError(tab, 'TAB_AS_INDENT', 'Tabs are not allowed as indentation')
return {
comma,
found,
7 changes: 6 additions & 1 deletion src/parse/cst-scalar.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ComposeContext } from '../compose/compose-node.js'
import type { ComposeErrorHandler } from '../compose/composer.js'
import { resolveBlockScalar } from '../compose/resolve-block-scalar.js'
import { resolveFlowScalar } from '../compose/resolve-flow-scalar.js'
@@ -55,7 +56,11 @@ export function resolveAsScalar(
case 'double-quoted-scalar':
return resolveFlowScalar(token, strict, _onError)
case 'block-scalar':
return resolveBlockScalar(token, strict, _onError)
return resolveBlockScalar(
{ options: { strict } } as ComposeContext,
token,
_onError
)
}
}
return null
14 changes: 12 additions & 2 deletions src/parse/lexer.ts
Original file line number Diff line number Diff line change
@@ -551,13 +551,23 @@ export class Lexer {
nl = this.buffer.length
}
}
if (!this.blockScalarKeep) {

// Trailing insufficiently indented tabs are invalid.
// To catch that during parsing, we include them in the block scalar value.
let i = nl + 1
ch = this.buffer[i]
while (ch === ' ') ch = this.buffer[++i]
if (ch === '\t') {
while (ch === '\t' || ch === ' ' || ch === '\r' || ch === '\n')
ch = this.buffer[++i]
nl = i - 1
} else if (!this.blockScalarKeep) {
do {
let i = nl - 1
let ch = this.buffer[i]
if (ch === '\r') ch = this.buffer[--i]
const lastChar = i // Drop the line if last char not more indented
while (ch === ' ' || ch === '\t') ch = this.buffer[--i]
while (ch === ' ') ch = this.buffer[--i]
if (ch === '\n' && i >= this.pos && i + 1 + indent > lastChar) nl = i
else break
} while (true)
19 changes: 4 additions & 15 deletions tests/yaml-test-suite.ts
Original file line number Diff line number Diff line change
@@ -13,24 +13,12 @@ type TestCase = {
dump?: string
}

type TestFile = [TestCase & { name: string }, ...TestCase[]]
type TestFile = [TestCase & { name: string; skip?: boolean }, ...TestCase[]]

const skip: Record<string, boolean | string[]> = {
'2JQS/0': ['test.event', 'errors'], //
'2JQS/0': ['test.event', 'errors'], // duplicate empty keys are invalid
'9MMA/0': ['errors'], // allow stream with directive & no docs
'SF5V/0': ['errors'], // allow duplicate %YAML directives

// FIXME recent upstream additions
'DK95/0': true,
'DK95/4': true,
'DK95/5': true,
'Y79Y/4': ['errors'],
'Y79Y/5': ['errors'],
'Y79Y/6': ['errors'],
'Y79Y/7': ['errors'],
'Y79Y/8': ['errors'],
'Y79Y/9': ['errors'],
'ZYU8/2': ['errors']
'SF5V/0': ['errors'] // allow duplicate %YAML directives
}

function testJsonMatch(docs: Document[], json: string) {
@@ -67,6 +55,7 @@ for (const fn of readdirSync(testRoot)) {
const file = readFileSync(path, 'utf8')
const testData = parse(file) as TestFile
if (!Array.isArray(testData)) throw new Error(`Unsupported test file: ${fn}`)
if (testData[0].skip) continue

const name = `${id}: ${testData[0].name}`
for (let i = 0; i < testData.length; ++i) {