add-to-calendar-button 2.3.2 → 2.3.4
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.
- package/dist/atcb.js +6 -5
- package/dist/commonjs/index.js +61 -34
- package/dist/module/index.js +61 -34
- package/index.d.ts +1 -0
- package/package.json +1 -1
- package/test/server-side-init.test.js +1 -2
package/dist/commonjs/index.js
CHANGED
|
@@ -7,22 +7,22 @@ const tzlibActions = require('timezones-ical-library');
|
|
|
7
7
|
* Add to Calendar Button
|
|
8
8
|
* ++++++++++++++++++++++
|
|
9
9
|
*
|
|
10
|
-
* Version: 2.3.
|
|
10
|
+
* Version: 2.3.4
|
|
11
11
|
* Creator: Jens Kuerschner (https://jenskuerschner.de)
|
|
12
12
|
* Project: https://github.com/add2cal/add-to-calendar-button
|
|
13
13
|
* License: Elastic License 2.0 (ELv2) (https://github.com/add2cal/add-to-calendar-button/blob/main/LICENSE.txt)
|
|
14
14
|
* Note: DO NOT REMOVE THE COPYRIGHT NOTICE ABOVE!
|
|
15
15
|
*
|
|
16
16
|
*/
|
|
17
|
-
const atcbVersion = '2.3.
|
|
18
|
-
const atcbCssTemplate = {
|
|
17
|
+
const atcbVersion = '2.3.4';
|
|
18
|
+
const atcbCssTemplate = {
|
|
19
19
|
if (typeof window === 'undefined') {
|
|
20
20
|
return false;
|
|
21
21
|
} else {
|
|
22
22
|
return true;
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
-
const
|
|
25
|
+
const atcbIsiOS = atcbIsBrowser()
|
|
26
26
|
? () => {
|
|
27
27
|
if ((/iPad|iPhone|iPod/i.test(navigator.userAgent || navigator.vendor || window.opera) && !window.MSStream) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) {
|
|
28
28
|
return true;
|
|
@@ -33,7 +33,7 @@ const isiOS = isBrowser()
|
|
|
33
33
|
: () => {
|
|
34
34
|
return false;
|
|
35
35
|
};
|
|
36
|
-
const
|
|
36
|
+
const atcbIsAndroid = atcbIsBrowser()
|
|
37
37
|
? () => {
|
|
38
38
|
if (/android/i.test(navigator.userAgent || navigator.vendor || window.opera) && !window.MSStream) {
|
|
39
39
|
return true;
|
|
@@ -44,7 +44,7 @@ const isAndroid = isBrowser()
|
|
|
44
44
|
: () => {
|
|
45
45
|
return false;
|
|
46
46
|
};
|
|
47
|
-
/*const isChrome =
|
|
47
|
+
/*const isChrome = atcbIsBrowser()
|
|
48
48
|
? () => {
|
|
49
49
|
if (/chrome|chromium|crios|google inc/i.test(navigator.userAgent || navigator.vendor)) {
|
|
50
50
|
return true;
|
|
@@ -55,7 +55,7 @@ const isAndroid = isBrowser()
|
|
|
55
55
|
: () => {
|
|
56
56
|
return false;
|
|
57
57
|
};*/
|
|
58
|
-
const
|
|
58
|
+
const atcbIsSafari = atcbIsBrowser()
|
|
59
59
|
? () => {
|
|
60
60
|
if (/^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent || navigator.vendor)) {
|
|
61
61
|
return true;
|
|
@@ -66,14 +66,14 @@ const isSafari = isBrowser()
|
|
|
66
66
|
: () => {
|
|
67
67
|
return false;
|
|
68
68
|
};
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
69
|
+
const atcbIsMobile = () => {
|
|
70
|
+
if (atcbIsAndroid() || atcbIsiOS()) {
|
|
71
71
|
return true;
|
|
72
72
|
} else {
|
|
73
73
|
return false;
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
|
-
const
|
|
76
|
+
const atcbIsWebView = atcbIsBrowser()
|
|
77
77
|
? () => {
|
|
78
78
|
if (/(; ?wv|(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari))/i.test(navigator.userAgent || navigator.vendor)) {
|
|
79
79
|
return true;
|
|
@@ -84,7 +84,7 @@ const isWebView = isBrowser()
|
|
|
84
84
|
: () => {
|
|
85
85
|
return false;
|
|
86
86
|
};
|
|
87
|
-
const
|
|
87
|
+
const atcbIsProblematicWebView = atcbIsBrowser()
|
|
88
88
|
? () => {
|
|
89
89
|
if (/(Instagram)/i.test(navigator.userAgent || navigator.vendor || window.opera)) {
|
|
90
90
|
return true;
|
|
@@ -95,7 +95,7 @@ const isProblematicWebView = isBrowser()
|
|
|
95
95
|
: () => {
|
|
96
96
|
return false;
|
|
97
97
|
};
|
|
98
|
-
const atcbDefaultTarget =
|
|
98
|
+
const atcbDefaultTarget = atcbIsWebView() ? '_system' : '_blank';
|
|
99
99
|
const atcbOptions = ['apple', 'google', 'ical', 'ms365', 'outlookcom', 'msteams', 'yahoo'];
|
|
100
100
|
const atcbValidRecurrOptions = ['apple', 'google', 'ical'];
|
|
101
101
|
const atcbInvalidSubscribeOptions = ['msteams'];
|
|
@@ -103,6 +103,7 @@ const atcbiOSInvalidOptions = ['ical'];
|
|
|
103
103
|
const atcbStates = [];
|
|
104
104
|
const atcbWcParams = [
|
|
105
105
|
'debug',
|
|
106
|
+
'cspnonce',
|
|
106
107
|
'name',
|
|
107
108
|
'dates',
|
|
108
109
|
'description',
|
|
@@ -324,8 +325,8 @@ function atcb_decorate_data_options(data) {
|
|
|
324
325
|
iCalGiven = true;
|
|
325
326
|
}
|
|
326
327
|
if (
|
|
327
|
-
(
|
|
328
|
-
(data.recurrence != null && data.recurrence != '' && (!atcbValidRecurrOptions.includes(optionName) || (data.recurrence_until != null && data.recurrence_until != '' && (optionName === 'apple' || optionName === 'ical')) || (
|
|
328
|
+
(atcbIsiOS() && atcbiOSInvalidOptions.includes(optionName)) ||
|
|
329
|
+
(data.recurrence != null && data.recurrence != '' && (!atcbValidRecurrOptions.includes(optionName) || (data.recurrence_until != null && data.recurrence_until != '' && (optionName === 'apple' || optionName === 'ical')) || (atcbIsiOS() && optionName === 'google'))) ||
|
|
329
330
|
(data.subscribe && atcbInvalidSubscribeOptions.includes(optionName))
|
|
330
331
|
) {
|
|
331
332
|
continue;
|
|
@@ -334,13 +335,13 @@ function atcb_decorate_data_options(data) {
|
|
|
334
335
|
data.optionLabels.push(optionLabel);
|
|
335
336
|
}
|
|
336
337
|
if (newOptions.length === 0) {
|
|
337
|
-
if (!
|
|
338
|
+
if (!atcbIsiOS()) {
|
|
338
339
|
newOptions.push('ical');
|
|
339
340
|
data.optionLabels.push('');
|
|
340
341
|
}
|
|
341
342
|
iCalGiven = true;
|
|
342
343
|
}
|
|
343
|
-
if (
|
|
344
|
+
if (atcbIsiOS() && iCalGiven && !appleGiven) {
|
|
344
345
|
newOptions.push('apple');
|
|
345
346
|
data.optionLabels.push('');
|
|
346
347
|
}
|
|
@@ -405,7 +406,7 @@ function atcb_decorate_sizes(size) {
|
|
|
405
406
|
return sizes;
|
|
406
407
|
}
|
|
407
408
|
function atcb_decorate_light_mode(lightMode = '') {
|
|
408
|
-
if (lightMode == 'system' &&
|
|
409
|
+
if (lightMode == 'system' && atcbIsBrowser()) {
|
|
409
410
|
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
410
411
|
return prefersDarkScheme.matches ? 'dark' : 'light';
|
|
411
412
|
}
|
|
@@ -1964,6 +1965,13 @@ function atcb_generate_modal_host(host, data, reset = true) {
|
|
|
1964
1965
|
|
|
1965
1966
|
function atcb_generate_rich_data(data, parent) {
|
|
1966
1967
|
const schemaEl = document.createElement('script');
|
|
1968
|
+
if (parent.hasAttribute('cspnonce')) {
|
|
1969
|
+
const cspnonceRegex = /[`'"()[\]{}<>\s]/;
|
|
1970
|
+
if (cspnonceRegex.test(parent.getAttribute('cspnonce'))) {
|
|
1971
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
1972
|
+
}
|
|
1973
|
+
schemaEl.setAttribute('nonce', parent.getAttribute('cspnonce'));
|
|
1974
|
+
}
|
|
1967
1975
|
schemaEl.type = 'application/ld+json';
|
|
1968
1976
|
const schemaContentMulti = [];
|
|
1969
1977
|
if (data.dates.length > 1) {
|
|
@@ -2170,7 +2178,7 @@ function atcb_generate_subscribe_links(host, linkType, data, keyboardTrigger) {
|
|
|
2170
2178
|
const adjustedFileUrl = data.icsFile.replace('https://', 'webcal://');
|
|
2171
2179
|
switch (linkType) {
|
|
2172
2180
|
case 'ical': // also for apple (see above)
|
|
2173
|
-
if (
|
|
2181
|
+
if (atcbIsMobile()) {
|
|
2174
2182
|
atcb_subscribe_ical(data.icsFile);
|
|
2175
2183
|
break;
|
|
2176
2184
|
}
|
|
@@ -2283,7 +2291,7 @@ function atcb_generate_google(data) {
|
|
|
2283
2291
|
}
|
|
2284
2292
|
if (data.location != null && data.location != '') {
|
|
2285
2293
|
urlParts.push('location=' + encodeURIComponent(data.location));
|
|
2286
|
-
if (
|
|
2294
|
+
if (atcbIsiOS()) {
|
|
2287
2295
|
if (tmpDataDescription.length > 0) {
|
|
2288
2296
|
tmpDataDescription.push('<br><br>');
|
|
2289
2297
|
}
|
|
@@ -2329,7 +2337,7 @@ function atcb_generate_yahoo(data) {
|
|
|
2329
2337
|
function atcb_generate_microsoft(data, type = '365') {
|
|
2330
2338
|
const urlParts = [];
|
|
2331
2339
|
const basePath = (function () {
|
|
2332
|
-
if (
|
|
2340
|
+
if (atcbIsMobile()) {
|
|
2333
2341
|
return '/calendar/0/deeplink/compose?path=%2Fcalendar%2Faction%2Fcompose&rru=addevent';
|
|
2334
2342
|
}
|
|
2335
2343
|
return '/calendar/action/compose?rru=addevent';
|
|
@@ -2363,7 +2371,7 @@ function atcb_generate_msteams(data) {
|
|
|
2363
2371
|
const urlParts = [];
|
|
2364
2372
|
const baseUrl = 'https://teams.microsoft.com/l/meeting/new?';
|
|
2365
2373
|
const formattedDate = atcb_generate_time(data, 'delimiters', 'msteams', true);
|
|
2366
|
-
if (!formattedDate.allday ||
|
|
2374
|
+
if (!formattedDate.allday || atcbIsMobile()) {
|
|
2367
2375
|
urlParts.push('startTime=' + encodeURIComponent(formattedDate.start));
|
|
2368
2376
|
urlParts.push('endTime=' + encodeURIComponent(formattedDate.end));
|
|
2369
2377
|
} else {
|
|
@@ -2410,7 +2418,7 @@ function atcb_generate_ical(host, data, subEvent = 'all', keyboardTrigger = fals
|
|
|
2410
2418
|
}
|
|
2411
2419
|
return '';
|
|
2412
2420
|
})();
|
|
2413
|
-
if (givenIcsFile != '' && (!
|
|
2421
|
+
if (givenIcsFile != '' && (!atcbIsiOS() || (atcbIsiOS() && atcbIsWebView() && data.bypassWebViewCheck == true))) {
|
|
2414
2422
|
atcb_save_file(givenIcsFile, filename);
|
|
2415
2423
|
return;
|
|
2416
2424
|
}
|
|
@@ -2507,7 +2515,7 @@ function atcb_generate_ical(host, data, subEvent = 'all', keyboardTrigger = fals
|
|
|
2507
2515
|
}
|
|
2508
2516
|
return 'data:text/calendar;charset=utf-8,' + encodeURIComponent(ics_lines.join('\r\n'));
|
|
2509
2517
|
})();
|
|
2510
|
-
if ((
|
|
2518
|
+
if ((atcbIsiOS() && !atcbIsSafari()) || (atcbIsWebView() && (atcbIsiOS() || (atcbIsAndroid() && atcbIsProblematicWebView())))) {
|
|
2511
2519
|
atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger);
|
|
2512
2520
|
return;
|
|
2513
2521
|
}
|
|
@@ -2533,7 +2541,7 @@ function atcb_determine_ical_filename(data, subEvent) {
|
|
|
2533
2541
|
}
|
|
2534
2542
|
function atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger) {
|
|
2535
2543
|
atcb_copy_to_clipboard(dataUrl);
|
|
2536
|
-
if (
|
|
2544
|
+
if (atcbIsiOS() && !atcbIsSafari()) {
|
|
2537
2545
|
atcb_create_modal(
|
|
2538
2546
|
host,
|
|
2539
2547
|
data,
|
|
@@ -2561,7 +2569,7 @@ function atcb_save_file(file, filename) {
|
|
|
2561
2569
|
const save = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
|
|
2562
2570
|
save.rel = 'noopener';
|
|
2563
2571
|
save.href = file;
|
|
2564
|
-
if (
|
|
2572
|
+
if (atcbIsMobile()) {
|
|
2565
2573
|
save.target = '_self';
|
|
2566
2574
|
} else {
|
|
2567
2575
|
save.target = '_blank';
|
|
@@ -2627,11 +2635,11 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general', a
|
|
|
2627
2635
|
const endDate = data.endDate.split('-');
|
|
2628
2636
|
const newStartDate = new Date(Date.UTC(startDate[0], startDate[1] - 1, startDate[2], 12, 0, 0));
|
|
2629
2637
|
const newEndDate = new Date(Date.UTC(endDate[0], endDate[1] - 1, endDate[2], 12, 0, 0));
|
|
2630
|
-
if (targetCal === 'google' || (targetCal === 'microsoft' && !
|
|
2638
|
+
if (targetCal === 'google' || (targetCal === 'microsoft' && !atcbIsMobile()) || targetCal === 'msteams' || targetCal === 'ical') {
|
|
2631
2639
|
newEndDate.setDate(newEndDate.getDate() + 1);
|
|
2632
2640
|
}
|
|
2633
2641
|
if (targetCal === 'msteams') {
|
|
2634
|
-
if (
|
|
2642
|
+
if (atcbIsMobile()) {
|
|
2635
2643
|
const offset = newStartDate.getTimezoneOffset();
|
|
2636
2644
|
const formattedOffset = (function () {
|
|
2637
2645
|
if (offset < 0) {
|
|
@@ -2695,7 +2703,7 @@ function atcb_secure_url(url, throwError = true) {
|
|
|
2695
2703
|
}
|
|
2696
2704
|
}
|
|
2697
2705
|
function atcb_validEmail(email) {
|
|
2698
|
-
if (!/^.{0,70}@.{1,30}\.[
|
|
2706
|
+
if (!/^.{0,70}@.{1,30}\.[a-zA-Z]{2,9}$/.test(email)) {
|
|
2699
2707
|
return false;
|
|
2700
2708
|
}
|
|
2701
2709
|
return true;
|
|
@@ -2840,7 +2848,7 @@ function atcb_copy_to_clipboard(dataString) {
|
|
|
2840
2848
|
tmpInput.contentEditable = true;
|
|
2841
2849
|
tmpInput.readOnly = false;
|
|
2842
2850
|
tmpInput.value = dataString;
|
|
2843
|
-
if (
|
|
2851
|
+
if (atcbIsiOS()) {
|
|
2844
2852
|
var range = document.createRange();
|
|
2845
2853
|
range.selectNodeContents(tmpInput);
|
|
2846
2854
|
var selection = window.getSelection();
|
|
@@ -2889,7 +2897,7 @@ function atcb_log_event(event, trigger, identifier) {
|
|
|
2889
2897
|
if (parentEl) {
|
|
2890
2898
|
parentEl.setAttribute('atcb-last-event', event + ':' + trigger);
|
|
2891
2899
|
}
|
|
2892
|
-
if (
|
|
2900
|
+
if (atcbIsBrowser()) {
|
|
2893
2901
|
atcb_push_to_data_layer(event, trigger);
|
|
2894
2902
|
}
|
|
2895
2903
|
}
|
|
@@ -3466,7 +3474,7 @@ let atcbInitialGlobalInit = false;
|
|
|
3466
3474
|
let atcbBtnCount = 0;
|
|
3467
3475
|
const lightModeMutationObserver = [];
|
|
3468
3476
|
const template = `<div class="atcb-initialized" style="display:none;position:relative;width:fit-content;"></div>`;
|
|
3469
|
-
if (
|
|
3477
|
+
if (atcbIsBrowser()) {
|
|
3470
3478
|
class AddToCalendarButton extends HTMLElement {
|
|
3471
3479
|
constructor() {
|
|
3472
3480
|
super();
|
|
@@ -3707,11 +3715,18 @@ function atcb_set_light_mode(shadowRoot, data) {
|
|
|
3707
3715
|
shadowRoot.host.classList.add('atcb-' + hostLightMode);
|
|
3708
3716
|
}
|
|
3709
3717
|
function atcb_load_css(host, rootObj = null, style = '', inline = false, buttonsList = false, customCss = '') {
|
|
3718
|
+
const cspnonceRegex = /[`'"()[\]{}<>\s]/;
|
|
3710
3719
|
if (!document.getElementById('atcb-global-style')) {
|
|
3711
3720
|
const cssGlobalContent = document.createElement('style');
|
|
3712
3721
|
cssGlobalContent.id = 'atcb-global-style';
|
|
3713
3722
|
const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
3714
3723
|
cssGlobalContent.innerText = '.atcb-modal-no-scroll { overflow-y: hidden !important; -webkit-overflow-scrolling: touch; } body.atcb-modal-no-scroll { padding-right: ' + scrollBarWidth + 'px; }';
|
|
3724
|
+
if (host.host.hasAttribute('cspnonce')) {
|
|
3725
|
+
if (cspnonceRegex.test(host.host.getAttribute('cspnonce'))) {
|
|
3726
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
3727
|
+
}
|
|
3728
|
+
cssGlobalContent.setAttribute('nonce', host.host.getAttribute('cspnonce'));
|
|
3729
|
+
}
|
|
3715
3730
|
document.head.append(cssGlobalContent);
|
|
3716
3731
|
}
|
|
3717
3732
|
if (customCss != '' && style == 'custom') {
|
|
@@ -3719,6 +3734,12 @@ function atcb_load_css(host, rootObj = null, style = '', inline = false, buttons
|
|
|
3719
3734
|
cssFile.setAttribute('rel', 'stylesheet');
|
|
3720
3735
|
cssFile.setAttribute('type', 'text/css');
|
|
3721
3736
|
cssFile.setAttribute('href', customCss);
|
|
3737
|
+
if (host.host.hasAttribute('cspnonce')) {
|
|
3738
|
+
if (cspnonceRegex.test(host.host.getAttribute('cspnonce'))) {
|
|
3739
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
3740
|
+
}
|
|
3741
|
+
cssFile.setAttribute('nonce', host.host.getAttribute('cspnonce'));
|
|
3742
|
+
}
|
|
3722
3743
|
if (rootObj == null) {
|
|
3723
3744
|
host.host.style.display = 'none';
|
|
3724
3745
|
loadExternalCssAsynch(cssFile, host, host.host);
|
|
@@ -3732,6 +3753,12 @@ function atcb_load_css(host, rootObj = null, style = '', inline = false, buttons
|
|
|
3732
3753
|
}
|
|
3733
3754
|
if (style != 'none' && atcbCssTemplate[`${style}`] != null) {
|
|
3734
3755
|
const cssContent = document.createElement('style');
|
|
3756
|
+
if (host.host.hasAttribute('cspnonce')) {
|
|
3757
|
+
if (cspnonceRegex.test(host.host.getAttribute('cspnonce'))) {
|
|
3758
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
3759
|
+
}
|
|
3760
|
+
cssContent.setAttribute('nonce', host.host.getAttribute('cspnonce'));
|
|
3761
|
+
}
|
|
3735
3762
|
const overrideDefaultCss = (function () {
|
|
3736
3763
|
if (host.host.hasAttribute('styleLight')) {
|
|
3737
3764
|
const output = ':host { ' + atcb_secure_content(host.host.getAttribute('styleLight').replace(/(\\r\\n|\\n|\\r)/g, ''), false) + ' }';
|
|
@@ -3793,7 +3820,7 @@ function atcb_render_debug_msg(host, error) {
|
|
|
3793
3820
|
}
|
|
3794
3821
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3795
3822
|
function atcb_action(data, triggerElement, keyboardTrigger = false) {
|
|
3796
|
-
if (!
|
|
3823
|
+
if (!atcbIsBrowser()) {
|
|
3797
3824
|
return;
|
|
3798
3825
|
}
|
|
3799
3826
|
data = atcb_secure_content(data);
|
|
@@ -3849,7 +3876,7 @@ function atcb_action(data, triggerElement, keyboardTrigger = false) {
|
|
|
3849
3876
|
atcb_log_event('initialization', data.identifier, data.identifier);
|
|
3850
3877
|
if (!data.blockInteraction) {
|
|
3851
3878
|
let host = null;
|
|
3852
|
-
if (!oneOption || (data.options[0] !== 'apple' && data.options[0] !== 'ical') || (data.dates && data.dates.length > 1 && data.dates.organizer) || (
|
|
3879
|
+
if (!oneOption || (data.options[0] !== 'apple' && data.options[0] !== 'ical') || (data.dates && data.dates.length > 1 && data.dates.organizer) || (atcbIsMobile())) {
|
|
3853
3880
|
host = document.createElement('div');
|
|
3854
3881
|
host.id = 'atcb-customTrigger-' + data.identifier + '-host';
|
|
3855
3882
|
if (root == document.body) {
|
|
@@ -3928,7 +3955,7 @@ function atcb_get_pro_data(licenseKey) {
|
|
|
3928
3955
|
return data;
|
|
3929
3956
|
}
|
|
3930
3957
|
function atcb_set_global_event_listener(host, data) {
|
|
3931
|
-
if (!
|
|
3958
|
+
if (!atcbIsBrowser()) {
|
|
3932
3959
|
return;
|
|
3933
3960
|
}
|
|
3934
3961
|
if (data.lightMode == 'bodyScheme') {
|
package/dist/module/index.js
CHANGED
|
@@ -6,22 +6,22 @@ import { tzlib_get_ical_block, tzlib_get_offset, tzlib_get_timezones } from 'tim
|
|
|
6
6
|
* Add to Calendar Button
|
|
7
7
|
* ++++++++++++++++++++++
|
|
8
8
|
*
|
|
9
|
-
* Version: 2.3.
|
|
9
|
+
* Version: 2.3.4
|
|
10
10
|
* Creator: Jens Kuerschner (https://jenskuerschner.de)
|
|
11
11
|
* Project: https://github.com/add2cal/add-to-calendar-button
|
|
12
12
|
* License: Elastic License 2.0 (ELv2) (https://github.com/add2cal/add-to-calendar-button/blob/main/LICENSE.txt)
|
|
13
13
|
* Note: DO NOT REMOVE THE COPYRIGHT NOTICE ABOVE!
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
const atcbVersion = '2.3.
|
|
17
|
-
const atcbCssTemplate = {
|
|
16
|
+
const atcbVersion = '2.3.4';
|
|
17
|
+
const atcbCssTemplate = {
|
|
18
18
|
if (typeof window === 'undefined') {
|
|
19
19
|
return false;
|
|
20
20
|
} else {
|
|
21
21
|
return true;
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
const
|
|
24
|
+
const atcbIsiOS = atcbIsBrowser()
|
|
25
25
|
? () => {
|
|
26
26
|
if ((/iPad|iPhone|iPod/i.test(navigator.userAgent || navigator.vendor || window.opera) && !window.MSStream) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) {
|
|
27
27
|
return true;
|
|
@@ -32,7 +32,7 @@ const isiOS = isBrowser()
|
|
|
32
32
|
: () => {
|
|
33
33
|
return false;
|
|
34
34
|
};
|
|
35
|
-
const
|
|
35
|
+
const atcbIsAndroid = atcbIsBrowser()
|
|
36
36
|
? () => {
|
|
37
37
|
if (/android/i.test(navigator.userAgent || navigator.vendor || window.opera) && !window.MSStream) {
|
|
38
38
|
return true;
|
|
@@ -43,7 +43,7 @@ const isAndroid = isBrowser()
|
|
|
43
43
|
: () => {
|
|
44
44
|
return false;
|
|
45
45
|
};
|
|
46
|
-
/*const isChrome =
|
|
46
|
+
/*const isChrome = atcbIsBrowser()
|
|
47
47
|
? () => {
|
|
48
48
|
if (/chrome|chromium|crios|google inc/i.test(navigator.userAgent || navigator.vendor)) {
|
|
49
49
|
return true;
|
|
@@ -54,7 +54,7 @@ const isAndroid = isBrowser()
|
|
|
54
54
|
: () => {
|
|
55
55
|
return false;
|
|
56
56
|
};*/
|
|
57
|
-
const
|
|
57
|
+
const atcbIsSafari = atcbIsBrowser()
|
|
58
58
|
? () => {
|
|
59
59
|
if (/^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent || navigator.vendor)) {
|
|
60
60
|
return true;
|
|
@@ -65,14 +65,14 @@ const isSafari = isBrowser()
|
|
|
65
65
|
: () => {
|
|
66
66
|
return false;
|
|
67
67
|
};
|
|
68
|
-
const
|
|
69
|
-
if (
|
|
68
|
+
const atcbIsMobile = () => {
|
|
69
|
+
if (atcbIsAndroid() || atcbIsiOS()) {
|
|
70
70
|
return true;
|
|
71
71
|
} else {
|
|
72
72
|
return false;
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
|
-
const
|
|
75
|
+
const atcbIsWebView = atcbIsBrowser()
|
|
76
76
|
? () => {
|
|
77
77
|
if (/(; ?wv|(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari))/i.test(navigator.userAgent || navigator.vendor)) {
|
|
78
78
|
return true;
|
|
@@ -83,7 +83,7 @@ const isWebView = isBrowser()
|
|
|
83
83
|
: () => {
|
|
84
84
|
return false;
|
|
85
85
|
};
|
|
86
|
-
const
|
|
86
|
+
const atcbIsProblematicWebView = atcbIsBrowser()
|
|
87
87
|
? () => {
|
|
88
88
|
if (/(Instagram)/i.test(navigator.userAgent || navigator.vendor || window.opera)) {
|
|
89
89
|
return true;
|
|
@@ -94,7 +94,7 @@ const isProblematicWebView = isBrowser()
|
|
|
94
94
|
: () => {
|
|
95
95
|
return false;
|
|
96
96
|
};
|
|
97
|
-
const atcbDefaultTarget =
|
|
97
|
+
const atcbDefaultTarget = atcbIsWebView() ? '_system' : '_blank';
|
|
98
98
|
const atcbOptions = ['apple', 'google', 'ical', 'ms365', 'outlookcom', 'msteams', 'yahoo'];
|
|
99
99
|
const atcbValidRecurrOptions = ['apple', 'google', 'ical'];
|
|
100
100
|
const atcbInvalidSubscribeOptions = ['msteams'];
|
|
@@ -102,6 +102,7 @@ const atcbiOSInvalidOptions = ['ical'];
|
|
|
102
102
|
const atcbStates = [];
|
|
103
103
|
const atcbWcParams = [
|
|
104
104
|
'debug',
|
|
105
|
+
'cspnonce',
|
|
105
106
|
'name',
|
|
106
107
|
'dates',
|
|
107
108
|
'description',
|
|
@@ -323,8 +324,8 @@ function atcb_decorate_data_options(data) {
|
|
|
323
324
|
iCalGiven = true;
|
|
324
325
|
}
|
|
325
326
|
if (
|
|
326
|
-
(
|
|
327
|
-
(data.recurrence != null && data.recurrence != '' && (!atcbValidRecurrOptions.includes(optionName) || (data.recurrence_until != null && data.recurrence_until != '' && (optionName === 'apple' || optionName === 'ical')) || (
|
|
327
|
+
(atcbIsiOS() && atcbiOSInvalidOptions.includes(optionName)) ||
|
|
328
|
+
(data.recurrence != null && data.recurrence != '' && (!atcbValidRecurrOptions.includes(optionName) || (data.recurrence_until != null && data.recurrence_until != '' && (optionName === 'apple' || optionName === 'ical')) || (atcbIsiOS() && optionName === 'google'))) ||
|
|
328
329
|
(data.subscribe && atcbInvalidSubscribeOptions.includes(optionName))
|
|
329
330
|
) {
|
|
330
331
|
continue;
|
|
@@ -333,13 +334,13 @@ function atcb_decorate_data_options(data) {
|
|
|
333
334
|
data.optionLabels.push(optionLabel);
|
|
334
335
|
}
|
|
335
336
|
if (newOptions.length === 0) {
|
|
336
|
-
if (!
|
|
337
|
+
if (!atcbIsiOS()) {
|
|
337
338
|
newOptions.push('ical');
|
|
338
339
|
data.optionLabels.push('');
|
|
339
340
|
}
|
|
340
341
|
iCalGiven = true;
|
|
341
342
|
}
|
|
342
|
-
if (
|
|
343
|
+
if (atcbIsiOS() && iCalGiven && !appleGiven) {
|
|
343
344
|
newOptions.push('apple');
|
|
344
345
|
data.optionLabels.push('');
|
|
345
346
|
}
|
|
@@ -404,7 +405,7 @@ function atcb_decorate_sizes(size) {
|
|
|
404
405
|
return sizes;
|
|
405
406
|
}
|
|
406
407
|
function atcb_decorate_light_mode(lightMode = '') {
|
|
407
|
-
if (lightMode == 'system' &&
|
|
408
|
+
if (lightMode == 'system' && atcbIsBrowser()) {
|
|
408
409
|
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
409
410
|
return prefersDarkScheme.matches ? 'dark' : 'light';
|
|
410
411
|
}
|
|
@@ -1963,6 +1964,13 @@ function atcb_generate_modal_host(host, data, reset = true) {
|
|
|
1963
1964
|
|
|
1964
1965
|
function atcb_generate_rich_data(data, parent) {
|
|
1965
1966
|
const schemaEl = document.createElement('script');
|
|
1967
|
+
if (parent.hasAttribute('cspnonce')) {
|
|
1968
|
+
const cspnonceRegex = /[`'"()[\]{}<>\s]/;
|
|
1969
|
+
if (cspnonceRegex.test(parent.getAttribute('cspnonce'))) {
|
|
1970
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
1971
|
+
}
|
|
1972
|
+
schemaEl.setAttribute('nonce', parent.getAttribute('cspnonce'));
|
|
1973
|
+
}
|
|
1966
1974
|
schemaEl.type = 'application/ld+json';
|
|
1967
1975
|
const schemaContentMulti = [];
|
|
1968
1976
|
if (data.dates.length > 1) {
|
|
@@ -2169,7 +2177,7 @@ function atcb_generate_subscribe_links(host, linkType, data, keyboardTrigger) {
|
|
|
2169
2177
|
const adjustedFileUrl = data.icsFile.replace('https://', 'webcal://');
|
|
2170
2178
|
switch (linkType) {
|
|
2171
2179
|
case 'ical': // also for apple (see above)
|
|
2172
|
-
if (
|
|
2180
|
+
if (atcbIsMobile()) {
|
|
2173
2181
|
atcb_subscribe_ical(data.icsFile);
|
|
2174
2182
|
break;
|
|
2175
2183
|
}
|
|
@@ -2282,7 +2290,7 @@ function atcb_generate_google(data) {
|
|
|
2282
2290
|
}
|
|
2283
2291
|
if (data.location != null && data.location != '') {
|
|
2284
2292
|
urlParts.push('location=' + encodeURIComponent(data.location));
|
|
2285
|
-
if (
|
|
2293
|
+
if (atcbIsiOS()) {
|
|
2286
2294
|
if (tmpDataDescription.length > 0) {
|
|
2287
2295
|
tmpDataDescription.push('<br><br>');
|
|
2288
2296
|
}
|
|
@@ -2328,7 +2336,7 @@ function atcb_generate_yahoo(data) {
|
|
|
2328
2336
|
function atcb_generate_microsoft(data, type = '365') {
|
|
2329
2337
|
const urlParts = [];
|
|
2330
2338
|
const basePath = (function () {
|
|
2331
|
-
if (
|
|
2339
|
+
if (atcbIsMobile()) {
|
|
2332
2340
|
return '/calendar/0/deeplink/compose?path=%2Fcalendar%2Faction%2Fcompose&rru=addevent';
|
|
2333
2341
|
}
|
|
2334
2342
|
return '/calendar/action/compose?rru=addevent';
|
|
@@ -2362,7 +2370,7 @@ function atcb_generate_msteams(data) {
|
|
|
2362
2370
|
const urlParts = [];
|
|
2363
2371
|
const baseUrl = 'https://teams.microsoft.com/l/meeting/new?';
|
|
2364
2372
|
const formattedDate = atcb_generate_time(data, 'delimiters', 'msteams', true);
|
|
2365
|
-
if (!formattedDate.allday ||
|
|
2373
|
+
if (!formattedDate.allday || atcbIsMobile()) {
|
|
2366
2374
|
urlParts.push('startTime=' + encodeURIComponent(formattedDate.start));
|
|
2367
2375
|
urlParts.push('endTime=' + encodeURIComponent(formattedDate.end));
|
|
2368
2376
|
} else {
|
|
@@ -2409,7 +2417,7 @@ function atcb_generate_ical(host, data, subEvent = 'all', keyboardTrigger = fals
|
|
|
2409
2417
|
}
|
|
2410
2418
|
return '';
|
|
2411
2419
|
})();
|
|
2412
|
-
if (givenIcsFile != '' && (!
|
|
2420
|
+
if (givenIcsFile != '' && (!atcbIsiOS() || (atcbIsiOS() && atcbIsWebView() && data.bypassWebViewCheck == true))) {
|
|
2413
2421
|
atcb_save_file(givenIcsFile, filename);
|
|
2414
2422
|
return;
|
|
2415
2423
|
}
|
|
@@ -2506,7 +2514,7 @@ function atcb_generate_ical(host, data, subEvent = 'all', keyboardTrigger = fals
|
|
|
2506
2514
|
}
|
|
2507
2515
|
return 'data:text/calendar;charset=utf-8,' + encodeURIComponent(ics_lines.join('\r\n'));
|
|
2508
2516
|
})();
|
|
2509
|
-
if ((
|
|
2517
|
+
if ((atcbIsiOS() && !atcbIsSafari()) || (atcbIsWebView() && (atcbIsiOS() || (atcbIsAndroid() && atcbIsProblematicWebView())))) {
|
|
2510
2518
|
atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger);
|
|
2511
2519
|
return;
|
|
2512
2520
|
}
|
|
@@ -2532,7 +2540,7 @@ function atcb_determine_ical_filename(data, subEvent) {
|
|
|
2532
2540
|
}
|
|
2533
2541
|
function atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger) {
|
|
2534
2542
|
atcb_copy_to_clipboard(dataUrl);
|
|
2535
|
-
if (
|
|
2543
|
+
if (atcbIsiOS() && !atcbIsSafari()) {
|
|
2536
2544
|
atcb_create_modal(
|
|
2537
2545
|
host,
|
|
2538
2546
|
data,
|
|
@@ -2560,7 +2568,7 @@ function atcb_save_file(file, filename) {
|
|
|
2560
2568
|
const save = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
|
|
2561
2569
|
save.rel = 'noopener';
|
|
2562
2570
|
save.href = file;
|
|
2563
|
-
if (
|
|
2571
|
+
if (atcbIsMobile()) {
|
|
2564
2572
|
save.target = '_self';
|
|
2565
2573
|
} else {
|
|
2566
2574
|
save.target = '_blank';
|
|
@@ -2626,11 +2634,11 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general', a
|
|
|
2626
2634
|
const endDate = data.endDate.split('-');
|
|
2627
2635
|
const newStartDate = new Date(Date.UTC(startDate[0], startDate[1] - 1, startDate[2], 12, 0, 0));
|
|
2628
2636
|
const newEndDate = new Date(Date.UTC(endDate[0], endDate[1] - 1, endDate[2], 12, 0, 0));
|
|
2629
|
-
if (targetCal === 'google' || (targetCal === 'microsoft' && !
|
|
2637
|
+
if (targetCal === 'google' || (targetCal === 'microsoft' && !atcbIsMobile()) || targetCal === 'msteams' || targetCal === 'ical') {
|
|
2630
2638
|
newEndDate.setDate(newEndDate.getDate() + 1);
|
|
2631
2639
|
}
|
|
2632
2640
|
if (targetCal === 'msteams') {
|
|
2633
|
-
if (
|
|
2641
|
+
if (atcbIsMobile()) {
|
|
2634
2642
|
const offset = newStartDate.getTimezoneOffset();
|
|
2635
2643
|
const formattedOffset = (function () {
|
|
2636
2644
|
if (offset < 0) {
|
|
@@ -2694,7 +2702,7 @@ function atcb_secure_url(url, throwError = true) {
|
|
|
2694
2702
|
}
|
|
2695
2703
|
}
|
|
2696
2704
|
function atcb_validEmail(email) {
|
|
2697
|
-
if (!/^.{0,70}@.{1,30}\.[
|
|
2705
|
+
if (!/^.{0,70}@.{1,30}\.[a-zA-Z]{2,9}$/.test(email)) {
|
|
2698
2706
|
return false;
|
|
2699
2707
|
}
|
|
2700
2708
|
return true;
|
|
@@ -2839,7 +2847,7 @@ function atcb_copy_to_clipboard(dataString) {
|
|
|
2839
2847
|
tmpInput.contentEditable = true;
|
|
2840
2848
|
tmpInput.readOnly = false;
|
|
2841
2849
|
tmpInput.value = dataString;
|
|
2842
|
-
if (
|
|
2850
|
+
if (atcbIsiOS()) {
|
|
2843
2851
|
var range = document.createRange();
|
|
2844
2852
|
range.selectNodeContents(tmpInput);
|
|
2845
2853
|
var selection = window.getSelection();
|
|
@@ -2888,7 +2896,7 @@ function atcb_log_event(event, trigger, identifier) {
|
|
|
2888
2896
|
if (parentEl) {
|
|
2889
2897
|
parentEl.setAttribute('atcb-last-event', event + ':' + trigger);
|
|
2890
2898
|
}
|
|
2891
|
-
if (
|
|
2899
|
+
if (atcbIsBrowser()) {
|
|
2892
2900
|
atcb_push_to_data_layer(event, trigger);
|
|
2893
2901
|
}
|
|
2894
2902
|
}
|
|
@@ -3465,7 +3473,7 @@ let atcbInitialGlobalInit = false;
|
|
|
3465
3473
|
let atcbBtnCount = 0;
|
|
3466
3474
|
const lightModeMutationObserver = [];
|
|
3467
3475
|
const template = `<div class="atcb-initialized" style="display:none;position:relative;width:fit-content;"></div>`;
|
|
3468
|
-
if (
|
|
3476
|
+
if (atcbIsBrowser()) {
|
|
3469
3477
|
class AddToCalendarButton extends HTMLElement {
|
|
3470
3478
|
constructor() {
|
|
3471
3479
|
super();
|
|
@@ -3706,11 +3714,18 @@ function atcb_set_light_mode(shadowRoot, data) {
|
|
|
3706
3714
|
shadowRoot.host.classList.add('atcb-' + hostLightMode);
|
|
3707
3715
|
}
|
|
3708
3716
|
function atcb_load_css(host, rootObj = null, style = '', inline = false, buttonsList = false, customCss = '') {
|
|
3717
|
+
const cspnonceRegex = /[`'"()[\]{}<>\s]/;
|
|
3709
3718
|
if (!document.getElementById('atcb-global-style')) {
|
|
3710
3719
|
const cssGlobalContent = document.createElement('style');
|
|
3711
3720
|
cssGlobalContent.id = 'atcb-global-style';
|
|
3712
3721
|
const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
3713
3722
|
cssGlobalContent.innerText = '.atcb-modal-no-scroll { overflow-y: hidden !important; -webkit-overflow-scrolling: touch; } body.atcb-modal-no-scroll { padding-right: ' + scrollBarWidth + 'px; }';
|
|
3723
|
+
if (host.host.hasAttribute('cspnonce')) {
|
|
3724
|
+
if (cspnonceRegex.test(host.host.getAttribute('cspnonce'))) {
|
|
3725
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
3726
|
+
}
|
|
3727
|
+
cssGlobalContent.setAttribute('nonce', host.host.getAttribute('cspnonce'));
|
|
3728
|
+
}
|
|
3714
3729
|
document.head.append(cssGlobalContent);
|
|
3715
3730
|
}
|
|
3716
3731
|
if (customCss != '' && style == 'custom') {
|
|
@@ -3718,6 +3733,12 @@ function atcb_load_css(host, rootObj = null, style = '', inline = false, buttons
|
|
|
3718
3733
|
cssFile.setAttribute('rel', 'stylesheet');
|
|
3719
3734
|
cssFile.setAttribute('type', 'text/css');
|
|
3720
3735
|
cssFile.setAttribute('href', customCss);
|
|
3736
|
+
if (host.host.hasAttribute('cspnonce')) {
|
|
3737
|
+
if (cspnonceRegex.test(host.host.getAttribute('cspnonce'))) {
|
|
3738
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
3739
|
+
}
|
|
3740
|
+
cssFile.setAttribute('nonce', host.host.getAttribute('cspnonce'));
|
|
3741
|
+
}
|
|
3721
3742
|
if (rootObj == null) {
|
|
3722
3743
|
host.host.style.display = 'none';
|
|
3723
3744
|
loadExternalCssAsynch(cssFile, host, host.host);
|
|
@@ -3731,6 +3752,12 @@ function atcb_load_css(host, rootObj = null, style = '', inline = false, buttons
|
|
|
3731
3752
|
}
|
|
3732
3753
|
if (style != 'none' && atcbCssTemplate[`${style}`] != null) {
|
|
3733
3754
|
const cssContent = document.createElement('style');
|
|
3755
|
+
if (host.host.hasAttribute('cspnonce')) {
|
|
3756
|
+
if (cspnonceRegex.test(host.host.getAttribute('cspnonce'))) {
|
|
3757
|
+
throw new Error("cspnonce input contains forbidden characters.");
|
|
3758
|
+
}
|
|
3759
|
+
cssContent.setAttribute('nonce', host.host.getAttribute('cspnonce'));
|
|
3760
|
+
}
|
|
3734
3761
|
const overrideDefaultCss = (function () {
|
|
3735
3762
|
if (host.host.hasAttribute('styleLight')) {
|
|
3736
3763
|
const output = ':host { ' + atcb_secure_content(host.host.getAttribute('styleLight').replace(/(\\r\\n|\\n|\\r)/g, ''), false) + ' }';
|
|
@@ -3792,7 +3819,7 @@ function atcb_render_debug_msg(host, error) {
|
|
|
3792
3819
|
}
|
|
3793
3820
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3794
3821
|
function atcb_action(data, triggerElement, keyboardTrigger = false) {
|
|
3795
|
-
if (!
|
|
3822
|
+
if (!atcbIsBrowser()) {
|
|
3796
3823
|
return;
|
|
3797
3824
|
}
|
|
3798
3825
|
data = atcb_secure_content(data);
|
|
@@ -3848,7 +3875,7 @@ function atcb_action(data, triggerElement, keyboardTrigger = false) {
|
|
|
3848
3875
|
atcb_log_event('initialization', data.identifier, data.identifier);
|
|
3849
3876
|
if (!data.blockInteraction) {
|
|
3850
3877
|
let host = null;
|
|
3851
|
-
if (!oneOption || (data.options[0] !== 'apple' && data.options[0] !== 'ical') || (data.dates && data.dates.length > 1 && data.dates.organizer) || (
|
|
3878
|
+
if (!oneOption || (data.options[0] !== 'apple' && data.options[0] !== 'ical') || (data.dates && data.dates.length > 1 && data.dates.organizer) || (atcbIsMobile())) {
|
|
3852
3879
|
host = document.createElement('div');
|
|
3853
3880
|
host.id = 'atcb-customTrigger-' + data.identifier + '-host';
|
|
3854
3881
|
if (root == document.body) {
|
|
@@ -3927,7 +3954,7 @@ function atcb_get_pro_data(licenseKey) {
|
|
|
3927
3954
|
return data;
|
|
3928
3955
|
}
|
|
3929
3956
|
function atcb_set_global_event_listener(host, data) {
|
|
3930
|
-
if (!
|
|
3957
|
+
if (!atcbIsBrowser()) {
|
|
3931
3958
|
return;
|
|
3932
3959
|
}
|
|
3933
3960
|
if (data.lightMode == 'bodyScheme') {
|
package/index.d.ts
CHANGED