diff --git a/src/extensions/outliner/client.mjs b/src/extensions/outliner/client.mjs
index e318094..fb27ae7 100644
--- a/src/extensions/outliner/client.mjs
+++ b/src/extensions/outliner/client.mjs
@@ -11,8 +11,8 @@ function Heading({ indent, ...props }, ...children) {
const { html } = globalThis.__enhancerApi;
return html`
{
`,
});
- let $page;
- const updatePage = () => {
- if (document.contains($page)) return;
- $page = document.querySelector(page);
- updateHeadings();
- };
-
+ let $page, $scroller;
const getHeadings = () => {
return [...$page.querySelectorAll(headings.join(", "))];
},
@@ -87,24 +81,57 @@ export default async (api, db) => {
}
return title;
},
+ getBlockOffset = ($block) => {
+ let offset = 0;
+ while (!$block.matches("[data-content-editable-root]")) {
+ offset += $block.offsetTop;
+ $block = $block.offsetParent;
+ }
+ return offset;
+ },
updateHeadings = debounce(() => {
$toc.innerHTML = "";
if (!$page) return;
const $frag = document.createDocumentFragment();
for (const $heading of getHeadings()) {
- const $h = html`<${Heading}
+ $heading._$outline = html`<${Heading}
indent=${getHeadingLevel($heading)}
onclick=${() => {
- const $scroller = document.querySelector(scroller);
- $scroller.scrollTo({ top: $heading.offsetTop - 24, behavior });
- }}>${getHeadingTitle($heading)}`;
- $frag.append($h);
+ $scroller.scrollTo({
+ top: getBlockOffset($heading) - 24,
+ behavior,
+ });
+ }}
+ >${getHeadingTitle($heading)}
+ />`;
+ $frag.append($heading._$outline);
}
$toc.append($frag);
+ onScroll();
});
+ const $progressMarker = html``,
+ onScroll = () => {
+ const $h = getHeadings().find(($h) => {
+ return $scroller.scrollTop < getBlockOffset($h) - 16;
+ })?._$outline;
+ if ($h) $h.prepend($progressMarker);
+ },
+ setup = () => {
+ if (document.contains($page)) return;
+ $page = document.querySelector(page);
+ console.log($page);
+ $scroller = document.querySelector(scroller);
+ $scroller?.removeEventListener("scroll", onScroll);
+ $scroller?.addEventListener("scroll", onScroll);
+ updateHeadings();
+ };
+
const semanticHeadings = '[class$="header-block"] :is(h2, h3, h4)';
addMutationListener(`${page} ${semanticHeadings}`, updateHeadings);
- addMutationListener(`${page}, ${scroller}`, updatePage, false);
- updatePage();
+ addMutationListener(`${page}, ${scroller}`, setup, false);
+ setup();
};