fix(parsing): classify the keep block-scalar chomping indicator

The scanner consumed the `+` indicator of a `|+` / `>+` block scalar but
mapped it to nothing, so keep was silently treated as clip, and a scanner
test baked that in. Add a `keep` case to BlockScalarChomping, recognize
`+` in the header scanner, and correct the test. Full keep value semantics
(preserving trailing blank lines) depend on scanner blank-line capture and
are tracked in #57; this commit fixes the token classification only.
This commit is contained in:
Mihaela M 2026-06-26 07:50:07 +02:00
parent 44abc12e80
commit fadde56a05
5 changed files with 19 additions and 3 deletions

View File

@ -22,6 +22,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
win, earlier sources win, inherited-then-local ordering) now have one source
of truth. No behavior change.
### Fixed
- Classify the block scalar keep chomping indicator (`|+` / `>+`) as a distinct
`keep` chomping instead of silently treating it as clip. Full keep semantics
(preserving trailing blank lines) still depend on scanner blank-line capture,
tracked in #57.
### Documentation
- Correct `SECURITY.md`: fix the reporting contact address and replace the

View File

@ -2,6 +2,7 @@ extension PureYAML.Parsing {
enum BlockScalarChomping: String, Equatable, CustomStringConvertible {
case clip
case strip
case keep
var description: String {
rawValue

View File

@ -301,6 +301,8 @@ extension PureYAML.Parsing.Scanner {
while let character = state.reader.peek(), isBlockScalarHeaderCharacter(character) {
if character == "-" {
chomping = .strip
} else if character == "+" {
chomping = .keep
} else if character.isNumber {
indentationIndicator = Int(String(character))
}

View File

@ -249,7 +249,13 @@ extension PureYAML.Parsing.TokenEventParser {
switch chomping {
case .strip:
return content
case .clip:
case .clip, .keep:
// Clip and keep currently coincide: both append the single final
// line break. They diverge only over trailing blank lines, which the
// scanner does not yet capture into `lines`, so keep cannot preserve
// them today. That gap (and the related dropping of internal blank
// lines and folded-paragraph breaks) is tracked separately. Strip is
// the only branch that omits the final break.
return content + "\n"
}
}

View File

@ -333,7 +333,7 @@ private func expectFlowAndBlockScalarKinds(_ tokens: [String]) {
"mappingKey",
"scalar value=\"text\" style=plain",
"mappingValue",
"blockScalarHeader style=literal",
"blockScalarHeader style=literal chomping=keep",
"indent width=2",
"scalar value=\"line\" style=plain",
"dedent width=0",
@ -357,7 +357,7 @@ private func expectFlowAndBlockScalarRequiredKinds(_ tokens: [String]) {
"tag value=!Thing",
"anchor name=item",
"alias name=item",
"blockScalarHeader style=literal",
"blockScalarHeader style=literal chomping=keep",
"blockScalarHeader style=folded chomping=strip",
])
}