Fix vCard folding and group parsing rules

Accept horizontal-tab continuations when unfolding content lines and
allow hyphens in group names, matching the MIME-DIR and vCard grammar.
Also add focused private tests covering both cases.

AI-Assisted: yes
AI-Tool: OpenAI Codex / gpt-5.4 xhigh
This commit is contained in:
2026-03-28 10:04:44 -05:00
parent 3d2d40667d
commit 466e47fd36
3 changed files with 17 additions and 2 deletions

View File

@@ -163,8 +163,9 @@ proc readGroup*(p: var VCardParser): Option[string] =
## name. If there is not a valid group the read position is left unchanged. ## name. If there is not a valid group the read position is left unchanged.
p.setBookmark p.setBookmark
let validChars = ALPHA_NUM + {'-'}
var ch = p.read var ch = p.read
while ALPHA_NUM.contains(ch): ch = p.read while validChars.contains(ch): ch = p.read
if (ch == '.'): if (ch == '.'):
result = some(readSinceBookmark(p)[0..^2]) result = some(readSinceBookmark(p)[0..^2])

View File

@@ -202,7 +202,7 @@ proc isLineWrap(vcl: var VCardLexer, allowRefill = true): bool =
# at least three characters in the buffer # at least three characters in the buffer
else: else:
return vcl.buffer[wrappedIdx(vcl.pos + 1)] == '\n' and return vcl.buffer[wrappedIdx(vcl.pos + 1)] == '\n' and
vcl.buffer[wrappedIdx(vcl.pos + 2)] == ' ' vcl.buffer[wrappedIdx(vcl.pos + 2)] in {' ', '\t'}
proc read*(vcl: var VCardLexer, peek = false): char = proc read*(vcl: var VCardLexer, peek = false): char =
## Read one byte off of the input stream. By default this will advance the ## Read one byte off of the input stream. By default this will advance the
@@ -392,6 +392,13 @@ proc runVcardLexerPrivateTests*() =
assert l.readExpected("line wrap\r\nline 2") assert l.readExpected("line wrap\r\nline 2")
# "handles wrapped lines with tabs":
block:
var l: VCardLexer
l.open(newStringStream("line\r\n\twrap\r\nline 2"), 3)
assert l.readExpected("linewrap\r\nline 2")
# "fillBuffer correctness": # "fillBuffer correctness":
block: block:
var l: VCardLexer var l: VCardLexer

View File

@@ -1272,6 +1272,13 @@ proc runVCard3PrivateTests*() =
assert g.isSome assert g.isSome
assert g.get == "mygroup" assert g.get == "mygroup"
# "readGroup with hyphen":
block:
var p = initParser("item-1.BEGIN:VCARD")
let g = p.readGroup
assert g.isSome
assert g.get == "item-1"
# "readGroup without group": # "readGroup without group":
block: block:
var p = initParser("BEGIN:VCARD") var p = initParser("BEGIN:VCARD")