Correct the vCard 3 parameter parser so quoted parameter values are
consumed according to the MIME-DIR grammar instead of failing
immediately on the opening double quote.
The fix explicitly advances past the opening quote, reads the quoted
qsafe-char sequence, and strips the surrounding quotes from the returned
parameter value. Unquoted parameter handling is unchanged.
Add private parser coverage for quoted parameter values and quoted
values containing commas, plus a public regression test showing that
quoted LANGUAGE and TYPE parameters are accepted by the vCard 3 parser.
AI-Assisted: yes
AI-Tool: OpenAI Codex / gpt-5.4 xhigh
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
Decode ENCODING=b payloads for PHOTO, LOGO, SOUND, and KEY when parsing
so serializing a parsed card does not base64-encode already encoded wire
data a second time. Add regression coverage for both inline binary and
VALUE=uri round-trips.
AI-Assisted: yes
AI-Tool: OpenAI Codex /gpt-5.4 xhigh
- Parsers and serializers are now present for all property types.
- Tests exist to cover parsing for most value types. Many property types
share the same parsing logic based on their value type. We have
created unit tests to cover each value type, not neccesarily all
properties individually.
- Unify the naming pattern of types and enums. Specifically:
- use `VC_Param` instead of `VCParam`. The goal here is to make the
important information (Param, Source, PropertyName, etc.) easy to
see at a glance while preserving a prefix that allows multiple
implementation to coexist (VC3_Source vs. VC4_Source) and also be
easily distinguishable at a glance.
- use `pnName` instead of `cnName`. The VCard standard refers to each
line of data as a "content line," so the original name of each was
"Content." However, the spec more commonly refers to each piece of
data as a "property." There is a 1-to-1 mapping of content lines to
property instances, but property is a more accurate name.
- Introduce the idea of property cardinality to the VCard3
implementation. The spec does not tightly define property cardinality,
but implies it with statements like "if the NAME type is present, then
*its* value is *the* displayable, presentation text associated..."
(emphasis added). Similar language implies some properties must be
present exactly once (FN, N, VERSION) or at most once (NAME, PROFILE,
SOURCE, BDAY, CATEGORIES, PRODID, REV, SORT-STRING, UID). Any other
properties are assumed to be allowed any number of times (including
0).
In the case of a VCard that contains multiple instances of properties
expected to be singular, the parser will still parse and store these
properties. They can be accessed via the `vcard#allPropsOfType`
function. For example:
# vc3 is a VCard3
allPropsOfType[VC3_N](vc3)
If we see over the course of time that other implementations regularly
use multiple instances of properties we have expected to be singular,
we are open to changing the contract to treat them so (though this
may be a breaking change).
- Refactor the VCard3 implementation to use generated property
accessors, following a similar pattern to the new VCard4
implementation.
- Remove the accessor definitions that allow access via the content seq
directly (`vc3.content.name` for example). There really isn't a reason
for this use-case and the library is simpler without exposing this.
- newVC3_Tel was not assigning the value provided to the constructed
object.
- Private unit tests were run every time the code was compiled due to
how the unittest library works. These now only run as part of the unit
tests with `nimble test`.