Testing on notes

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-04-27 23:12:57 +02:00
parent 5472ac3449
commit f00515e4c3
8 changed files with 277 additions and 133 deletions
+110
View File
@@ -0,0 +1,110 @@
---
interface Props {
vars: string[];
}
const { vars } = Astro.props;
---
{
vars.length > 0 && (
<>
<button
id="vars-toggle"
data-note-vars={JSON.stringify(vars)}
class="btn btn-ghost btn-xs font-mono text-base-content/40 hover:text-base-content/70 border border-base-300/50"
onclick="document.getElementById('vars-modal').showModal()"
>
<span class="font-mono text-[10px] leading-none">$</span>
vars
</button>
<dialog id="vars-modal" class="modal">
<div
class="modal-box max-w-sm"
style="background: oklch(10% 0 0); border: 1px solid oklch(71% 0.0863 296.59 / 0.5);"
>
<h3 class="font-mono text-[10px] text-base-content/40 uppercase tracking-widest mb-4">
variables
</h3>
<div class="space-y-2.5">
{vars.map((v) => (
<div class="flex items-center gap-3">
<label
class="font-mono text-xs text-primary/70 w-36 shrink-0 truncate"
title={`$${v}`}
>
${v}
</label>
<input
type="text"
data-var={v}
placeholder={`$${v}`}
class="vars-input input input-sm flex-1 min-w-0 font-mono text-xs bg-base-300/20 border-base-300/60 text-base-content/80 placeholder:text-base-content/25 focus:border-primary/60"
/>
</div>
))}
</div>
<div class="mt-5 flex justify-end">
<button
class="btn btn-ghost btn-xs font-mono text-base-content/40 hover:text-base-content/70 border border-base-300/50"
onclick="document.getElementById('vars-modal').close()"
>
close
</button>
</div>
</div>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>
</>
)
}
<script>
document.addEventListener("astro:page-load", () => {
const btn = document.getElementById("vars-toggle");
if (!btn) return;
const vars: string[] = JSON.parse(btn.dataset.noteVars ?? "[]");
const content = document.querySelector(".note-content");
if (!vars.length || !content) return;
const originals = new Map<Text, string>();
const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT);
let node: Text | null;
while ((node = walker.nextNode() as Text | null)) {
if (/\$[a-zA-Z_][a-zA-Z0-9_]*/.test(node.nodeValue ?? "")) {
originals.set(node, node.nodeValue!);
}
}
function applyVars() {
const values: Record<string, string> = {};
document.querySelectorAll<HTMLInputElement>(".vars-input").forEach((input) => {
values[input.dataset.var!] = input.value.trim();
});
const sorted = [...vars].sort((a, b) => b.length - a.length);
for (const [node, original] of originals) {
let text = original;
for (const name of sorted) {
const val = values[name];
if (val) {
text = text.replace(
new RegExp(`\\$${name}(?![a-zA-Z0-9_])`, "g"),
val,
);
}
}
node.nodeValue = text;
}
}
document.addEventListener("input", (e) => {
if ((e.target as HTMLElement)?.classList.contains("vars-input")) applyVars();
});
});
</script>