diff --git a/src/components/ReadingMap.astro b/src/components/ReadingMap.astro
index 0346c6d..4ea1710 100644
--- a/src/components/ReadingMap.astro
+++ b/src/components/ReadingMap.astro
@@ -57,12 +57,21 @@ const {
try {
const { mount } = await import('../lib/reading-map.js');
for (const el of containers) {
- mount(el, {
+ const map = await mount(el, {
src: el.dataset.src!,
// Fail closed, like the garden's other widgets: a missing payload or a dead GPU
// leaves a plain page rather than an empty bordered box.
onError: (err: unknown) => console.warn('reading map unavailable:', err),
});
+ if (!map) continue;
+
+ // Ring the node the header's quote came from. The two are independent fetches on
+ // every page view and either can land first, so handle both orders: read the hash if
+ // it is already there, and listen in case it is not. `garden:quote` is dispatched by
+ // the header script in Base.astro.
+ const ring = (hash?: string) => hash && map.markQuoted(hash);
+ ring(window.__gardenQuoteHash);
+ addEventListener('garden:quote', (e) => ring((e as CustomEvent).detail?.text_hash));
}
} catch (err) {
/* chunk failed to load: the figure stays hidden */
diff --git a/src/components/ReadingNow.astro b/src/components/ReadingNow.astro
new file mode 100644
index 0000000..58ad106
--- /dev/null
+++ b/src/components/ReadingNow.astro
@@ -0,0 +1,117 @@
+---
+/**
+ * "Currently reading" — the book Wes most recently made progress in.
+ *
+ * import ReadingNow from '../components/ReadingNow.astro';
+ *
+ *
+ * Data: api.c0smere.net/reading/current, which is kobo_archive on phlegethon by way of
+ * api.reading_current(). Date-only by design — the timestamp would publish when he is awake.
+ *
+ * ⚠️ **It says how long ago on purpose.** Six of the ten books on the currently-reading shelf
+ * have not been opened in months, so this widget will sit on one entry indefinitely the moment
+ * the Kobo goes down for a while. Without the relative date that reads as a broken widget
+ * rather than an honest one; past DORMANT_DAYS it also mutes itself and says "paused".
+ *
+ * No cover image: there is no source for one. `kobo.books.isbn` is a sideloader's UUID for most
+ * of the shelf and `kobo.storygraph_links` carries no cover URL. The remaining route is pulling
+ * it out of the epub at intake time, which is a library-rag change, not a garden one.
+ */
+---
+
+
+ Currently reading
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/env.d.ts b/src/env.d.ts
new file mode 100644
index 0000000..ad6b6c8
--- /dev/null
+++ b/src/env.d.ts
@@ -0,0 +1,18 @@
+///
+
+declare global {
+ interface Window {
+ /**
+ * `text_hash` of the reading highlight in the page header, set by Base.astro once
+ * api.c0smere.net/highlights/random answers. The reading map reads it to ring the node
+ * that passage came from.
+ *
+ * A global as well as a `garden:quote` event because the two fetches race: whichever
+ * lands second needs the other's result, and only one of the two mechanisms works in
+ * each order.
+ */
+ __gardenQuoteHash?: string;
+ }
+}
+
+export {};
diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro
index ae6b62b..b24e9b0 100644
--- a/src/layouts/Base.astro
+++ b/src/layouts/Base.astro
@@ -5,6 +5,7 @@ import { buildNavTree } from '../lib/nav.mjs';
import { COMMIT, BUILT_AT } from '../lib/build-info.mjs';
import NavTree from '../components/NavTree.astro';
import Toc from '../components/Toc.astro';
+import ReadingNow from '../components/ReadingNow.astro';
import { loadNotebooks, notebookUrl } from '../lib/notebooks.mjs';
interface Props {
@@ -198,13 +199,13 @@ const pageUrl = new URL(Astro.url.pathname, Astro.site);
- {
- showToc && (
-
- )
- }
+ {/* The rail exists whenever EITHER thing wants it. It used to be rendered only when
+ there was a table of contents, which would have left the reading widget with no home
+ on any page of fewer than two headings — including the homepage. */}
+