Fix vCard 3 text escaping and decoding

Implement RFC 2426 text escaping consistently across vCard 3
serialization and parsing.

On serialization, escape backslashes, newlines, semicolons, and commas
for simple text properties, structured text components, and list-valued
text properties so generated FN, N, ADR, ORG, CATEGORIES, and related
properties are spec-compliant on the wire.

On parsing, decode escaped text for the properties that were previously
read as raw values: FN, NICKNAME, LABEL, MAILER, TITLE, ROLE, PRODID,
and SORT-STRING. This preserves existing structured-text parsing for N,
ADR, NOTE, ORG, and CATEGORIES while fixing the direct raw-value
mismatch identified in the review.

Add regression coverage for both directions: parsing escaped text values
and serializing escaped simple, structured, and list text values.

AI-Assisted: yes
AI-Tool: OpenAI Codex / gpt-5.4 xhigh
This commit is contained in:
2026-03-28 10:27:30 -05:00
parent 35377f5a25
commit 201556ecbe
2 changed files with 94 additions and 23 deletions

View File

@@ -112,6 +112,35 @@ suite "vcard/vcard3":
check parsed.fn.value == "Jane, Smith; Esq.\\Office\nSecond line"
test "spec: affected text properties decode RFC 2426 escapes when parsing":
let parsed = parseSingleVCard3(vcard3Doc(
"VERSION:3.0",
"FN:John Smith",
"N:Smith;John;;;",
r"NICKNAME:Johnny\, Jr.\nTwo",
r"LABEL:123 Main St.\nSuite 100\; Mail Stop",
r"MAILER:Mailer\\Pro",
r"TITLE:Lead\; Engineer",
r"ROLE:Ops\, Support",
r"PRODID:-//Example\\Corp//EN",
r"SORT-STRING:Smith\, John"))
check:
parsed.nickname.isSome
parsed.nickname.get.value == "Johnny, Jr.\nTwo"
parsed.label.len == 1
parsed.label[0].value == "123 Main St.\nSuite 100; Mail Stop"
parsed.mailer.len == 1
parsed.mailer[0].value == "Mailer\\Pro"
parsed.title.len == 1
parsed.title[0].value == "Lead; Engineer"
parsed.role.len == 1
parsed.role[0].value == "Ops, Support"
parsed.prodid.isSome
parsed.prodid.get.value == "-//Example\\Corp//EN"
parsed.sortstring.isSome
parsed.sortstring.get.value == "Smith, John"
test "spec: simple text values escape special characters when serializing":
let vc = newMinimalVCard3()
vc.set(newVC3_Fn("Jane, Smith; Esq.\\Office\nSecond line"))