Update visible examples with visitor IP

This commit is contained in:
StasonJatham committed 2026-05-21 18:51:18 +02:00
1 parent 8de260dfc7
commit 03ef2d9af6
6 files changed
+67 -2

No files matched your search

+1
View File
@@ -137,6 +137,7 @@ def _page(
{preload_logo_html}
<script src="/theme.js?v=2"></script>
<script src="/clipboard.js?v=3" defer></script>
<script src="/visitor-ip.js?v=1" defer></script>
{extra_scripts_html}
<link href="/bootstrap-subset.css?v=3" rel="stylesheet">
<link href="/app.css?v=13" rel="stylesheet">
+52
View File
@@ -190,3 +190,55 @@ document.querySelectorAll("[data-admin-table]").forEach((tableShell) => {
render();
});
""".strip()
VISITOR_IP_JS = """
(() => {
const ipv4Placeholder = "203.0.113.10";
const ipv6Placeholder = "2001:db8::10";
const needsIpv4 = () => document.body.textContent.includes(ipv4Placeholder) || document.querySelector(`[data-copy*="${ipv4Placeholder}"]`);
const needsIpv6 = () => document.body.textContent.includes(ipv6Placeholder) || document.querySelector(`[data-copy*="${ipv6Placeholder}"]`);
const fetchIp = async (url) => {
try {
const response = await fetch(url, { cache: "no-store", mode: "cors" });
if (!response.ok) return "";
const payload = await response.json();
return typeof payload.ip === "string" ? payload.ip : "";
} catch (_) {
return "";
}
};
const replaceInTextNodes = (search, replacement) => {
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode()) {
if (walker.currentNode.nodeValue.includes(search)) nodes.push(walker.currentNode);
}
nodes.forEach((node) => {
node.nodeValue = node.nodeValue.split(search).join(replacement);
});
};
const replaceInCopyValues = (search, replacement) => {
document.querySelectorAll("[data-copy]").forEach((element) => {
const value = element.dataset.copy || "";
if (value.includes(search)) element.dataset.copy = value.split(search).join(replacement);
});
};
const replaceEverywhere = (search, replacement) => {
if (!replacement || replacement === search) return;
replaceInTextNodes(search, replacement);
replaceInCopyValues(search, replacement);
};
document.addEventListener("DOMContentLoaded", async () => {
const tasks = [];
if (needsIpv4()) tasks.push(fetchIp("https://api4.ipify.org?format=json").then((ip) => replaceEverywhere(ipv4Placeholder, ip)));
if (needsIpv6()) tasks.push(fetchIp("https://api6.ipify.org?format=json").then((ip) => replaceEverywhere(ipv6Placeholder, ip)));
await Promise.allSettled(tasks);
});
})();
""".strip()
+1 -1
View File
@@ -132,7 +132,7 @@ def content_security_policy(path: str) -> str:
"style-src 'self'; "
"img-src 'self' data:; "
"font-src 'self'; "
"connect-src 'self'; "
"connect-src 'self' https://api4.ipify.org https://api6.ipify.org; "
"form-action 'self'; "
"frame-ancestors 'none'"
)