Exclude inline comments from raw value reads

rawValue and the coercion/malformed paths now stop at the quote-aware
inline-comment boundary, so 'title: 2048  # note' coerces to "2048"
and a read-then-write no longer compounds the comment (pinned
idempotent). Strictly read-side; round-trip bytes untouched. +6 tests
(124 total).

Claude-Session: https://claude.ai/code/session_018BjQRYBR6jQja3jCRi5S3A
This commit is contained in:
2026-07-26 16:10:32 -04:00
parent 4085dd7a46
commit 5a459f0ee4
2 changed files with 110 additions and 20 deletions
+69
View File
@@ -459,6 +459,35 @@ struct FrontmatterAccessTests {
#expect(document.rawValue(for: "labels") == "[a, b, c]")
#expect(document.rawValue(for: "schema") == "1")
}
/// A trailing comment belongs to the line, not to the value reads stop at it.
@Test func rawValueStopsAtAnInlineComment() throws {
let document = try FrontmatterDocument.parse(Fixture.rich)
#expect(document.rawValue(for: "project") == "lanework")
}
/// but a `#` inside a quoted scalar is value text, and a multi-line value is never scanned.
@Test func rawValueKeepsAHashThatIsNotAComment() throws {
let text = """
---
quoted: "hash # inside"
single: 'hash # inside'
both: "hash # inside" # and a real one
flow: [a, "b # c"] # note
block: |
text # not a comment out here either
---
body
"""
let document = try FrontmatterDocument.parse(text)
#expect(document.rawValue(for: "quoted") == "\"hash # inside\"")
#expect(document.rawValue(for: "single") == "'hash # inside'")
#expect(document.rawValue(for: "both") == "\"hash # inside\"")
#expect(document.rawValue(for: "flow") == "[a, \"b # c\"]")
#expect(document.rawValue(for: "block") == "|\n text # not a comment out here either")
#expect(document.serialized() == text)
}
}
// MARK: - Strict fields
@@ -526,6 +555,32 @@ struct FrontmatterLenientFieldTests {
#expect(try document("icon: 2026-07-26T16:41:38Z").icon == .valid("2026-07-26T16:41:38Z"))
}
/// The comment on a value line belongs to the line, not to the value: the source text a
/// wrong-typed scalar coerces to stops where the comment starts.
@Test func aTrailingCommentIsNotPartOfACoercedValue() throws {
#expect(try document("title: 2048 # note").title == .valid("2048"))
#expect(try document("title: true # note").title == .valid("true"))
#expect(try document("background: 42\t# tabbed").background == .valid("42"))
#expect(try document("icon: 2026-07-26T16:41:38Z # when").icon == .valid("2026-07-26T16:41:38Z"))
}
/// A `#` inside a quoted scalar is value text the quotes are what make `#ff8800` writable
/// at all, so a read must not treat it as a comment.
@Test func aHashInsideAQuotedValueIsNotTrimmed() throws {
#expect(try document("title: \"2048 # note\"").title == .valid("2048 # note"))
#expect(try document("background: \"#ff8800\"").background == .valid("#ff8800"))
#expect(try document("background: \"#ff8800\" # brand orange").background == .valid("#ff8800"))
}
/// A sequence or mapping has no scalar reading at all; the raw text it falls back to stops at
/// the comment like every other read.
@Test func malformedRawStopsAtAnInlineComment() throws {
#expect(try document("background: [red, blue] # a palette").background == .malformed(raw: "[red, blue]"))
#expect(try document("title: {a: 1} # a mapping").title == .malformed(raw: "{a: 1}"))
#expect(try document("width: wide # roughly").width == .malformed(raw: "wide"))
#expect(try document("order: banana # not a number").order == .malformed(raw: "banana"))
}
@Test func quotedStringLenientValuesAreUnaffectedByCoercion() throws {
#expect(try document("title: \"2048\"").title == .valid("2048"))
#expect(try document("title: \"true\"").title == .valid("true"))
@@ -774,6 +829,20 @@ struct FrontmatterInlineCommentTests {
#expect(document.serialized() == "---\norder: 8192 # keep at top\n---\nbody\n")
}
/// Reading a value and writing it straight back must leave one comment, not two the read
/// stops at the comment, the write re-splices it.
@Test func aReadThenWriteDoesNotCompoundTheComment() throws {
var document = try FrontmatterDocument.parse("---\ntitle: 2048 # note\n---\nbody\n")
#expect(document.title == .valid("2048"))
document.set("title", to: .string(document.title.value ?? ""))
#expect(document.serialized() == "---\ntitle: \"2048\" # note\n---\nbody\n")
document.set("title", to: .string(document.title.value ?? ""))
#expect(document.serialized() == "---\ntitle: \"2048\" # note\n---\nbody\n")
#expect(try FrontmatterDocument.parse(document.serialized()).title == .valid("2048"))
}
@Test func theCommentSurvivesAReparse() throws {
var document = try FrontmatterDocument.parse("---\norder: 3072 # keep at top\n---\nbody\n")
document.set("order", to: .double(4096))