feat: syntax highlighting with theme-matched colors, highlight toggle, layout tweaks

Custom Shiki theme matching site palette (green keywords, yellow strings,
blue functions, purple constants). Toggle button to switch between
highlighted and plain green. Reorganized page: What is it → Quick Start →
What can you do. Tightened copy. Narrower architecture diagram.
This commit is contained in:
swaits committed 2026-04-08 17:15:15 -06:00
1 parent d13ab1a492
commit 5f0f14d12b
2 files changed
+80 -16

No files matched your search

+73 -16
View File
@@ -1,5 +1,43 @@
--- ---
import Base from "../layouts/Base.astro"; import Base from "../layouts/Base.astro";
import { Code } from "astro:components";
const quickStartCode = `import donglora as dl
ser = dl.connect()
dl.send(ser, "SetConfig", config=dl.DEFAULT_CONFIG)
dl.send(ser, "StartRx")
while pkt := dl.recv(ser):
print(f'{pkt["rssi"]:4d}dBm {pkt["snr"]:3d}dB {pkt["payload"].hex()}')`;
// Shiki theme tuned to match the site's green-accent dark palette
const siteTheme = {
name: "donglora",
type: "dark" as const,
colors: {
"editor.background": "#12121a",
"editor.foreground": "#e0e0e8",
},
settings: [
{ scope: ["comment"], settings: { foreground: "#555570", fontStyle: "italic" } },
{ scope: ["keyword", "storage", "keyword.control"], settings: { foreground: "#6ee7b7" } },
{ scope: ["string", "string.quoted"], settings: { foreground: "#fbbf24" } },
{ scope: ["constant.numeric", "constant.language"], settings: { foreground: "#c4b5fd" } },
{ scope: ["entity.name.function", "meta.function-call"], settings: { foreground: "#60a5fa" } },
{ scope: ["support.function", "support.function.builtin"], settings: { foreground: "#60a5fa" } },
{ scope: ["variable", "variable.other"], settings: { foreground: "#e0e0e8" } },
{ scope: ["variable.parameter", "variable.other.readwrite"], settings: { foreground: "#e0e0e8" } },
{ scope: ["keyword.operator", "keyword.operator.assignment", "keyword.operator.comparison"], settings: { foreground: "#6ee7b7" } },
{ scope: ["punctuation", "meta.brace"], settings: { foreground: "#8888a0" } },
{ scope: ["punctuation.definition.string", "punctuation.section"], settings: { foreground: "#fbbf24" } },
{ scope: ["entity.name.import", "entity.name.module"], settings: { foreground: "#34d399" } },
{ scope: ["support.type", "entity.name.type"], settings: { foreground: "#60a5fa" } },
{ scope: ["constant.other", "variable.other.constant"], settings: { foreground: "#c4b5fd" } },
{ scope: ["meta.function-call.arguments", "variable.parameter.function-call"], settings: { foreground: "#e0e0e8" } },
{ scope: ["meta.attribute", "entity.other.attribute-name"], settings: { foreground: "#8888a0" } },
],
};
--- ---
<Base title="DongLoRa — Protocol-agnostic LoRa over USB"> <Base title="DongLoRa — Protocol-agnostic LoRa over USB">
@@ -75,18 +113,37 @@ import Base from "../layouts/Base.astro";
<span class="font-mono text-accent font-bold text-lg shrink-0">3.</span> <span class="font-mono text-accent font-bold text-lg shrink-0">3.</span>
<div> <div>
<p class="font-medium text-text">Listen for packets</p> <p class="font-medium text-text">Listen for packets</p>
<pre <div class="mt-2 rounded border border-border overflow-hidden relative group" id="code-block">
class="font-mono text-sm text-accent bg-bg-card border border-border px-4 py-3 rounded mt-2 overflow-x-auto" <button
set:html={`import donglora as dl id="highlight-toggle"
class="absolute top-2 right-2 text-text-dim hover:text-accent transition-colors opacity-0 group-hover:opacity-100 focus:opacity-100"
ser = dl.connect() title="Toggle syntax highlighting"
dl.send(ser, "SetConfig", config=dl.DEFAULT_CONFIG) aria-label="Toggle syntax highlighting"
dl.send(ser, "StartRx") >
<svg id="toggle-icon-on" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
while pkt := dl.recv(ser): <circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
p = pkt["payload"] </svg>
print(f'{pkt["rssi"]:4d}dBm {pkt["snr"]:3d}dB {p.hex()}')`} <svg id="toggle-icon-off" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="hidden">
/> <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
</button>
<div id="code-highlighted">
<Code code={quickStartCode} lang="python" theme={siteTheme} />
</div>
<pre id="code-plain" class="hidden font-mono text-sm text-accent px-4 py-4" style="background-color: var(--color-bg-card);">{quickStartCode}</pre>
</div>
<script is:inline>
document.getElementById('highlight-toggle').addEventListener('click', () => {
const h = document.getElementById('code-highlighted');
const p = document.getElementById('code-plain');
const iconOn = document.getElementById('toggle-icon-on');
const iconOff = document.getElementById('toggle-icon-off');
h.classList.toggle('hidden');
p.classList.toggle('hidden');
iconOn.classList.toggle('hidden');
iconOff.classList.toggle('hidden');
});
</script>
</div> </div>
</li> </li>
</ol> </ol>
@@ -103,11 +160,11 @@ while pkt := dl.recv(ser):
</p> </p>
<pre <pre
class="font-mono text-sm text-accent bg-bg-card border border-border p-6 rounded overflow-x-auto mb-8" class="font-mono text-sm text-accent bg-bg-card border border-border p-6 rounded overflow-x-auto mb-8"
>your code ──► client library ──► USB ──► firmware ──► LoRa radio >your code ──► client lib ──► USB ──► DongLoRa radio
your code ──► client library ──┐ your code ──► client lib ──┐
your code ──► client library ──┼──► mux ──► USB ──► firmware ──► LoRa radio your code ──► client lib ──┼──► mux ──► USB ──► DongLoRa radio
your code ──► client library ──┘</pre> your code ──► client lib ──┘</pre>
<p class="text-text-muted leading-relaxed mb-6"> <p class="text-text-muted leading-relaxed mb-6">
Because the firmware is protocol-agnostic, a DongLoRa dongle works with any LoRa network Because the firmware is protocol-agnostic, a DongLoRa dongle works with any LoRa network
— Meshtastic, MeshCore, custom protocols, or raw packets. — Meshtastic, MeshCore, custom protocols, or raw packets.
+7
View File
@@ -48,4 +48,11 @@
background: var(--color-border-bright); background: var(--color-border-bright);
border-radius: 3px; border-radius: 3px;
} }
/* Shiki code blocks — match site card background */
.astro-code {
background-color: var(--color-bg-card) !important;
padding: 1rem;
font-size: 0.875rem;
}
} }