website: use cpp to inject JS functions

This commit is contained in:
Evgeny @ SimpleX Chat
2026-05-31 07:28:29 +00:00
parent 5b733f0d71
commit 1769a6b81f
4 changed files with 163 additions and 141 deletions
+1
View File
@@ -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
+1 -1
View File
@@ -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")
+157 -140
View File
@@ -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, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;")
.replace(/\n/g, "<br>");
}
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 += `<strong>${escapeHtml(text)}</strong>`;
break;
case 'italic':
html += `<em>${escapeHtml(text)}</em>`;
break;
case 'strikeThrough':
html += `<s>${escapeHtml(text)}</s>`;
break;
case 'snippet':
html += `<span style="font-family: monospace;">${escapeHtml(text)}</span>`;
break;
case 'secret':
html += `<span class="secret">${escapeHtml(text)}</span>`;
break;
case 'small':
html += `<span class="small-text">${escapeHtml(text)}</span>`;
break;
case 'colored':
html += `<span class="${format.color}">${escapeHtml(text)}</span>`;
break;
case 'uri':
let href = text.startsWith('http://') || text.startsWith('https://') || text.startsWith('simplex:/') ? text : 'https://' + text;
html += `<a href="${href}"${targetBlank(href)}>${escapeHtml(text)}</a>`;
break;
case 'hyperLink': {
const { showText, linkUri } = format;
html += `<a href="${linkUri}"${targetBlank(linkUri)}>${escapeHtml(showText ?? linkUri)}</a>`;
break;
}
case 'simplexLink': {
const { showText, linkType, simplexUri, smpHosts } = format;
const linkText = showText ? escapeHtml(showText) : getSimplexLinkDescr(linkType);
html += `<a href="${platformSimplexUri(simplexUri)}" target="_blank">${linkText} <em>(${viaHost(smpHosts)})</em></a>`;
break;
}
case 'command':
html += `<span style="font-family: monospace;">${escapeHtml(text)}</span>`;
break;
case 'mention':
html += `<strong>${escapeHtml(text)}</strong>`;
break;
case 'email':
html += `<a href="mailto:${text}">${escapeHtml(text)}</a>`;
break;
case 'phone':
html += `<a href="tel:${text}">${escapeHtml(text)}</a>`;
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, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;")
.replace(/\n/g, "<br>");
}
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 += `<strong>${escapeHtml(text)}</strong>`;
break;
case 'italic':
html += `<em>${escapeHtml(text)}</em>`;
break;
case 'strikeThrough':
html += `<s>${escapeHtml(text)}</s>`;
break;
case 'snippet':
html += `<span style="font-family: monospace;">${escapeHtml(text)}</span>`;
break;
case 'secret':
html += `<span class="secret">${escapeHtml(text)}</span>`;
break;
case 'small':
html += `<span class="small-text">${escapeHtml(text)}</span>`;
break;
case 'colored':
html += `<span class="${format.color}">${escapeHtml(text)}</span>`;
break;
case 'uri':
let href = text.startsWith('http://') || text.startsWith('https://') || text.startsWith('simplex:/') ? text : 'https://' + text;
html += `<a href="${href}"${targetBlank(href)}>${escapeHtml(text)}</a>`;
break;
case 'hyperLink': {
const { showText, linkUri } = format;
html += `<a href="${linkUri}"${targetBlank(linkUri)}>${escapeHtml(showText ?? linkUri)}</a>`;
break;
}
case 'simplexLink': {
const { showText, linkType, simplexUri, smpHosts } = format;
const linkText = showText ? escapeHtml(showText) : getSimplexLinkDescr(linkType);
html += `<a href="${platformSimplexUri(simplexUri)}" target="_blank">${linkText} <em>(${viaHost(smpHosts)})</em></a>`;
break;
}
case 'command':
html += `<span style="font-family: monospace;">${escapeHtml(text)}</span>`;
break;
case 'mention':
html += `<strong>${escapeHtml(text)}</strong>`;
break;
case 'email':
html += `<a href="mailto:${text}">${escapeHtml(text)}</a>`;
break;
case 'phone':
html += `<a href="tel:${text}">${escapeHtml(text)}</a>`;
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}`;
}
}
+4
View File
@@ -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