From 466e47fd368163816cdeecb03ab0f8a6b8f0ad02 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Sat, 28 Mar 2026 10:04:44 -0500 Subject: [PATCH] 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 --- src/vcard/private/internals.nim | 3 ++- src/vcard/private/lexer.nim | 9 ++++++++- src/vcard/vcard3.nim | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/vcard/private/internals.nim b/src/vcard/private/internals.nim index eaaadc5..dfb8ac5 100644 --- a/src/vcard/private/internals.nim +++ b/src/vcard/private/internals.nim @@ -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. p.setBookmark + let validChars = ALPHA_NUM + {'-'} var ch = p.read - while ALPHA_NUM.contains(ch): ch = p.read + while validChars.contains(ch): ch = p.read if (ch == '.'): result = some(readSinceBookmark(p)[0..^2]) diff --git a/src/vcard/private/lexer.nim b/src/vcard/private/lexer.nim index 25011f7..c0e4be4 100644 --- a/src/vcard/private/lexer.nim +++ b/src/vcard/private/lexer.nim @@ -202,7 +202,7 @@ proc isLineWrap(vcl: var VCardLexer, allowRefill = true): bool = # at least three characters in the buffer else: 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 = ## 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") + # "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": block: var l: VCardLexer diff --git a/src/vcard/vcard3.nim b/src/vcard/vcard3.nim index 29751bb..6b46772 100644 --- a/src/vcard/vcard3.nim +++ b/src/vcard/vcard3.nim @@ -1272,6 +1272,13 @@ proc runVCard3PrivateTests*() = assert g.isSome 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": block: var p = initParser("BEGIN:VCARD")