add-to-calendar-button 2.6.21 → 2.7.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.
@@ -974,14 +974,14 @@ function tzlib_get_timezones(jsonType = false) {
974
974
  * Add to Calendar Button
975
975
  * ++++++++++++++++++++++
976
976
  *
977
- * Version: 2.6.21
977
+ * Version: 2.7.1
978
978
  * Creator: Jens Kuerschner (https://jekuer.com)
979
979
  * Project: https://github.com/add2cal/add-to-calendar-button
980
980
  * License: Elastic License 2.0 (ELv2) (https://github.com/add2cal/add-to-calendar-button/blob/main/LICENSE.txt)
981
981
  * Note: DO NOT REMOVE THE COPYRIGHT NOTICE ABOVE!
982
982
  *
983
983
  */
984
- const atcbVersion = '2.6.21';
984
+ const atcbVersion = '2.7.1';
985
985
  const atcbCssTemplate = {};
986
986
  const atcbIsBrowser = () => {
987
987
  if (typeof window === 'undefined') {
@@ -1516,8 +1516,9 @@ function atcb_decorate_data_description(data, i) {
1516
1516
  description = cleanDescription(description);
1517
1517
  if (data.customVar) {
1518
1518
  for (const key in data.customVar) {
1519
- const sanitizedKey = key.replace(/[^\w\-.]/g, '');
1520
- description = description.replace(new RegExp(`%%${sanitizedKey}%%`, 'g'), data.customVar[`${key}`]);
1519
+ const sanitizedKey = '%%' + key.replace(/[^\w\-.]/g, '') + '%%';
1520
+ // eslint-disable-next-line security/detect-non-literal-regexp
1521
+ description = description.replace(new RegExp(sanitizedKey, 'gi'), data.customVar[`${key}`]);
1521
1522
  }
1522
1523
  }
1523
1524
  const descriptionHtmlFree = atcb_rewrite_html_elements(description, true);
@@ -1575,9 +1576,11 @@ function atcb_decorate_data_extend(data) {
1575
1576
  }
1576
1577
  if (data.customVar) {
1577
1578
  for (const key in data.customVar) {
1578
- const sanitizedKey = key.replace(/[^\w\-.]/g, '');
1579
- data.dates[`${i}`].name = data.dates[`${i}`].name.replace(new RegExp(`%%${sanitizedKey}%%`, 'g'), data.customVar[`${key}`]);
1580
- data.dates[`${i}`].location = data.dates[`${i}`].location.replace(new RegExp(`%%${sanitizedKey}%%`, 'g'), data.customVar[`${key}`]);
1579
+ const sanitizedKey = '%%' + key.replace(/[^\w\-.]/g, '') + '%%';
1580
+ // eslint-disable-next-line security/detect-non-literal-regexp
1581
+ data.dates[`${i}`].name = data.dates[`${i}`].name.replace(new RegExp(sanitizedKey, 'gi'), data.customVar[`${key}`]);
1582
+ // eslint-disable-next-line security/detect-non-literal-regexp
1583
+ data.dates[`${i}`].location = data.dates[`${i}`].location.replace(new RegExp(sanitizedKey, 'gi'), data.customVar[`${key}`]);
1581
1584
  }
1582
1585
  }
1583
1586
  }
@@ -1590,26 +1593,31 @@ function atcb_decorate_data_extend(data) {
1590
1593
  return data;
1591
1594
  }
1592
1595
  function atcb_date_cleanup(dateTimeData) {
1596
+ function isValidDateFormat(dateStr) {
1597
+ return /^\d\d\d\d-\d\d-\d\d(?:T\d\d:\d\d)?(?::\d\d)?(?:.\d\d\d)?Z?$/i.test(dateStr);
1598
+ }
1599
+ function isValidTodayFormat(dateStr) {
1600
+ return /^today(?:\+(?:\d|\d\d|\d\d\d|\d\d\d\d))?$/i.test(dateStr);
1601
+ }
1593
1602
  if (!dateTimeData.endDate || dateTimeData.endDate === '') {
1594
1603
  dateTimeData.endDate = dateTimeData.startDate;
1595
1604
  }
1596
1605
  const endpoints = ['start', 'end'];
1597
1606
  endpoints.forEach(function (point) {
1598
- if (!/^(?:\d{4}-\d{2}-\d{2}T?(?:\d{2}:\d{2})?Z?|today(?:\+\d{1,4})?)$/i.test(dateTimeData[point + 'Date'])) {
1607
+ const dateStr = dateTimeData[point + 'Date'];
1608
+ if (!isValidDateFormat(dateStr) && !isValidTodayFormat(dateStr)) {
1599
1609
  dateTimeData[point + 'Date'] = 'badly-formed';
1600
1610
  } else {
1601
- dateTimeData[point + 'Date'] = atcb_date_calculation(dateTimeData[point + 'Date']);
1611
+ if (isValidTodayFormat(dateStr)) dateTimeData[point + 'Date'] = atcb_date_calculation(dateStr);
1602
1612
  if (dateTimeData[point + 'Date']) {
1603
- dateTimeData[point + 'Date'] = dateTimeData[point + 'Date'].replace(/\.\d{3}/, '').replace('Z', '');
1604
1613
  const tmpSplitStartDate = dateTimeData[point + 'Date'].split('T');
1605
1614
  if (tmpSplitStartDate[1]) {
1606
1615
  dateTimeData[point + 'Date'] = tmpSplitStartDate[0];
1607
1616
  dateTimeData[point + 'Time'] = tmpSplitStartDate[1];
1608
1617
  }
1609
1618
  }
1610
- if (dateTimeData[point + 'Time'] && dateTimeData[point + 'Time'].length === 8) {
1611
- const timeStr = dateTimeData[point + 'Time'];
1612
- dateTimeData[point + 'Time'] = timeStr.substring(0, timeStr.length - 3);
1619
+ if (dateTimeData[point + 'Time'] && dateTimeData[point + 'Time'].length > 5) {
1620
+ dateTimeData[point + 'Time'] = dateTimeData[point + 'Time'].substring(0, 5);
1613
1621
  }
1614
1622
  }
1615
1623
  });
@@ -1654,12 +1662,7 @@ function atcb_date_calculation(dateString) {
1654
1662
  dateString = dateString.replace(/today/gi, todayString);
1655
1663
  const dateStringParts = dateString.split('+');
1656
1664
  const dateParts = dateStringParts[0].split('-');
1657
- let newDate = (function () {
1658
- if (dateParts[0].length < 4) {
1659
- return new Date(Date.UTC(dateParts[2], dateParts[0] - 1, dateParts[1]));
1660
- }
1661
- return new Date(Date.UTC(dateParts[0], dateParts[1] - 1, dateParts[2]));
1662
- })();
1665
+ const newDate = new Date(Date.UTC(dateParts[0], dateParts[1] - 1, dateParts[2].substring(0, 2)));
1663
1666
  if (dateStringParts[1] && dateStringParts[1] > 0) {
1664
1667
  newDate.setDate(newDate.getDate() + parseInt(dateStringParts[1]));
1665
1668
  }
@@ -1702,19 +1705,25 @@ function atcb_decorate_data_button_status_handling(data) {
1702
1705
  return data;
1703
1706
  }
1704
1707
  async function atcb_decorate_data_rsvp(data) {
1705
- if (typeof atcb_check_booked_out !== 'function' || !data.rsvp || Object.keys(data.rsvp).length === 0) return data;
1708
+ if (typeof atcb_check_bookings !== 'function' || !data.rsvp || !data.proKey || Object.keys(data.rsvp).length === 0) return data;
1706
1709
  data.rsvp.expired = (function () {
1707
1710
  if (data.rsvp && data.rsvp.expires && new Date(data.rsvp.expires) < new Date()) {
1708
1711
  return true;
1709
1712
  }
1710
1713
  return false;
1711
1714
  })();
1712
- data.rsvp.bookedOut = await atcb_check_booked_out(data);
1713
- if (data.rsvp.expired || data.rsvp.bookedOut) {
1714
- data.blockInteraction = true;
1715
- }
1716
- if (data.blockInteraction) {
1717
- data.disabled = true;
1715
+ if (data.rsvp.max) {
1716
+ const bookings = await atcb_check_bookings(data.proKey, data.dev);
1717
+ data.rsvp.seatsLeft = data.rsvp.max - bookings;
1718
+ if (data.rsvp.seatsLeft < 1) {
1719
+ data.rsvp.bookedOut = true;
1720
+ }
1721
+ if (data.rsvp.expired || data.rsvp.bookedOut) {
1722
+ data.blockInteraction = true;
1723
+ }
1724
+ if (data.blockInteraction) {
1725
+ data.disabled = true;
1726
+ }
1718
1727
  }
1719
1728
  return data;
1720
1729
  }
@@ -2453,6 +2462,9 @@ async function atcb_generate_rsvp_form(host, data, hostEl, keyboardTrigger = fal
2453
2462
  ' class="atcb-modal-btn atcb-modal-btn-primary atcb-modal-btn-border">' +
2454
2463
  atcb_translate_hook('submit', data) +
2455
2464
  '</button><span id="pro-form-submitting" class="pro-waiting"><span>.</span><span>.</span><span>.</span></span></p>';
2465
+ if (rsvpData.seatsLeft && rsvpData.seatsLeft > 0) {
2466
+ rsvpContent += '<p class="pro-form-fine">' + atcb_translate_hook('form.seatsleft', data) + ': <b>' + rsvpData.seatsLeft + '</b></p>';
2467
+ }
2456
2468
  rsvpContent += '</form>';
2457
2469
  rsvpContent += '</div></div>';
2458
2470
  let rsvpHost = null;
@@ -2692,24 +2704,20 @@ async function atcb_generate_rsvp_button(host, data) {
2692
2704
  }
2693
2705
  return true;
2694
2706
  }
2695
- async function atcb_check_booked_out(data) {
2696
- if (data.rsvp && data.rsvp.max && data.proKey && data.proKey !== '') {
2697
- try {
2698
- const response = await fetch('https://api.add-to-calendar-pro.com/dffb8bbd-ee5e-4a4f-a7ea-503af98ca468?prokey=' + data.proKey + (data.dev ? '&dev=true' : ''), {
2699
- method: 'GET',
2700
- });
2701
- if (!response.ok) {
2702
- throw new Error('Network response was not ok');
2703
- }
2704
- const responseJson = await response.json();
2705
- if (parseInt(responseJson.total) >= data.rsvp.max) {
2706
- return true;
2707
- }
2708
- } catch (error) {
2709
- console.error('Error:', error);
2707
+ async function atcb_check_bookings(proKey, dev = false) {
2708
+ try {
2709
+ const response = await fetch('https://api.add-to-calendar-pro.com/dffb8bbd-ee5e-4a4f-a7ea-503af98ca468?prokey=' + proKey + (dev ? '&dev=true' : ''), {
2710
+ method: 'GET',
2711
+ });
2712
+ if (!response.ok) {
2713
+ throw new Error('Network response was not ok');
2710
2714
  }
2715
+ const responseJson = await response.json();
2716
+ return parseInt(responseJson.total);
2717
+ } catch (error) {
2718
+ console.error('Error:', error);
2711
2719
  }
2712
- return false;
2720
+ return 0;
2713
2721
  }
2714
2722
  function atcb_build_form(fields, identifier = '', disabled = false) {
2715
2723
  /*!
@@ -3829,7 +3837,7 @@ function atcb_generate_subscribe_links(host, linkType, data, keyboardTrigger) {
3829
3837
  atcb_subscribe_ical(data, data.icsFile);
3830
3838
  break;
3831
3839
  }
3832
- atcb_subscribe_ical(data, adjustedFileUrl);
3840
+ atcb_subscribe_ical(data, adjustedFileUrl, host, keyboardTrigger);
3833
3841
  break;
3834
3842
  case 'google':
3835
3843
  atcb_subscribe_google(data, adjustedFileUrl);
@@ -3898,7 +3906,11 @@ function atcb_set_fully_successful(host, data, multiDateModal = false) {
3898
3906
  atcb_toggle(host, 'close');
3899
3907
  }
3900
3908
  }
3901
- function atcb_subscribe_ical(data, fileUrl) {
3909
+ function atcb_subscribe_ical(data, fileUrl, host = null, keyboardTrigger = false) {
3910
+ if ((atcbIsiOS() || data.fakeIOS) && !atcbIsSafari()) {
3911
+ atcb_ical_copy_note(host, fileUrl, data, keyboardTrigger);
3912
+ return;
3913
+ }
3902
3914
  atcb_open_cal_url(data, 'ical', fileUrl, true);
3903
3915
  }
3904
3916
  function atcb_subscribe_google(data, fileUrl) {
@@ -4223,7 +4235,7 @@ function atcb_generate_ical(host, data, subEvent = 'all', keyboardTrigger = fals
4223
4235
  }
4224
4236
  return 'data:text/calendar;charset=utf-8,' + encodeURIComponent(ics_lines.join('\r\n'));
4225
4237
  })();
4226
- if ((atcbIsiOS() && !atcbIsSafari()) || (atcbIsWebView() && (atcbIsiOS() || (atcbIsAndroid() && atcbIsProblematicWebView())))) {
4238
+ if (((atcbIsiOS() || data.fakeIOS) && !atcbIsSafari()) || (atcbIsWebView() && (atcbIsiOS() || data.fakeIOS || ((atcbIsAndroid() || data.fakeAndroid) && atcbIsProblematicWebView())))) {
4227
4239
  atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger);
4228
4240
  return;
4229
4241
  }
@@ -4249,7 +4261,7 @@ function atcb_determine_ical_filename(data, subEvent) {
4249
4261
  }
4250
4262
  function atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger) {
4251
4263
  atcb_copy_to_clipboard(dataUrl);
4252
- if (atcbIsiOS() && !atcbIsSafari()) {
4264
+ if ((atcbIsiOS() || data.fakeIOS) && !atcbIsSafari()) {
4253
4265
  atcb_create_modal(
4254
4266
  host,
4255
4267
  data,
@@ -5766,27 +5778,26 @@ if (atcbIsBrowser()) {
5766
5778
  }
5767
5779
  this.proOverride = !proOverrideVal || proOverrideVal === 'true' || proOverrideVal === '' ? true : false;
5768
5780
  }
5769
- if ((this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') || (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '')) {
5770
- if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5771
- this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5781
+ try {
5782
+ if ((this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') || (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '')) {
5783
+ if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5784
+ this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5785
+ } else {
5786
+ this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5787
+ }
5788
+ if (this.data.proKey) this.proKey = this.data.proKey;
5772
5789
  } else {
5773
- this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5774
- }
5775
- if (this.data.proKey) this.proKey = this.data.proKey;
5776
- }
5777
- if (!this.data.name || this.data.name === '') {
5778
- this.data.proKey = '';
5779
- try {
5790
+ this.data.proKey = '';
5780
5791
  this.data = await atcb_process_inline_data(this, this.debug);
5781
- } catch (e) {
5782
- if (this.debug) {
5783
- console.error(e);
5784
- atcb_render_debug_msg(this.shadowRoot, e);
5785
- }
5786
- this.state.initializing = false;
5787
- this.state.ready = true;
5788
- return;
5789
5792
  }
5793
+ } catch (e) {
5794
+ if (this.debug) {
5795
+ console.error(e);
5796
+ atcb_render_debug_msg(this.shadowRoot, e);
5797
+ }
5798
+ this.state.initializing = false;
5799
+ this.state.ready = true;
5800
+ return;
5790
5801
  }
5791
5802
  await this.initButton();
5792
5803
  this.state.initializing = false;
@@ -5841,24 +5852,23 @@ if (atcbIsBrowser()) {
5841
5852
  const elem = document.createElement('template');
5842
5853
  elem.innerHTML = template;
5843
5854
  this.shadowRoot.append(elem.content.cloneNode(true));
5844
- if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5845
- this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5846
- if (this.data.proKey) this.proKey = this.data.proKey;
5847
- } else if (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '') {
5848
- this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5849
- if (this.data.proKey) this.proKey = this.data.proKey;
5850
- }
5851
- if (!this.data.name || this.data.name === '') {
5852
- try {
5855
+ try {
5856
+ if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5857
+ this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5858
+ if (this.data.proKey) this.proKey = this.data.proKey;
5859
+ } else if (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '') {
5860
+ this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5861
+ if (this.data.proKey) this.proKey = this.data.proKey;
5862
+ } else {
5853
5863
  this.data = await atcb_process_inline_data(this, this.debug);
5854
- } catch (e) {
5855
- if (this.debug) {
5856
- console.error(e);
5857
- atcb_render_debug_msg(this.shadowRoot, e);
5858
- }
5859
- this.updatePending = false;
5860
- return;
5861
5864
  }
5865
+ } catch (e) {
5866
+ if (this.debug) {
5867
+ console.error(e);
5868
+ atcb_render_debug_msg(this.shadowRoot, e);
5869
+ }
5870
+ this.updatePending = false;
5871
+ return;
5862
5872
  }
5863
5873
  atcb_cleanup(this.shadowRoot, this.identifier);
5864
5874
  await this.initButton();
@@ -6189,19 +6199,28 @@ async function atcb_action(inputData, triggerElement, keyboardTrigger = false) {
6189
6199
  if (!atcbIsBrowser()) {
6190
6200
  return;
6191
6201
  }
6192
- let data = await (async function () {
6193
- const cleanedInput = atcb_secure_content(inputData);
6194
- if (cleanedInput.prokey && cleanedInput.prokey !== '') {
6195
- cleanedInput.proKey = cleanedInput.prokey;
6196
- }
6197
- if (cleanedInput.proKey && cleanedInput.proKey !== '') {
6198
- const proData = await atcb_get_pro_data(cleanedInput.proKey, null, cleanedInput);
6199
- if (proData.name && proData.name != '') {
6200
- return proData;
6202
+ let data;
6203
+ try {
6204
+ data = await (async function () {
6205
+ const cleanedInput = atcb_secure_content(inputData);
6206
+ if (cleanedInput.prokey && cleanedInput.prokey !== '') {
6207
+ cleanedInput.proKey = cleanedInput.prokey;
6201
6208
  }
6202
- }
6203
- return cleanedInput;
6204
- })();
6209
+ if (cleanedInput.proKey && cleanedInput.proKey !== '') {
6210
+ try {
6211
+ const proData = await atcb_get_pro_data(cleanedInput.proKey, null, cleanedInput);
6212
+ return proData;
6213
+ } catch (e) {
6214
+ throw new Error(e.message);
6215
+ }
6216
+ } else {
6217
+ return cleanedInput;
6218
+ }
6219
+ })();
6220
+ } catch (e) {
6221
+ console.error(e);
6222
+ return;
6223
+ }
6205
6224
  data.debug = data.debug === 'true';
6206
6225
  try {
6207
6226
  await atcb_check_required(data);
@@ -6339,9 +6358,6 @@ async function atcb_get_pro_data(licenseKey, el = null, directData = {}) {
6339
6358
  const response = await fetch((dataOverrides.dev ? 'https://event-dev.caldn.net/' : 'https://event.caldn.net/') + licenseKey + '/config.json');
6340
6359
  if (response.ok) {
6341
6360
  const data = await response.json();
6342
- if (!data.name || data.name === '') {
6343
- throw new Error('Not possible to read proKey config from server...');
6344
- }
6345
6361
  if (proOverride) {
6346
6362
  atcbWcParams.forEach((key) => {
6347
6363
  if (Object.prototype.hasOwnProperty.call(dataOverrides, key) && ['hideBranding', 'hidebranding', 'rsvp', 'ty'].indexOf(key) === -1) {
@@ -6355,13 +6371,16 @@ async function atcb_get_pro_data(licenseKey, el = null, directData = {}) {
6355
6371
  }
6356
6372
  });
6357
6373
  }
6374
+ if (!data.name || data.name === '') {
6375
+ throw new Error('Not possible to read proKey config from server...');
6376
+ }
6358
6377
  data.proKey = licenseKey;
6359
6378
  data.identifier = licenseKey;
6360
6379
  return data;
6361
6380
  }
6362
6381
  throw new Error('Not possible to read proKey config from server...');
6363
6382
  } catch {
6364
- console.error('Add to Calendar Button proKey invalid or server not responding! Falling back to local data...');
6383
+ throw new Error('Add to Calendar Button proKey invalid or server not responding!');
6365
6384
  }
6366
6385
  }
6367
6386
  return {};