@pipobscure/vcard 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Text escaping and unescaping for vCard v4 (RFC 6350 section 3.4)
3
+ *
4
+ * In TEXT value types:
5
+ * \\ → \
6
+ * \n or \N → newline (U+000A)
7
+ * \, → ,
8
+ * \; → ;
9
+ *
10
+ * On output, these characters must be escaped:
11
+ * \ → \\
12
+ * newline → \n
13
+ * , → \, (only in compound/list fields)
14
+ * ; → \; (always in structured fields)
15
+ */
16
+ /** Unescape a single text component (after splitting on `;` or `,`) */
17
+ export declare function unescapeText(s: string): string;
18
+ /** Escape a text value for use as a TEXT property value (no structural chars) */
19
+ export declare function escapeText(s: string): string;
20
+ /**
21
+ * Escape a text value that is a component of a structured/list property.
22
+ * The caller is responsible for joining components with `;` or `,`.
23
+ * Only escapes `\`, `\n`, and `;` — the `,` within a component (for list-within-struct).
24
+ */
25
+ export declare function escapeStructuredComponent(s: string): string;
26
+ /**
27
+ * Split a structured value on `;`, respecting backslash escapes.
28
+ * Returns raw (still-escaped) components.
29
+ */
30
+ export declare function splitStructured(value: string): string[];
31
+ /**
32
+ * Split a compound value on `,`, respecting backslash escapes.
33
+ * Returns raw (still-escaped) items.
34
+ */
35
+ export declare function splitList(value: string): string[];
36
+ /** Unescape and split a structured value into its components */
37
+ export declare function parseStructured(value: string): string[];
38
+ /** Unescape and split a list value into its items */
39
+ export declare function parseList(value: string): string[];
40
+ /** Unescape and split a structured-with-lists value.
41
+ * Each `;`-separated component may itself be a `,`-separated list.
42
+ */
43
+ export declare function parseStructuredList(value: string): string[][];
44
+ /**
45
+ * Check whether a parameter value needs quoting (RFC 6350 section 5.1).
46
+ * Param values containing `:`, `;`, or `,` must be quoted.
47
+ */
48
+ export declare function needsParamQuoting(value: string): boolean;
49
+ /**
50
+ * Quote a parameter value if necessary.
51
+ * Existing double-quotes within the value are escaped as \".
52
+ */
53
+ export declare function quoteParamValue(value: string): string;
54
+ /**
55
+ * Unquote a parameter value (remove surrounding quotes if present,
56
+ * unescape internal \" sequences).
57
+ */
58
+ export declare function unquoteParamValue(value: string): string;
59
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ9C;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBvD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBjD;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvD;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAE7D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvD"}
package/dist/escape.js ADDED
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Text escaping and unescaping for vCard v4 (RFC 6350 section 3.4)
3
+ *
4
+ * In TEXT value types:
5
+ * \\ → \
6
+ * \n or \N → newline (U+000A)
7
+ * \, → ,
8
+ * \; → ;
9
+ *
10
+ * On output, these characters must be escaped:
11
+ * \ → \\
12
+ * newline → \n
13
+ * , → \, (only in compound/list fields)
14
+ * ; → \; (always in structured fields)
15
+ */
16
+ /** Unescape a single text component (after splitting on `;` or `,`) */
17
+ export function unescapeText(s) {
18
+ return s.replace(/\\(\\|n|N|,|;)/g, (_, c) => {
19
+ if (c === 'n' || c === 'N')
20
+ return '\n';
21
+ if (c === '\\')
22
+ return '\\';
23
+ if (c === ',')
24
+ return ',';
25
+ if (c === ';')
26
+ return ';';
27
+ return c;
28
+ });
29
+ }
30
+ /** Escape a text value for use as a TEXT property value (no structural chars) */
31
+ export function escapeText(s) {
32
+ return s
33
+ .replace(/\\/g, '\\\\')
34
+ .replace(/\n/g, '\\n')
35
+ .replace(/,/g, '\\,')
36
+ .replace(/;/g, '\\;');
37
+ }
38
+ /**
39
+ * Escape a text value that is a component of a structured/list property.
40
+ * The caller is responsible for joining components with `;` or `,`.
41
+ * Only escapes `\`, `\n`, and `;` — the `,` within a component (for list-within-struct).
42
+ */
43
+ export function escapeStructuredComponent(s) {
44
+ return s
45
+ .replace(/\\/g, '\\\\')
46
+ .replace(/\n/g, '\\n')
47
+ .replace(/;/g, '\\;')
48
+ .replace(/,/g, '\\,');
49
+ }
50
+ /**
51
+ * Split a structured value on `;`, respecting backslash escapes.
52
+ * Returns raw (still-escaped) components.
53
+ */
54
+ export function splitStructured(value) {
55
+ const parts = [];
56
+ let current = '';
57
+ for (let i = 0; i < value.length; i++) {
58
+ const ch = value[i];
59
+ if (ch === '\\' && i + 1 < value.length) {
60
+ current += ch + value[++i];
61
+ }
62
+ else if (ch === ';') {
63
+ parts.push(current);
64
+ current = '';
65
+ }
66
+ else {
67
+ current += ch;
68
+ }
69
+ }
70
+ parts.push(current);
71
+ return parts;
72
+ }
73
+ /**
74
+ * Split a compound value on `,`, respecting backslash escapes.
75
+ * Returns raw (still-escaped) items.
76
+ */
77
+ export function splitList(value) {
78
+ const parts = [];
79
+ let current = '';
80
+ for (let i = 0; i < value.length; i++) {
81
+ const ch = value[i];
82
+ if (ch === '\\' && i + 1 < value.length) {
83
+ current += ch + value[++i];
84
+ }
85
+ else if (ch === ',') {
86
+ parts.push(current);
87
+ current = '';
88
+ }
89
+ else {
90
+ current += ch;
91
+ }
92
+ }
93
+ parts.push(current);
94
+ return parts;
95
+ }
96
+ /** Unescape and split a structured value into its components */
97
+ export function parseStructured(value) {
98
+ return splitStructured(value).map(unescapeText);
99
+ }
100
+ /** Unescape and split a list value into its items */
101
+ export function parseList(value) {
102
+ return splitList(value).map(unescapeText);
103
+ }
104
+ /** Unescape and split a structured-with-lists value.
105
+ * Each `;`-separated component may itself be a `,`-separated list.
106
+ */
107
+ export function parseStructuredList(value) {
108
+ return splitStructured(value).map(component => parseList(component));
109
+ }
110
+ /**
111
+ * Check whether a parameter value needs quoting (RFC 6350 section 5.1).
112
+ * Param values containing `:`, `;`, or `,` must be quoted.
113
+ */
114
+ export function needsParamQuoting(value) {
115
+ return /[;:,"]/.test(value);
116
+ }
117
+ /**
118
+ * Quote a parameter value if necessary.
119
+ * Existing double-quotes within the value are escaped as \".
120
+ */
121
+ export function quoteParamValue(value) {
122
+ if (!needsParamQuoting(value))
123
+ return value;
124
+ return '"' + value.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
125
+ }
126
+ /**
127
+ * Unquote a parameter value (remove surrounding quotes if present,
128
+ * unescape internal \" sequences).
129
+ */
130
+ export function unquoteParamValue(value) {
131
+ if (value.startsWith('"') && value.endsWith('"') && value.length >= 2) {
132
+ return value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
133
+ }
134
+ return value;
135
+ }
136
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE;QACnD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACxC,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,GAAG,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,GAAG,CAAC;QAC1B,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC;SACL,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,CAAS;IACjD,OAAO,CAAC;SACL,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACxC,OAAO,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAE,CAAC;QAC9B,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACxC,OAAO,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAE,CAAC;QAC9B,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAClD,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * vCard v4 generator — RFC 6350
3
+ *
4
+ * Strict output:
5
+ * - CRLF line endings (§3.2)
6
+ * - Line folding at 75 octets (§3.2)
7
+ * - VERSION:4.0 first property after BEGIN:VCARD
8
+ * - Proper text escaping
9
+ * - Parameter values quoted when necessary
10
+ */
11
+ import type { ParameterMap } from './types.js';
12
+ import { Property } from './property.js';
13
+ /**
14
+ * Fold a content line to at most 75 octets per line (RFC 6350 §3.2).
15
+ * Continuation lines begin with a single space.
16
+ * Counts UTF-8 bytes, not characters.
17
+ */
18
+ export declare function foldLine(line: string): string;
19
+ /**
20
+ * Serialize a ParameterMap to string (without leading semicolon).
21
+ * Multiple values for the same parameter are joined with commas.
22
+ * Values containing special characters are quoted.
23
+ */
24
+ export declare function serializeParameters(params: ParameterMap): string;
25
+ /**
26
+ * Serialize a single Property to a folded content line string (with CRLF).
27
+ */
28
+ export declare function serializeProperty(prop: Property): string;
29
+ export interface GenerateOptions {
30
+ /**
31
+ * Whether to validate the vCard before generating.
32
+ * Default: true
33
+ */
34
+ validate?: boolean;
35
+ /**
36
+ * Whether to include a PRODID property.
37
+ * If a string is provided, it is used as the PRODID value.
38
+ * Default: false
39
+ */
40
+ prodid?: boolean | string;
41
+ }
42
+ /**
43
+ * Serialize a list of properties to a vCard string.
44
+ * Handles VERSION insertion and ordering.
45
+ *
46
+ * @throws VCardError if validation is enabled and the vCard is invalid
47
+ */
48
+ export declare function serializeVCard(properties: Property[], options?: GenerateOptions): string;
49
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAc,MAAM,eAAe,CAAC;AAMrD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmC7C;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAgBhE;AAID;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAQxD;AAID,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAID;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,QAAQ,EAAE,EACtB,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAoBR"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * vCard v4 generator — RFC 6350
3
+ *
4
+ * Strict output:
5
+ * - CRLF line endings (§3.2)
6
+ * - Line folding at 75 octets (§3.2)
7
+ * - VERSION:4.0 first property after BEGIN:VCARD
8
+ * - Proper text escaping
9
+ * - Parameter values quoted when necessary
10
+ */
11
+ import { quoteParamValue } from './escape.js';
12
+ import { VCardError } from './property.js';
13
+ // ── Line folding ──────────────────────────────────────────────────────────
14
+ const MAX_LINE_OCTETS = 75;
15
+ /**
16
+ * Fold a content line to at most 75 octets per line (RFC 6350 §3.2).
17
+ * Continuation lines begin with a single space.
18
+ * Counts UTF-8 bytes, not characters.
19
+ */
20
+ export function foldLine(line) {
21
+ if (Buffer.byteLength(line, 'utf8') <= MAX_LINE_OCTETS) {
22
+ return line + '\r\n';
23
+ }
24
+ const parts = [];
25
+ let start = 0;
26
+ // First segment: 75 octets max.
27
+ // Continuation segments: 74 octets of content + 1-byte leading space = 75.
28
+ let maxBytes = MAX_LINE_OCTETS;
29
+ while (start < line.length) {
30
+ let end = start;
31
+ let octetCount = 0;
32
+ // Advance character by character, counting UTF-8 bytes
33
+ while (end < line.length) {
34
+ const cp = line.codePointAt(end);
35
+ const charBytes = cp > 0xffff ? 4 : cp > 0x7ff ? 3 : cp > 0x7f ? 2 : 1;
36
+ if (octetCount + charBytes > maxBytes)
37
+ break;
38
+ octetCount += charBytes;
39
+ end += cp > 0xffff ? 2 : 1; // surrogate pair awareness
40
+ }
41
+ if (end === start) {
42
+ // Force-include at least one character to avoid infinite loop
43
+ end = start + 1;
44
+ }
45
+ parts.push(line.slice(start, end));
46
+ start = end;
47
+ maxBytes = MAX_LINE_OCTETS - 1; // subsequent lines lose 1 byte to leading space
48
+ }
49
+ return parts.join('\r\n ') + '\r\n';
50
+ }
51
+ // ── Parameter serialization ───────────────────────────────────────────────
52
+ /**
53
+ * Serialize a ParameterMap to string (without leading semicolon).
54
+ * Multiple values for the same parameter are joined with commas.
55
+ * Values containing special characters are quoted.
56
+ */
57
+ export function serializeParameters(params) {
58
+ const parts = [];
59
+ for (const [name, value] of params) {
60
+ if (Array.isArray(value)) {
61
+ if (value.length === 0)
62
+ continue;
63
+ // Multiple values: emit as single NAME=val1,val2 or individual NAME=val for each
64
+ // RFC 6350 §5.1 allows multi-value params
65
+ const joined = value.map(quoteParamValue).join(',');
66
+ parts.push(`${name}=${joined}`);
67
+ }
68
+ else {
69
+ parts.push(`${name}=${quoteParamValue(value)}`);
70
+ }
71
+ }
72
+ return parts.join(';');
73
+ }
74
+ // ── Content line serialization ────────────────────────────────────────────
75
+ /**
76
+ * Serialize a single Property to a folded content line string (with CRLF).
77
+ */
78
+ export function serializeProperty(prop) {
79
+ const namePart = prop.group ? `${prop.group}.${prop.name}` : prop.name;
80
+ const paramStr = serializeParameters(prop.params);
81
+ const separator = paramStr ? `;${paramStr}` : '';
82
+ const value = prop.toContentLine();
83
+ const line = `${namePart}${separator}:${value}`;
84
+ return foldLine(line);
85
+ }
86
+ // ── VCard serialization ───────────────────────────────────────────────────
87
+ /**
88
+ * Serialize a list of properties to a vCard string.
89
+ * Handles VERSION insertion and ordering.
90
+ *
91
+ * @throws VCardError if validation is enabled and the vCard is invalid
92
+ */
93
+ export function serializeVCard(properties, options = {}) {
94
+ const validate = options.validate !== false;
95
+ if (validate) {
96
+ validateForGeneration(properties);
97
+ }
98
+ let output = 'BEGIN:VCARD\r\n';
99
+ output += 'VERSION:4.0\r\n';
100
+ // Properties to emit (skip VERSION — already emitted above)
101
+ // Order: structural first (FN, N), then everything else
102
+ const ordered = orderProperties(properties.filter(p => p.name !== 'VERSION'));
103
+ for (const prop of ordered) {
104
+ output += serializeProperty(prop);
105
+ }
106
+ output += 'END:VCARD\r\n';
107
+ return output;
108
+ }
109
+ // ── Property ordering ─────────────────────────────────────────────────────
110
+ /** Preferred property output order (for readability) */
111
+ const PROPERTY_ORDER = {
112
+ FN: 1,
113
+ N: 2,
114
+ NICKNAME: 3,
115
+ GENDER: 4,
116
+ BDAY: 5,
117
+ ANNIVERSARY: 6,
118
+ ORG: 7,
119
+ TITLE: 8,
120
+ ROLE: 9,
121
+ EMAIL: 10,
122
+ TEL: 11,
123
+ ADR: 12,
124
+ URL: 13,
125
+ IMPP: 14,
126
+ LANG: 15,
127
+ TZ: 16,
128
+ GEO: 17,
129
+ PHOTO: 18,
130
+ LOGO: 19,
131
+ SOUND: 20,
132
+ NOTE: 21,
133
+ CATEGORIES: 22,
134
+ SOURCE: 23,
135
+ XML: 24,
136
+ KEY: 25,
137
+ FBURL: 26,
138
+ CALADRURI: 27,
139
+ CALURI: 28,
140
+ MEMBER: 29,
141
+ RELATED: 30,
142
+ UID: 31,
143
+ REV: 32,
144
+ PRODID: 33,
145
+ KIND: 34,
146
+ CLIENTPIDMAP: 35,
147
+ };
148
+ function orderProperties(properties) {
149
+ return [...properties].sort((a, b) => {
150
+ const oa = PROPERTY_ORDER[a.name] ?? 100;
151
+ const ob = PROPERTY_ORDER[b.name] ?? 100;
152
+ return oa - ob;
153
+ });
154
+ }
155
+ // ── Validation ─────────────────────────────────────────────────────────────
156
+ /**
157
+ * Validate a property list for strict vCard v4 generation.
158
+ * @throws VCardError on first validation failure
159
+ */
160
+ function validateForGeneration(properties) {
161
+ // FN is required (cardinality 1*)
162
+ const fnProps = properties.filter(p => p.name === 'FN');
163
+ if (fnProps.length === 0) {
164
+ throw new VCardError('Missing required property: FN', 'FN');
165
+ }
166
+ // PREF values must be 1–100
167
+ for (const prop of properties) {
168
+ const pref = prop.pref;
169
+ if (pref !== undefined && (pref < 1 || pref > 100 || !Number.isInteger(pref))) {
170
+ throw new VCardError(`PREF parameter on ${prop.name} must be an integer between 1 and 100, got: ${pref}`, prop.name);
171
+ }
172
+ }
173
+ // GENDER sex must be one of M, F, O, N, U, or empty
174
+ for (const prop of properties) {
175
+ if (prop.name === 'GENDER') {
176
+ // GenderProperty has a value field
177
+ const gp = prop;
178
+ const validSex = ['M', 'F', 'O', 'N', 'U', ''];
179
+ if (!validSex.includes(gp.value.sex)) {
180
+ throw new VCardError(`Invalid GENDER sex value: ${gp.value.sex}. Must be one of M, F, O, N, U`, 'GENDER');
181
+ }
182
+ }
183
+ }
184
+ // REV must be a valid timestamp
185
+ for (const prop of properties) {
186
+ if (prop.name === 'REV') {
187
+ const rp = prop;
188
+ if (rp.value instanceof Date && isNaN(rp.value.getTime())) {
189
+ throw new VCardError('REV property contains invalid date', 'REV');
190
+ }
191
+ }
192
+ }
193
+ }
194
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @pipobscure/vcard — A fully featured vCard v4 (RFC 6350) library
3
+ *
4
+ * Provides tolerant parsing and strict generation of vCard data,
5
+ * designed for use with CardDAV.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { VCard, FNProperty, EmailProperty } from '@pipobscure/vcard';
10
+ *
11
+ * // Parse
12
+ * const [contact] = VCard.parse(vcardText);
13
+ * console.log(contact.displayName); // 'Alice Example'
14
+ * console.log(contact.primaryEmail); // 'alice@example.com'
15
+ *
16
+ * // Build
17
+ * const vc = new VCard();
18
+ * vc.fn.push(new FNProperty('Bob Builder'));
19
+ * vc.email.push(new EmailProperty('bob@example.com'));
20
+ * const text = vc.toString(); // strict RFC 6350 output
21
+ * ```
22
+ */
23
+ export { VCard, VCardError } from './vcard.js';
24
+ export { Property, TextProperty, TextListProperty, UriProperty, FNProperty, NProperty, NicknameProperty, PhotoProperty, BDayProperty, AnniversaryProperty, GenderProperty, AdrProperty, TelProperty, EmailProperty, IMPPProperty, LangProperty, TZProperty, GeoProperty, TitleProperty, RoleProperty, LogoProperty, OrgProperty, MemberProperty, RelatedProperty, CategoriesProperty, NoteProperty, ProdIDProperty, RevProperty, SoundProperty, UIDProperty, ClientPidMapProperty, URLProperty, KeyProperty, FBURLProperty, CALADRURIProperty, CALURIProperty, KindProperty, XMLProperty, SourceProperty, UnknownProperty, parseDateAndOrTime, formatDateAndOrTime, } from './property.js';
25
+ export type { ValueType, TypeValue, KindValue, GenderSex, PartialDate, TimeValue, DateAndOrTime, StructuredName, Address, Organization, Gender, ClientPidMap, GeoCoordinates, ParameterMap, RawProperty, ValidationResult, ValidationError, } from './types.js';
26
+ export { escapeText, escapeStructuredComponent, unescapeText, parseStructured, parseList, parseStructuredList, needsParamQuoting, quoteParamValue, unquoteParamValue, splitStructured, splitList, } from './escape.js';
27
+ export { unfoldLines, parseContentLine, instantiateProperty, parseVCardText, } from './parser.js';
28
+ export type { ParseWarning, ParseResult, RawVCard } from './parser.js';
29
+ export { foldLine, serializeParameters, serializeProperty, serializeVCard } from './generator.js';
30
+ export type { GenerateOptions } from './generator.js';
31
+ import { VCard } from './vcard.js';
32
+ /**
33
+ * Parse vCard text and return all vCards found.
34
+ * Tolerant: never throws, silently accepts malformed input.
35
+ */
36
+ export declare function parse(text: string): VCard[];
37
+ /**
38
+ * Parse vCard text and return the first vCard.
39
+ * @throws Error if no vCard is found
40
+ */
41
+ export declare function parseOne(text: string): VCard;
42
+ /**
43
+ * Serialize a VCard (or array of VCards) to RFC 6350 text.
44
+ * @throws VCardError if the vCard is invalid
45
+ */
46
+ export declare function stringify(vcard: VCard | VCard[]): string;
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAEL,QAAQ,EAGR,YAAY,EACZ,gBAAgB,EAChB,WAAW,EAGX,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,cAAc,EAGd,WAAW,EAGX,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY,EAGZ,UAAU,EACV,WAAW,EAGX,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe,EAGf,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,WAAW,EAGX,WAAW,EAGX,aAAa,EACb,iBAAiB,EACjB,cAAc,EAGd,YAAY,EACZ,WAAW,EACX,cAAc,EAGd,eAAe,EAGf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAGvB,YAAY,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,aAAa,EACb,cAAc,EACd,OAAO,EACP,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,SAAS,GACV,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClG,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAE3C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAE5C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,MAAM,CAKxD"}
package/dist/index.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @pipobscure/vcard — A fully featured vCard v4 (RFC 6350) library
3
+ *
4
+ * Provides tolerant parsing and strict generation of vCard data,
5
+ * designed for use with CardDAV.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { VCard, FNProperty, EmailProperty } from '@pipobscure/vcard';
10
+ *
11
+ * // Parse
12
+ * const [contact] = VCard.parse(vcardText);
13
+ * console.log(contact.displayName); // 'Alice Example'
14
+ * console.log(contact.primaryEmail); // 'alice@example.com'
15
+ *
16
+ * // Build
17
+ * const vc = new VCard();
18
+ * vc.fn.push(new FNProperty('Bob Builder'));
19
+ * vc.email.push(new EmailProperty('bob@example.com'));
20
+ * const text = vc.toString(); // strict RFC 6350 output
21
+ * ```
22
+ */
23
+ // ── Main class ─────────────────────────────────────────────────────────────
24
+ export { VCard, VCardError } from './vcard.js';
25
+ // ── All property classes ───────────────────────────────────────────────────
26
+ export {
27
+ // Base
28
+ Property,
29
+ // Text properties
30
+ TextProperty, TextListProperty, UriProperty,
31
+ // Identification (RFC 6350 §6.2)
32
+ FNProperty, NProperty, NicknameProperty, PhotoProperty, BDayProperty, AnniversaryProperty, GenderProperty,
33
+ // Delivery addressing (RFC 6350 §6.3)
34
+ AdrProperty,
35
+ // Communications (RFC 6350 §6.4)
36
+ TelProperty, EmailProperty, IMPPProperty, LangProperty,
37
+ // Geographic (RFC 6350 §6.5)
38
+ TZProperty, GeoProperty,
39
+ // Organizational (RFC 6350 §6.6)
40
+ TitleProperty, RoleProperty, LogoProperty, OrgProperty, MemberProperty, RelatedProperty,
41
+ // Explanatory (RFC 6350 §6.7)
42
+ CategoriesProperty, NoteProperty, ProdIDProperty, RevProperty, SoundProperty, UIDProperty, ClientPidMapProperty, URLProperty,
43
+ // Security (RFC 6350 §6.8)
44
+ KeyProperty,
45
+ // Calendar (RFC 6350 §6.9)
46
+ FBURLProperty, CALADRURIProperty, CALURIProperty,
47
+ // General (RFC 6350 §6.1)
48
+ KindProperty, XMLProperty, SourceProperty,
49
+ // Unknown / extended
50
+ UnknownProperty,
51
+ // Date helpers
52
+ parseDateAndOrTime, formatDateAndOrTime, } from './property.js';
53
+ // ── Escape utilities (for advanced usage) ──────────────────────────────────
54
+ export { escapeText, escapeStructuredComponent, unescapeText, parseStructured, parseList, parseStructuredList, needsParamQuoting, quoteParamValue, unquoteParamValue, splitStructured, splitList, } from './escape.js';
55
+ // ── Parser ─────────────────────────────────────────────────────────────────
56
+ export { unfoldLines, parseContentLine, instantiateProperty, parseVCardText, } from './parser.js';
57
+ // ── Generator ──────────────────────────────────────────────────────────────
58
+ export { foldLine, serializeParameters, serializeProperty, serializeVCard } from './generator.js';
59
+ // ── Convenience functions ──────────────────────────────────────────────────
60
+ import { VCard } from './vcard.js';
61
+ /**
62
+ * Parse vCard text and return all vCards found.
63
+ * Tolerant: never throws, silently accepts malformed input.
64
+ */
65
+ export function parse(text) {
66
+ return VCard.parse(text);
67
+ }
68
+ /**
69
+ * Parse vCard text and return the first vCard.
70
+ * @throws Error if no vCard is found
71
+ */
72
+ export function parseOne(text) {
73
+ return VCard.parseOne(text);
74
+ }
75
+ /**
76
+ * Serialize a VCard (or array of VCards) to RFC 6350 text.
77
+ * @throws VCardError if the vCard is invalid
78
+ */
79
+ export function stringify(vcard) {
80
+ if (Array.isArray(vcard)) {
81
+ return vcard.map(vc => vc.toString()).join('');
82
+ }
83
+ return vcard.toString();
84
+ }
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,8EAA8E;AAC9E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/C,8EAA8E;AAC9E,OAAO;AACL,OAAO;AACP,QAAQ;AAER,kBAAkB;AAClB,YAAY,EACZ,gBAAgB,EAChB,WAAW;AAEX,iCAAiC;AACjC,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,cAAc;AAEd,sCAAsC;AACtC,WAAW;AAEX,iCAAiC;AACjC,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY;AAEZ,6BAA6B;AAC7B,UAAU,EACV,WAAW;AAEX,iCAAiC;AACjC,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe;AAEf,8BAA8B;AAC9B,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,WAAW;AAEX,2BAA2B;AAC3B,WAAW;AAEX,2BAA2B;AAC3B,aAAa,EACb,iBAAiB,EACjB,cAAc;AAEd,0BAA0B;AAC1B,YAAY,EACZ,WAAW,EACX,cAAc;AAEd,qBAAqB;AACrB,eAAe;AAEf,eAAe;AACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAuBvB,8EAA8E;AAC9E,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,8EAA8E;AAC9E,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,8EAA8E;AAC9E,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGlG,8EAA8E;AAE9E,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * vCard v4 parser — RFC 6350
3
+ *
4
+ * Design goals:
5
+ * - Tolerant: accept malformed input, mixed line endings, v3 quirks
6
+ * - Non-throwing: collect parse warnings, never discard data
7
+ * - Preserve unknown properties verbatim for round-tripping
8
+ */
9
+ import type { RawProperty } from './types.js';
10
+ import { Property } from './property.js';
11
+ export interface ParseWarning {
12
+ line?: number;
13
+ message: string;
14
+ }
15
+ /**
16
+ * Unfold content lines per RFC 6350 §3.2.
17
+ * Any CRLF or LF immediately followed by a space or tab is removed.
18
+ * Tolerates LF-only line endings.
19
+ */
20
+ export declare function unfoldLines(input: string): string[];
21
+ /**
22
+ * Parse a single content line into a RawProperty.
23
+ * Returns null for BEGIN/END/VERSION lines (handled separately).
24
+ *
25
+ * Format: [group.]name[;param=value...]:value
26
+ */
27
+ export declare function parseContentLine(line: string, warnings: ParseWarning[]): RawProperty | null;
28
+ /**
29
+ * Convert a RawProperty to a typed Property instance.
30
+ * Unknown properties become UnknownProperty instances.
31
+ */
32
+ export declare function instantiateProperty(raw: RawProperty, warnings: ParseWarning[]): Property;
33
+ /** A raw parsed vCard block (list of content lines) */
34
+ export interface RawVCard {
35
+ version: string;
36
+ properties: Property[];
37
+ warnings: ParseWarning[];
38
+ }
39
+ /** Result of parsing vCard text */
40
+ export interface ParseResult {
41
+ rawVCards: RawVCard[];
42
+ warnings: ParseWarning[];
43
+ }
44
+ /**
45
+ * Parse vCard text into raw vCard blocks.
46
+ * Tolerates:
47
+ * - Multiple vCards in one string
48
+ * - CRLF or LF line endings
49
+ * - Missing VERSION
50
+ * - Unknown properties
51
+ * - v3 syntax
52
+ */
53
+ export declare function parseVCardText(input: string): ParseResult;
54
+ //# sourceMappingURL=parser.d.ts.map