diff --git a/lib/frontend/actions/events.js b/lib/frontend/actions/events.js index 60d41b4..136ae15 100644 --- a/lib/frontend/actions/events.js +++ b/lib/frontend/actions/events.js @@ -1,7 +1,12 @@ import { postURL } from '../services' import { eventStore, parseStatusStore, requestStore } from '../stores' import { Request } from '../records' -import { uuidv4, parseStartTimeFromiCalString, promptDownload } from '../utils' +import { + uuidv4, + parseStartTimeFromiCalString, + promptDownload, + encodeIcalString, +} from '../utils' import { extractEventDataFromHTML } from '../../../lib/services/ics-retriever' import generateICS from '../../../lib/services/ics-generator' @@ -35,7 +40,7 @@ const createICS = async (html, url, { logger }) => { const eventData = extractEventDataFromHTML(html, url, { logger }) const text = await generateICS(eventData) - const dataUri = encodeURIComponent(text) + const dataUri = encodeIcalString(text) const uri = `data:text/calendar;charset=utf-8,${dataUri}` const summaryMatch = text.match(/SUMMARY:.*/)[0] diff --git a/lib/frontend/utils.js b/lib/frontend/utils.js index 9abeb83..68032e3 100644 --- a/lib/frontend/utils.js +++ b/lib/frontend/utils.js @@ -1,3 +1,5 @@ +const UNICODE_RE = /[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g + export const migrateRecord = (record) => { // NOTE: v3 records const id = record.id || record.order @@ -55,3 +57,13 @@ export const promptDownload = (uri) => { link.setAttribute('href', '') } + +export const encodeIcalString = (string) => { + try { + return encodeURIComponent(string) + } catch { + return string.replace(UNICODE_RE , ($0) => { + return $0.length > 1 ? $0 : '\ufffd'; + }) + } +}