From ee3937629f94c2aeb9284873bd6b9689449d65bd Mon Sep 17 00:00:00 2001 From: Philipp Kewisch Date: Thu, 2 May 2024 11:26:20 +0200 Subject: [PATCH] Detect the right design set for vcard3 --- lib/ical/component.js | 14 ++++++++++++++ lib/ical/design.js | 3 +++ test/design_test.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/lib/ical/component.js b/lib/ical/component.js index 4e25980d..586f1247 100644 --- a/lib/ical/component.js +++ b/lib/ical/component.js @@ -13,6 +13,9 @@ const NAME_INDEX = 0; const PROPERTY_INDEX = 1; const COMPONENT_INDEX = 2; +const PROPERTY_NAME_INDEX = 0; +const PROPERTY_VALUE_INDEX = 3; + /** * Wraps a jCal component, adding convenience methods to add, remove and update subcomponents and * properties. @@ -98,6 +101,17 @@ class Component { */ get _designSet() { let parentDesign = this.parent && this.parent._designSet; + if (!parentDesign && this.name == "vcard") { + // We can't decide on vcard3 vs vcard4 just based on the component name, the version number is + // in the version property. We also can't use hydrated properties here because it would lead + // to recursion, but the spec says that the version property needs to be the very first one. + let versionProp = this.jCal[PROPERTY_INDEX]?.[0]; + + if (versionProp && versionProp[PROPERTY_NAME_INDEX] == "version" && versionProp[PROPERTY_VALUE_INDEX] == "3.0") { + return design.getDesignSet("vcard3"); + } + } + return parentDesign || design.getDesignSet(this.name); } diff --git a/lib/ical/design.js b/lib/ical/design.js index 1778df65..7e0ae287 100644 --- a/lib/ical/design.js +++ b/lib/ical/design.js @@ -898,6 +898,7 @@ let vcard3Properties = extend(commonProperties, { * @type {ICAL.design.designSet} */ let icalSet = { + name: "ical", value: icalValues, param: icalParams, property: icalProperties, @@ -909,6 +910,7 @@ let icalSet = { * @type {ICAL.design.designSet} */ let vcardSet = { + name: "vcard4", value: vcardValues, param: vcardParams, property: vcardProperties, @@ -920,6 +922,7 @@ let vcardSet = { * @type {ICAL.design.designSet} */ let vcard3Set = { + name: "vcard3", value: vcard3Values, param: vcard3Params, property: vcard3Properties, diff --git a/test/design_test.js b/test/design_test.js index dbd411a3..7e1b8c63 100644 --- a/test/design_test.js +++ b/test/design_test.js @@ -964,4 +964,39 @@ suite('design', function() { }); }); }); + + suite('design sets', function() { + test('detection', function() { + let component = new ICAL.Component(ICAL.parse( + 'BEGIN:VCARD\n' + + 'VERSION:4.0\n' + + 'FN:Fun Name\n' + + 'BDAY:--0203\n' + + 'END:VCARD' + )); + assert.equal(component._designSet?.name, 'vcard4'); + assert.equal(component.getFirstProperty('fn')._designSet?.name, 'vcard4'); + + component = new ICAL.Component(ICAL.parse( + 'BEGIN:VCARD\n'+ + 'VERSION:3.0\n'+ + 'FN:Fun Name\n'+ + 'TEL;TYPE=VOICE,MSG,WORK:+1-555-937-3419\n'+ + 'TEL;TYPE=FAX,WORK:+1-555-528-4164\n'+ + 'EMAIL;TYPE=INTERNET:user@example.com\n'+ + 'END:VCARD' + )); + assert.equal(component._designSet?.name, 'vcard3'); + assert.equal(component.getFirstProperty('fn')._designSet?.name, 'vcard3'); + + component = new ICAL.Component(ICAL.parse( + 'BEGIN:VCALENDAR\n'+ + 'PRODID:-//Google Inc//Google Calendar 70.9054//EN\n' + + 'VERSION:2.0\n'+ + 'END:VCALENDAR' + )); + assert.equal(component._designSet?.name, 'ical'); + assert.equal(component.getFirstProperty('version')._designSet?.name, 'ical'); + }); + }); });