From 1769a6b81f8946a4c22a5e5dc71bdbecb306127e Mon Sep 17 00:00:00 2001 From: "Evgeny @ SimpleX Chat" <259188159+evgeny-simplex@users.noreply.github.com> Date: Sun, 31 May 2026 07:28:29 +0000 Subject: [PATCH] website: use cpp to inject JS functions --- .gitignore | 1 + website/.eleventy.js | 2 +- website/src/js/directory.js | 297 +++++++++++++++++++----------------- website/web.sh | 4 + 4 files changed, 163 insertions(+), 141 deletions(-) diff --git a/.gitignore b/.gitignore index 7bd3d04e59..1cd2a09f40 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ website/src/img/images/ website/src/images/ website/src/js/lottie.min.js website/src/js/ethers* +website/src/js/directory.js website/src/file-assets/ website/src/link-images/ website/src/privacy.md diff --git a/website/.eleventy.js b/website/.eleventy.js index f0310c5665..0567dd45d8 100644 --- a/website/.eleventy.js +++ b/website/.eleventy.js @@ -310,7 +310,7 @@ module.exports = function (ty) { ty.addPassthroughCopy("src/img") ty.addPassthroughCopy("src/video") ty.addPassthroughCopy("src/css") - ty.addPassthroughCopy("src/js") + ty.addPassthroughCopy("src/js/**/*.js") ty.addPassthroughCopy("src/lottie_file") ty.addPassthroughCopy("src/contact/*.js") ty.addPassthroughCopy("src/call") diff --git a/website/src/js/directory.js b/website/src/js/directory.js index afaac1053f..64bb4b2097 100644 --- a/website/src/js/directory.js +++ b/website/src/js/directory.js @@ -1,3 +1,160 @@ + + + + + + + + + + + +const isMobile = { + Android: () => navigator.userAgent.match(/Android/i), + iOS: () => navigator.userAgent.match(/iPhone|iPad|iPod/i), + any: () => navigator.userAgent.match(/Android|iPhone|iPad|iPod/i) +}; + +function escapeHtml(text) { + return text + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'") + .replace(/\n/g, "
"); +} + +function getSimplexLinkDescr(linkType) { + switch (linkType) { + case 'contact': return 'SimpleX contact address'; + case 'invitation': return 'SimpleX one-time invitation'; + case 'group': return 'SimpleX group link'; + case 'channel': return 'SimpleX channel link'; + case 'relay': return 'SimpleX relay link'; + default: return 'SimpleX link'; + } +} + +function viaHost(smpHosts) { + const first = smpHosts[0] ?? '?'; + return `via ${first}`; +} + +function isCurrentSite(uri) { + return uri.startsWith("https://simplex.chat") || uri.startsWith("https://www.simplex.chat") +} + +function targetBlank(uri) { + return isCurrentSite(uri) ? '' : ' target="_blank"' +} + +function renderMarkdown(fts) { + let html = ''; + for (const ft of fts) { + const { format, text } = ft; + if (!format) { + html += escapeHtml(text); + continue; + } + try { + switch (format.type) { + case 'bold': + html += `${escapeHtml(text)}`; + break; + case 'italic': + html += `${escapeHtml(text)}`; + break; + case 'strikeThrough': + html += `${escapeHtml(text)}`; + break; + case 'snippet': + html += `${escapeHtml(text)}`; + break; + case 'secret': + html += `${escapeHtml(text)}`; + break; + case 'small': + html += `${escapeHtml(text)}`; + break; + case 'colored': + html += `${escapeHtml(text)}`; + break; + case 'uri': + let href = text.startsWith('http://') || text.startsWith('https://') || text.startsWith('simplex:/') ? text : 'https://' + text; + html += `${escapeHtml(text)}`; + break; + case 'hyperLink': { + const { showText, linkUri } = format; + html += `${escapeHtml(showText ?? linkUri)}`; + break; + } + case 'simplexLink': { + const { showText, linkType, simplexUri, smpHosts } = format; + const linkText = showText ? escapeHtml(showText) : getSimplexLinkDescr(linkType); + html += `${linkText} (${viaHost(smpHosts)})`; + break; + } + case 'command': + html += `${escapeHtml(text)}`; + break; + case 'mention': + html += `${escapeHtml(text)}`; + break; + case 'email': + html += `${escapeHtml(text)}`; + break; + case 'phone': + html += `${escapeHtml(text)}`; + break; + case 'unknown': + html += escapeHtml(text); + break; + default: + html += escapeHtml(text); + } + } catch(e) { + console.log(e); + html += escapeHtml(text); + } + } + return html; +} + +const simplexAddressRegexp = /^simplex:\/([a-z]+)#(.+)/i; + +const simplexShortLinkTypes = ["a", "c", "g", "i", "r"]; + +function platformSimplexUri(uri) { + if (isMobile.any()) return uri; + const res = uri.match(simplexAddressRegexp); + if (!res || !Array.isArray(res) || res.length < 3) return uri; + const linkType = res[1]; + const fragment = res[2]; + if (simplexShortLinkTypes.includes(linkType)) { + const queryIndex = fragment.indexOf('?'); + if (queryIndex === -1) return uri; + const hashPart = fragment.substring(0, queryIndex); + const queryStr = fragment.substring(queryIndex + 1); + const params = new URLSearchParams(queryStr); + const host = params.get('h'); + if (!host) return uri; + params.delete('h'); + let newFragment = hashPart; + const remainingParams = params.toString(); + if (remainingParams) newFragment += '?' + remainingParams; + return `https://${host}:/${linkType}#${newFragment}`; + } else { + return `https://simplex.chat/${linkType}#${fragment}`; + } +} + +const simplexDirectoryDataURL = 'https://directory.simplex.chat/data/'; + +// const simplexDirectoryDataURL = 'http://localhost:8080/directory-data/'; + +const simplexUsersGroup = 'SimpleX users group'; + (function() { if (!document.location.pathname.startsWith('/directory')) return; @@ -428,144 +585,4 @@ if (document.readyState === 'loading') { } else { initDirectory(); } - -function escapeHtml(text) { - return text - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'") - .replace(/\n/g, "
"); -} - -function getSimplexLinkDescr(linkType) { - switch (linkType) { - case 'contact': return 'SimpleX contact address'; - case 'invitation': return 'SimpleX one-time invitation'; - case 'group': return 'SimpleX group link'; - case 'channel': return 'SimpleX channel link'; - case 'relay': return 'SimpleX relay link'; - default: return 'SimpleX link'; - } -} - -function viaHost(smpHosts) { - const first = smpHosts[0] ?? '?'; - return `via ${first}`; -} - -function isCurrentSite(uri) { - return uri.startsWith("https://simplex.chat") || uri.startsWith("https://www.simplex.chat") -} - -function targetBlank(uri) { - return isCurrentSite(uri) ? '' : ' target="_blank"' -} - -function renderMarkdown(fts) { - let html = ''; - for (const ft of fts) { - const { format, text } = ft; - if (!format) { - html += escapeHtml(text); - continue; - } - try { - switch (format.type) { - case 'bold': - html += `${escapeHtml(text)}`; - break; - case 'italic': - html += `${escapeHtml(text)}`; - break; - case 'strikeThrough': - html += `${escapeHtml(text)}`; - break; - case 'snippet': - html += `${escapeHtml(text)}`; - break; - case 'secret': - html += `${escapeHtml(text)}`; - break; - case 'small': - html += `${escapeHtml(text)}`; - break; - case 'colored': - html += `${escapeHtml(text)}`; - break; - case 'uri': - let href = text.startsWith('http://') || text.startsWith('https://') || text.startsWith('simplex:/') ? text : 'https://' + text; - html += `${escapeHtml(text)}`; - break; - case 'hyperLink': { - const { showText, linkUri } = format; - html += `${escapeHtml(showText ?? linkUri)}`; - break; - } - case 'simplexLink': { - const { showText, linkType, simplexUri, smpHosts } = format; - const linkText = showText ? escapeHtml(showText) : getSimplexLinkDescr(linkType); - html += `${linkText} (${viaHost(smpHosts)})`; - break; - } - case 'command': - html += `${escapeHtml(text)}`; - break; - case 'mention': - html += `${escapeHtml(text)}`; - break; - case 'email': - html += `${escapeHtml(text)}`; - break; - case 'phone': - html += `${escapeHtml(text)}`; - break; - case 'unknown': - html += escapeHtml(text); - break; - default: - html += escapeHtml(text); - } - } catch(e) { - console.log(e); - html += escapeHtml(text); - } - } - return html; -} })(); - -const simplexDirectoryDataURL = 'https://directory.simplex.chat/data/'; - -// const simplexDirectoryDataURL = 'http://localhost:8080/directory-data/'; - -const simplexUsersGroup = 'SimpleX users group'; - -const simplexAddressRegexp = /^simplex:\/([a-z]+)#(.+)/i; - -const simplexShortLinkTypes = ["a", "c", "g", "i", "r"]; - -function platformSimplexUri(uri) { - if (isMobile.any()) return uri; - const res = uri.match(simplexAddressRegexp); - if (!res || !Array.isArray(res) || res.length < 3) return uri; - const linkType = res[1]; - const fragment = res[2]; - if (simplexShortLinkTypes.includes(linkType)) { - const queryIndex = fragment.indexOf('?'); - if (queryIndex === -1) return uri; - const hashPart = fragment.substring(0, queryIndex); - const queryStr = fragment.substring(queryIndex + 1); - const params = new URLSearchParams(queryStr); - const host = params.get('h'); - if (!host) return uri; - params.delete('h'); - let newFragment = hashPart; - const remainingParams = params.toString(); - if (remainingParams) newFragment += '?' + remainingParams; - return `https://${host}:/${linkType}#${newFragment}`; - } else { - return `https://simplex.chat/${linkType}#${fragment}`; - } -} diff --git a/website/web.sh b/website/web.sh index 9464982a45..49888f78aa 100755 --- a/website/web.sh +++ b/website/web.sh @@ -55,6 +55,10 @@ for lang in "${langs[@]}"; do echo "done $lang copying" done +for f in src/js/*.jsc; do + [ -f "$f" ] && cpp -P -traditional-cpp "$f" "${f%.jsc}.js" +done + npm run build for lang in "${langs[@]}"; do