lildocs 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/cli.mjs +59 -4
- package/dist/render/Layout.tsrx +33 -20
- package/dist/render/Search.tsrx +6 -1
- package/dist/render/client.tsrx +2 -0
- package/dist/render/heading-links.ts +40 -5
- package/dist/render/sidebar.ts +63 -1
- package/dist/render/styles.css +204 -22
- package/dist/render/tabler-icons.css +16 -0
- package/dist/render/toc-visibility.ts +78 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,7 +31,11 @@ disk or from any static file host.
|
|
|
31
31
|
## Documentation
|
|
32
32
|
|
|
33
33
|
- [Getting started](https://aleclarson.github.io/lildocs/getting-started.html)
|
|
34
|
-
- [
|
|
34
|
+
- [Writing content](https://aleclarson.github.io/lildocs/features/content.html)
|
|
35
|
+
- [Navigation and page structure](https://aleclarson.github.io/lildocs/features/navigation.html)
|
|
36
|
+
- [Local search](https://aleclarson.github.io/lildocs/features/search.html)
|
|
37
|
+
- [Mermaid diagrams](https://aleclarson.github.io/lildocs/features/mermaid.html)
|
|
38
|
+
- [Generated API reference](https://aleclarson.github.io/lildocs/features/api-reference.html)
|
|
35
39
|
- [GitHub Pages deployment](https://aleclarson.github.io/lildocs/guides/github-pages.html)
|
|
36
40
|
- [CLI reference](https://aleclarson.github.io/lildocs/reference/cli.html)
|
|
37
41
|
- [Configuration reference](https://aleclarson.github.io/lildocs/reference/configuration.html)
|
package/dist/cli.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { command, flag, option, optional, positional, run, string, subcommands } from "cmd-ts";
|
|
6
6
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
-
import { access, copyFile, mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
7
|
+
import { access, appendFile, copyFile, mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import matter from "gray-matter";
|
|
10
10
|
import { Lexer, Marked, Parser, Renderer, marked } from "marked";
|
|
@@ -516,7 +516,10 @@ async function frontendViteConfig(cwd, mode) {
|
|
|
516
516
|
clearScreen: false,
|
|
517
517
|
logLevel: "warn",
|
|
518
518
|
plugins: [octaneRuntimeCompatibility(), octane()],
|
|
519
|
-
optimizeDeps: {
|
|
519
|
+
optimizeDeps: {
|
|
520
|
+
exclude: ["octane"],
|
|
521
|
+
...mode === "dev" ? { noDiscovery: true } : {}
|
|
522
|
+
},
|
|
520
523
|
ssr: { noExternal: [/^octane(?:$|\/)/] }
|
|
521
524
|
};
|
|
522
525
|
}
|
|
@@ -1711,7 +1714,8 @@ async function buildSite(options) {
|
|
|
1711
1714
|
favicon: configOptions.favicon
|
|
1712
1715
|
});
|
|
1713
1716
|
const mermaid = await createMermaidRenderer({ themeConfig: themeToMermaidConfig(theme, fontResolution.themeFonts) });
|
|
1714
|
-
const
|
|
1717
|
+
const configuredCss = `${resolveThemeFontImports(theme, configOptions.fonts)}${fontResolution.css}${themeToCssVariables(theme, fontResolution.themeFonts, configOptions.link, configOptions.navigation)}\n${mermaid.css}${backgroundResolution.css}${logoResolution.css}`;
|
|
1718
|
+
const css = `${configuredCss}${baseCss}`;
|
|
1715
1719
|
const assets = [
|
|
1716
1720
|
...fontResolution.assets,
|
|
1717
1721
|
...backgroundResolution.assets,
|
|
@@ -1758,7 +1762,7 @@ async function buildSite(options) {
|
|
|
1758
1762
|
page,
|
|
1759
1763
|
nav,
|
|
1760
1764
|
pageNavigation: pageNavigation.get(page.route),
|
|
1761
|
-
css,
|
|
1765
|
+
css: configuredCss,
|
|
1762
1766
|
searchIndexJson,
|
|
1763
1767
|
logo: logoResolution.logo,
|
|
1764
1768
|
favicon: logoResolution.favicon,
|
|
@@ -1854,6 +1858,7 @@ async function startDevServer(options) {
|
|
|
1854
1858
|
const input = await resolveInput(options.input, options.cwd, { homePagePreference: "readme-first" });
|
|
1855
1859
|
const outDir = path.resolve(options.cwd, options.outDir);
|
|
1856
1860
|
validateDevOutDir(options.cwd, input.docsRoot, outDir, options.outDir);
|
|
1861
|
+
await addGitExclude(options.cwd, outDir);
|
|
1857
1862
|
await mkdir(outDir, { recursive: true });
|
|
1858
1863
|
const vite = await createFrontendDevServer({
|
|
1859
1864
|
cwd: options.cwd,
|
|
@@ -1948,6 +1953,56 @@ function isInside(parent, child) {
|
|
|
1948
1953
|
const relative = path.relative(parent, child);
|
|
1949
1954
|
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
1950
1955
|
}
|
|
1956
|
+
async function addGitExclude(cwd, outDir) {
|
|
1957
|
+
try {
|
|
1958
|
+
const repository = await findGitRepository(cwd);
|
|
1959
|
+
if (!repository || !isInside(repository.root, outDir)) return;
|
|
1960
|
+
const relativeOutDir = path.relative(repository.root, outDir);
|
|
1961
|
+
if (!relativeOutDir) return;
|
|
1962
|
+
const pattern = `${relativeOutDir.split(path.sep).join("/")}/`;
|
|
1963
|
+
let contents = "";
|
|
1964
|
+
try {
|
|
1965
|
+
contents = await readFile(repository.excludePath, "utf8");
|
|
1966
|
+
} catch (error) {
|
|
1967
|
+
if (error.code !== "ENOENT") throw error;
|
|
1968
|
+
await mkdir(path.dirname(repository.excludePath), { recursive: true });
|
|
1969
|
+
}
|
|
1970
|
+
const entries = contents.split(/\r?\n/).map((entry) => entry.trim());
|
|
1971
|
+
const normalizedPattern = pattern.replace(/^\/|\/$/g, "");
|
|
1972
|
+
if (entries.some((entry) => entry.replace(/^\/|\/$/g, "") === normalizedPattern)) return;
|
|
1973
|
+
const separator = contents.length > 0 && !contents.endsWith("\n") ? "\n" : "";
|
|
1974
|
+
await appendFile(repository.excludePath, `${separator}${pattern}\n`);
|
|
1975
|
+
} catch {}
|
|
1976
|
+
}
|
|
1977
|
+
async function findGitRepository(start) {
|
|
1978
|
+
let current = path.resolve(start);
|
|
1979
|
+
while (true) {
|
|
1980
|
+
const dotGit = path.join(current, ".git");
|
|
1981
|
+
try {
|
|
1982
|
+
const metadata = await stat(dotGit);
|
|
1983
|
+
let gitDir = dotGit;
|
|
1984
|
+
if (!metadata.isDirectory()) {
|
|
1985
|
+
const pointer = await readFile(dotGit, "utf8");
|
|
1986
|
+
const match = /^gitdir:\s*(.+)\s*$/im.exec(pointer);
|
|
1987
|
+
if (!match?.[1]) return;
|
|
1988
|
+
gitDir = path.resolve(current, match[1]);
|
|
1989
|
+
}
|
|
1990
|
+
let commonDir = gitDir;
|
|
1991
|
+
try {
|
|
1992
|
+
const pointer = (await readFile(path.join(gitDir, "commondir"), "utf8")).trim();
|
|
1993
|
+
commonDir = path.resolve(gitDir, pointer);
|
|
1994
|
+
} catch {}
|
|
1995
|
+
return {
|
|
1996
|
+
root: current,
|
|
1997
|
+
excludePath: path.join(commonDir, "info", "exclude")
|
|
1998
|
+
};
|
|
1999
|
+
} catch {
|
|
2000
|
+
const parent = path.dirname(current);
|
|
2001
|
+
if (parent === current) return;
|
|
2002
|
+
current = parent;
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
1951
2006
|
//#endregion
|
|
1952
2007
|
//#region src/core/deploy.ts
|
|
1953
2008
|
async function deployGitHubPages(options) {
|
package/dist/render/Layout.tsrx
CHANGED
|
@@ -34,7 +34,6 @@ export function Layout({
|
|
|
34
34
|
clientStylePaths,
|
|
35
35
|
}: LayoutProps) @{
|
|
36
36
|
const transition = navigation?.transition ?? "fade";
|
|
37
|
-
const repoIconUrl = rootRelativeUrl(page.route, "assets/github-icon.svg");
|
|
38
37
|
const issueUrl = issueUrlForRepository(repositoryUrl);
|
|
39
38
|
const repositoryLabel = repositoryLabelForUrl(repositoryUrl);
|
|
40
39
|
|
|
@@ -82,11 +81,13 @@ export function Layout({
|
|
|
82
81
|
type="button"
|
|
83
82
|
aria-label="Collapse sidebar"
|
|
84
83
|
aria-controls="lildocs-sidebar"
|
|
84
|
+
aria-expanded="false"
|
|
85
85
|
>
|
|
86
86
|
<span
|
|
87
|
-
class="ti ti-layout-sidebar-left-collapse"
|
|
87
|
+
class="sidebarCollapseIcon ti ti-layout-sidebar-left-collapse"
|
|
88
88
|
aria-hidden="true"
|
|
89
89
|
/>
|
|
90
|
+
<span class="sidebarMenuIcon ti ti-menu-2" aria-hidden="true" />
|
|
90
91
|
</button>
|
|
91
92
|
</div>
|
|
92
93
|
<div id="lildocs-search-root" class="searchBox">
|
|
@@ -108,6 +109,18 @@ export function Layout({
|
|
|
108
109
|
pageRoute={page.route}
|
|
109
110
|
/>
|
|
110
111
|
</nav>
|
|
112
|
+
@if (repositoryUrl && repositoryLabel) {
|
|
113
|
+
<a
|
|
114
|
+
class="sidebarRepoLink"
|
|
115
|
+
href={repositoryUrl}
|
|
116
|
+
aria-label="View repository on GitHub"
|
|
117
|
+
>
|
|
118
|
+
<span class="repoIcon" aria-hidden="true" />
|
|
119
|
+
<span>
|
|
120
|
+
{repositoryLabel as string}
|
|
121
|
+
</span>
|
|
122
|
+
</a>
|
|
123
|
+
}
|
|
111
124
|
</div>
|
|
112
125
|
</aside>
|
|
113
126
|
<div class="sidebarFloatingControls">
|
|
@@ -142,7 +155,6 @@ export function Layout({
|
|
|
142
155
|
headings={page.headings}
|
|
143
156
|
repositoryUrl={repositoryUrl}
|
|
144
157
|
repositoryLabel={repositoryLabel}
|
|
145
|
-
repoIconUrl={repoIconUrl}
|
|
146
158
|
/>
|
|
147
159
|
</aside>
|
|
148
160
|
</div>
|
|
@@ -313,12 +325,10 @@ function Toc({
|
|
|
313
325
|
headings,
|
|
314
326
|
repositoryUrl,
|
|
315
327
|
repositoryLabel,
|
|
316
|
-
repoIconUrl,
|
|
317
328
|
}: {
|
|
318
329
|
headings: Heading[];
|
|
319
330
|
repositoryUrl?: string;
|
|
320
331
|
repositoryLabel?: string;
|
|
321
|
-
repoIconUrl: string;
|
|
322
332
|
}) @{
|
|
323
333
|
const tocHeadings = headings.filter(
|
|
324
334
|
(heading) => heading.depth > 1 && heading.depth < 4,
|
|
@@ -330,16 +340,23 @@ function Toc({
|
|
|
330
340
|
<nav aria-label="Table of contents">
|
|
331
341
|
@if (tocHeadings.length > 0) {
|
|
332
342
|
<>
|
|
333
|
-
<p
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
+
<p class="tocTitle">
|
|
344
|
+
<span class="ti ti-align-left" aria-hidden="true" />
|
|
345
|
+
On this page
|
|
346
|
+
</p>
|
|
347
|
+
<div class="tocLinks" data-toc-links>
|
|
348
|
+
<span class="tocRail" aria-hidden="true" />
|
|
349
|
+
<span class="tocVisibility" data-toc-visibility aria-hidden="true" />
|
|
350
|
+
<ul>
|
|
351
|
+
@for (const heading of tocHeadings; key heading.id) {
|
|
352
|
+
<li class={`tocDepth${heading.depth}`}>
|
|
353
|
+
<a href={`#${heading.id}`}>
|
|
354
|
+
{heading.text as string}
|
|
355
|
+
</a>
|
|
356
|
+
</li>
|
|
357
|
+
}
|
|
358
|
+
</ul>
|
|
359
|
+
</div>
|
|
343
360
|
</>
|
|
344
361
|
}
|
|
345
362
|
@if (repositoryUrl && repositoryLabel) {
|
|
@@ -348,11 +365,7 @@ function Toc({
|
|
|
348
365
|
href={repositoryUrl}
|
|
349
366
|
aria-label="View repository on GitHub"
|
|
350
367
|
>
|
|
351
|
-
<span
|
|
352
|
-
class="repoIcon"
|
|
353
|
-
aria-hidden="true"
|
|
354
|
-
style={`--ld-repo-icon: url(${repoIconUrl})`}
|
|
355
|
-
/>
|
|
368
|
+
<span class="repoIcon" aria-hidden="true" />
|
|
356
369
|
<span>
|
|
357
370
|
{repositoryLabel as string}
|
|
358
371
|
</span>
|
package/dist/render/Search.tsrx
CHANGED
|
@@ -73,11 +73,16 @@ export function SearchBox({
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
document.documentElement.classList.remove("sidebar-collapsed");
|
|
76
|
+
document.dispatchEvent(new CustomEvent("lildocs:sidebar-menu-open"));
|
|
76
77
|
inputRef.current?.focus();
|
|
77
78
|
setOpen(Boolean(query.trim()));
|
|
78
79
|
};
|
|
79
80
|
const handleShortcut = (event: KeyboardEvent) => {
|
|
80
|
-
|
|
81
|
+
const key = event.key.toLowerCase();
|
|
82
|
+
const hasCommandModifier = event.metaKey || event.ctrlKey;
|
|
83
|
+
if (
|
|
84
|
+
hasCommandModifier && (key === "k" || event.shiftKey && key === "f")
|
|
85
|
+
) {
|
|
81
86
|
event.preventDefault();
|
|
82
87
|
toggleSearch();
|
|
83
88
|
}
|
package/dist/render/client.tsrx
CHANGED
|
@@ -6,6 +6,7 @@ import { preloadRelativeUrl, SearchBox } from "./Search.tsrx";
|
|
|
6
6
|
import { initSectionHighlights } from "./section-highlight.js";
|
|
7
7
|
import { initSidebar } from "./sidebar.js";
|
|
8
8
|
import { initTableViewer } from "./table-viewer.js";
|
|
9
|
+
import { initTocVisibility } from "./toc-visibility.js";
|
|
9
10
|
import type { SearchEntry } from "./Search.tsrx";
|
|
10
11
|
|
|
11
12
|
initCopyCode();
|
|
@@ -14,6 +15,7 @@ initNavigation();
|
|
|
14
15
|
initSectionHighlights();
|
|
15
16
|
initSidebar();
|
|
16
17
|
initTableViewer();
|
|
18
|
+
initTocVisibility();
|
|
17
19
|
|
|
18
20
|
void mountSearch();
|
|
19
21
|
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
const headingSelector =
|
|
2
2
|
".content article h1[id], .content article h2[id], .content article h3[id], .content article h4[id], .content article h5[id], .content article h6[id]";
|
|
3
|
+
const headingLinkIcons = {
|
|
4
|
+
link: '<span class="ti ti-link" aria-hidden="true"></span>',
|
|
5
|
+
check: '<span class="ti ti-check" aria-hidden="true"></span>',
|
|
6
|
+
};
|
|
3
7
|
|
|
4
8
|
export function initHeadingLinks() {
|
|
9
|
+
enhanceHeadingLinks();
|
|
10
|
+
document.addEventListener("lildocs:page-view", enhanceHeadingLinks);
|
|
5
11
|
document.addEventListener("click", (event) => {
|
|
6
12
|
if (!(event.target instanceof Element) || event.target.closest("a")) {
|
|
7
13
|
return;
|
|
@@ -16,17 +22,46 @@ export function initHeadingLinks() {
|
|
|
16
22
|
});
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
function enhanceHeadingLinks() {
|
|
26
|
+
const headings =
|
|
27
|
+
document.querySelectorAll<HTMLHeadingElement>(headingSelector);
|
|
28
|
+
|
|
29
|
+
for (const heading of Array.from(headings)) {
|
|
30
|
+
if (heading.querySelector(".headingLinkIcon")) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const icon = document.createElement("button");
|
|
35
|
+
icon.type = "button";
|
|
36
|
+
icon.className = "headingLinkIcon";
|
|
37
|
+
icon.setAttribute("aria-label", "Copy link to heading");
|
|
38
|
+
icon.title = "Copy link to heading";
|
|
39
|
+
icon.innerHTML = headingLinkIcons.link;
|
|
40
|
+
heading.append(icon);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
19
44
|
async function copyHeadingLink(heading: HTMLHeadingElement) {
|
|
20
45
|
const url = new URL(window.location.href);
|
|
21
46
|
url.hash = heading.tagName === "H1" ? "" : heading.id;
|
|
22
47
|
|
|
23
48
|
try {
|
|
24
49
|
await writeClipboard(url.href);
|
|
25
|
-
heading.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
const icon = heading.querySelector<HTMLButtonElement>(".headingLinkIcon");
|
|
51
|
+
if (!icon) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
icon.classList.add("headingLinkCopied");
|
|
56
|
+
icon.innerHTML = headingLinkIcons.check;
|
|
57
|
+
icon.setAttribute("aria-label", "Copied");
|
|
58
|
+
icon.title = "Copied";
|
|
59
|
+
window.setTimeout(() => {
|
|
60
|
+
icon.classList.remove("headingLinkCopied");
|
|
61
|
+
icon.innerHTML = headingLinkIcons.link;
|
|
62
|
+
icon.setAttribute("aria-label", "Copy link to heading");
|
|
63
|
+
icon.title = "Copy link to heading";
|
|
64
|
+
}, 1600);
|
|
30
65
|
} catch {}
|
|
31
66
|
}
|
|
32
67
|
|
package/dist/render/sidebar.ts
CHANGED
|
@@ -14,6 +14,17 @@ export function initSidebar() {
|
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const mobileQuery = window.matchMedia("(max-width: 860px)");
|
|
18
|
+
|
|
19
|
+
const setMenuOpen = (open: boolean) => {
|
|
20
|
+
document.documentElement.classList.toggle("sidebar-menu-open", open);
|
|
21
|
+
collapseButton.setAttribute("aria-expanded", String(open));
|
|
22
|
+
collapseButton.setAttribute(
|
|
23
|
+
"aria-label",
|
|
24
|
+
open ? "Close navigation menu" : "Open navigation menu",
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
17
28
|
const setCollapsed = (collapsed: boolean) => {
|
|
18
29
|
document.documentElement.classList.toggle("sidebar-collapsed", collapsed);
|
|
19
30
|
collapseButton.setAttribute(
|
|
@@ -22,10 +33,61 @@ export function initSidebar() {
|
|
|
22
33
|
);
|
|
23
34
|
};
|
|
24
35
|
|
|
25
|
-
|
|
36
|
+
const syncResponsiveState = () => {
|
|
37
|
+
document.documentElement.classList.remove("sidebar-menu-open");
|
|
38
|
+
collapseButton.setAttribute("aria-expanded", "false");
|
|
39
|
+
collapseButton.setAttribute(
|
|
40
|
+
"aria-label",
|
|
41
|
+
mobileQuery.matches ? "Open navigation menu" : "Collapse sidebar",
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
collapseButton.addEventListener("click", () => {
|
|
46
|
+
if (mobileQuery.matches) {
|
|
47
|
+
setMenuOpen(
|
|
48
|
+
!document.documentElement.classList.contains("sidebar-menu-open"),
|
|
49
|
+
);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
setCollapsed(true);
|
|
53
|
+
});
|
|
26
54
|
expandButton.addEventListener("click", () => setCollapsed(false));
|
|
55
|
+
document.addEventListener("keydown", (event) => {
|
|
56
|
+
if (event.key === "Escape" && mobileQuery.matches) {
|
|
57
|
+
setMenuOpen(false);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "b") {
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
if (mobileQuery.matches) {
|
|
63
|
+
setMenuOpen(
|
|
64
|
+
!document.documentElement.classList.contains("sidebar-menu-open"),
|
|
65
|
+
);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
setCollapsed(
|
|
69
|
+
!document.documentElement.classList.contains("sidebar-collapsed"),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
sidebar.addEventListener("click", (event) => {
|
|
74
|
+
if (
|
|
75
|
+
mobileQuery.matches &&
|
|
76
|
+
event.target instanceof Element &&
|
|
77
|
+
event.target.closest("a[href]")
|
|
78
|
+
) {
|
|
79
|
+
setMenuOpen(false);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
27
82
|
searchButton.addEventListener("click", () => {
|
|
28
83
|
setCollapsed(false);
|
|
29
84
|
document.dispatchEvent(new CustomEvent("lildocs:search-toggle"));
|
|
30
85
|
});
|
|
86
|
+
document.addEventListener("lildocs:sidebar-menu-open", () => {
|
|
87
|
+
if (mobileQuery.matches) {
|
|
88
|
+
setMenuOpen(true);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
mobileQuery.addEventListener("change", syncResponsiveState);
|
|
92
|
+
syncResponsiveState();
|
|
31
93
|
}
|
package/dist/render/styles.css
CHANGED
|
@@ -129,6 +129,14 @@ body {
|
|
|
129
129
|
outline-offset: 2px;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
.sidebarMenuIcon {
|
|
133
|
+
display: none;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.sidebarRepoLink {
|
|
137
|
+
display: none;
|
|
138
|
+
}
|
|
139
|
+
|
|
132
140
|
.sidebarFloatingControls {
|
|
133
141
|
position: fixed;
|
|
134
142
|
top: 24px;
|
|
@@ -202,6 +210,7 @@ html.is-animating .transition-scale {
|
|
|
202
210
|
.content h5,
|
|
203
211
|
.content h6 {
|
|
204
212
|
font-family: var(--ld-font-heading);
|
|
213
|
+
line-height: 1.2;
|
|
205
214
|
}
|
|
206
215
|
|
|
207
216
|
.content article :where(h1, h2, h3, h4, h5, h6) {
|
|
@@ -210,19 +219,46 @@ html.is-animating .transition-scale {
|
|
|
210
219
|
}
|
|
211
220
|
|
|
212
221
|
.content article :where(h1, h2, h3, h4, h5, h6)[id] {
|
|
213
|
-
cursor:
|
|
222
|
+
cursor: pointer;
|
|
214
223
|
}
|
|
215
224
|
|
|
216
|
-
.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
225
|
+
.headingLinkIcon {
|
|
226
|
+
appearance: none;
|
|
227
|
+
margin-left: 0.35em;
|
|
228
|
+
border: 0;
|
|
229
|
+
padding: 0;
|
|
230
|
+
background: transparent;
|
|
231
|
+
color: currentColor;
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
font-size: 0.7em;
|
|
234
|
+
line-height: 1;
|
|
235
|
+
opacity: 0;
|
|
236
|
+
transition: opacity 150ms ease;
|
|
223
237
|
vertical-align: middle;
|
|
224
238
|
}
|
|
225
239
|
|
|
240
|
+
.content
|
|
241
|
+
article
|
|
242
|
+
:where(h1, h2, h3, h4, h5, h6)[id]:is(:hover, :focus-within)
|
|
243
|
+
.headingLinkIcon {
|
|
244
|
+
opacity: 0.55;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.content
|
|
248
|
+
article
|
|
249
|
+
:where(h1, h2, h3, h4, h5, h6)[id]
|
|
250
|
+
.headingLinkIcon:is(:hover, :focus-visible) {
|
|
251
|
+
opacity: 1;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.content
|
|
255
|
+
article
|
|
256
|
+
:where(h1, h2, h3, h4, h5, h6)[id]
|
|
257
|
+
.headingLinkIcon.headingLinkCopied {
|
|
258
|
+
color: var(--ld-color-accent);
|
|
259
|
+
opacity: 1;
|
|
260
|
+
}
|
|
261
|
+
|
|
226
262
|
.content article :where(h2, h3).sectionHighlight {
|
|
227
263
|
animation: section-highlight 2.4s ease-out;
|
|
228
264
|
border-radius: 6px;
|
|
@@ -248,6 +284,7 @@ html.is-animating .transition-scale {
|
|
|
248
284
|
|
|
249
285
|
.content article p {
|
|
250
286
|
margin-block: 1.25em;
|
|
287
|
+
line-height: 1.9;
|
|
251
288
|
}
|
|
252
289
|
|
|
253
290
|
.content img {
|
|
@@ -261,7 +298,7 @@ html.is-animating .transition-scale {
|
|
|
261
298
|
}
|
|
262
299
|
|
|
263
300
|
.groupBreadcrumbs {
|
|
264
|
-
margin-block-end:
|
|
301
|
+
margin-block-end: 0px !important;
|
|
265
302
|
color: var(--ld-color-accent);
|
|
266
303
|
font-size: 80%;
|
|
267
304
|
font-weight: 700;
|
|
@@ -269,6 +306,7 @@ html.is-animating .transition-scale {
|
|
|
269
306
|
|
|
270
307
|
.content article li {
|
|
271
308
|
margin-block: 1em;
|
|
309
|
+
line-height: 1.9;
|
|
272
310
|
}
|
|
273
311
|
|
|
274
312
|
.content article > div > ul {
|
|
@@ -294,7 +332,7 @@ html.is-animating .transition-scale {
|
|
|
294
332
|
|
|
295
333
|
.content article h1 + blockquote {
|
|
296
334
|
margin: 0 0 1.5em;
|
|
297
|
-
margin-top: -
|
|
335
|
+
margin-top: -0.6rem;
|
|
298
336
|
padding: 0;
|
|
299
337
|
border-left: 0;
|
|
300
338
|
border-radius: 0;
|
|
@@ -308,6 +346,10 @@ html.is-animating .transition-scale {
|
|
|
308
346
|
line-height: 1.45;
|
|
309
347
|
}
|
|
310
348
|
|
|
349
|
+
.content article h1 + blockquote > p {
|
|
350
|
+
line-height: 1.6;
|
|
351
|
+
}
|
|
352
|
+
|
|
311
353
|
.content blockquote > :first-child {
|
|
312
354
|
margin-top: 0;
|
|
313
355
|
}
|
|
@@ -365,13 +407,24 @@ html.is-animating .transition-scale {
|
|
|
365
407
|
|
|
366
408
|
.navList a,
|
|
367
409
|
.navDisclosure summary {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
color-mix(in srgb, var(--ld-color-border) 65%, transparent);
|
|
410
|
+
position: relative;
|
|
411
|
+
padding-left: 9px;
|
|
371
412
|
color: var(--ld-color-muted-text);
|
|
372
413
|
text-decoration: none;
|
|
373
414
|
}
|
|
374
415
|
|
|
416
|
+
.navList a::before,
|
|
417
|
+
.navDisclosure summary::before {
|
|
418
|
+
position: absolute;
|
|
419
|
+
top: -1px;
|
|
420
|
+
bottom: -1px;
|
|
421
|
+
left: 0;
|
|
422
|
+
width: 2px;
|
|
423
|
+
border-radius: 1px;
|
|
424
|
+
background: color-mix(in srgb, var(--ld-color-border) 65%, transparent);
|
|
425
|
+
content: "";
|
|
426
|
+
}
|
|
427
|
+
|
|
375
428
|
.navDisclosure summary {
|
|
376
429
|
display: flex;
|
|
377
430
|
align-items: center;
|
|
@@ -410,11 +463,15 @@ html.is-animating .transition-scale {
|
|
|
410
463
|
|
|
411
464
|
.navList a.active,
|
|
412
465
|
.navDisclosure summary.active {
|
|
413
|
-
border-left-color: var(--ld-color-accent);
|
|
414
466
|
color: var(--ld-color-accent);
|
|
415
467
|
font-weight: 550;
|
|
416
468
|
}
|
|
417
469
|
|
|
470
|
+
.navList a.active::before,
|
|
471
|
+
.navDisclosure summary.active::before {
|
|
472
|
+
background: var(--ld-color-accent);
|
|
473
|
+
}
|
|
474
|
+
|
|
418
475
|
.content pre {
|
|
419
476
|
position: relative;
|
|
420
477
|
overflow: auto;
|
|
@@ -741,11 +798,55 @@ html.mermaidFullscreenOpen {
|
|
|
741
798
|
font-weight: 700;
|
|
742
799
|
}
|
|
743
800
|
|
|
744
|
-
.
|
|
801
|
+
.tocTitle {
|
|
802
|
+
display: flex;
|
|
803
|
+
align-items: center;
|
|
804
|
+
gap: 7px;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.tocLinks {
|
|
808
|
+
position: relative;
|
|
809
|
+
margin-block: 1em;
|
|
810
|
+
margin-left: 5px;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
.tocLinks ul {
|
|
745
814
|
display: grid;
|
|
746
815
|
gap: 9px;
|
|
816
|
+
margin: 0;
|
|
747
817
|
list-style: none;
|
|
748
|
-
padding-left:
|
|
818
|
+
padding-left: 16px;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.tocRail,
|
|
822
|
+
.tocVisibility {
|
|
823
|
+
position: absolute;
|
|
824
|
+
top: 0;
|
|
825
|
+
left: 0;
|
|
826
|
+
width: 2px;
|
|
827
|
+
border-radius: 999px;
|
|
828
|
+
pointer-events: none;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.tocRail {
|
|
832
|
+
bottom: 0;
|
|
833
|
+
background: var(--ld-color-border);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.tocVisibility {
|
|
837
|
+
top: var(--ld-toc-visibility-top, 0);
|
|
838
|
+
z-index: 1;
|
|
839
|
+
height: var(--ld-toc-visibility-height, 0);
|
|
840
|
+
background: var(--ld-color-accent);
|
|
841
|
+
opacity: 0;
|
|
842
|
+
transition:
|
|
843
|
+
top 180ms var(--ld-navigation-easing),
|
|
844
|
+
height 180ms var(--ld-navigation-easing),
|
|
845
|
+
opacity 120ms ease;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.tocVisibility.isVisible {
|
|
849
|
+
opacity: 1;
|
|
749
850
|
}
|
|
750
851
|
|
|
751
852
|
.toc a {
|
|
@@ -762,8 +863,8 @@ html.mermaidFullscreenOpen {
|
|
|
762
863
|
width: 20px;
|
|
763
864
|
height: 20px;
|
|
764
865
|
background: currentColor;
|
|
765
|
-
mask:
|
|
766
|
-
-webkit-mask:
|
|
866
|
+
mask: url("./github-icon.svg") center / contain no-repeat;
|
|
867
|
+
-webkit-mask: url("./github-icon.svg") center / contain no-repeat;
|
|
767
868
|
}
|
|
768
869
|
|
|
769
870
|
.searchBox {
|
|
@@ -980,19 +1081,102 @@ html.mermaidFullscreenOpen {
|
|
|
980
1081
|
}
|
|
981
1082
|
}
|
|
982
1083
|
|
|
1084
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1085
|
+
.tocVisibility {
|
|
1086
|
+
transition: none;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
983
1090
|
@media (max-width: 860px) {
|
|
1091
|
+
html.sidebar-menu-open,
|
|
1092
|
+
html.sidebar-menu-open body {
|
|
1093
|
+
overflow: hidden;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
984
1096
|
.pageShell {
|
|
985
1097
|
display: block;
|
|
986
1098
|
}
|
|
987
1099
|
|
|
1100
|
+
.content {
|
|
1101
|
+
padding-block-start: 25px;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
988
1104
|
.sidebar {
|
|
989
|
-
position:
|
|
1105
|
+
position: sticky;
|
|
1106
|
+
top: 0;
|
|
1107
|
+
z-index: 30;
|
|
990
1108
|
height: auto;
|
|
991
1109
|
max-height: none;
|
|
1110
|
+
overflow: visible;
|
|
1111
|
+
padding: 0;
|
|
992
1112
|
border-bottom: 1px solid var(--ld-color-border);
|
|
993
1113
|
border-right: 0;
|
|
994
1114
|
}
|
|
995
1115
|
|
|
1116
|
+
.sidebarContents {
|
|
1117
|
+
display: block;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
.sidebarHeader {
|
|
1121
|
+
min-height: 76px;
|
|
1122
|
+
padding: 20px;
|
|
1123
|
+
background: var(--ld-color-sidebar-background);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
.sidebarCollapseIcon {
|
|
1127
|
+
display: none;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
.sidebarMenuIcon {
|
|
1131
|
+
display: block;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
.sidebarContents > .searchBox,
|
|
1135
|
+
#lildocs-sidebar-navigation {
|
|
1136
|
+
display: none;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
html.sidebar-menu-open .sidebar {
|
|
1140
|
+
position: fixed;
|
|
1141
|
+
inset: 0;
|
|
1142
|
+
width: 100%;
|
|
1143
|
+
height: 100dvh;
|
|
1144
|
+
max-height: 100dvh;
|
|
1145
|
+
overflow: auto;
|
|
1146
|
+
overscroll-behavior: contain;
|
|
1147
|
+
border-bottom: 0;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
html.sidebar-menu-open .sidebarHeader {
|
|
1151
|
+
position: sticky;
|
|
1152
|
+
top: 0;
|
|
1153
|
+
z-index: 1;
|
|
1154
|
+
border-bottom: 1px solid var(--ld-color-border);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
html.sidebar-menu-open .sidebarContents > .searchBox {
|
|
1158
|
+
display: block;
|
|
1159
|
+
margin: 20px;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
html.sidebar-menu-open #lildocs-sidebar-navigation {
|
|
1163
|
+
display: block;
|
|
1164
|
+
padding: 0 20px 32px;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
html.sidebar-menu-open .sidebarRepoLink {
|
|
1168
|
+
display: flex;
|
|
1169
|
+
align-items: center;
|
|
1170
|
+
gap: 7px;
|
|
1171
|
+
margin: 0 20px 32px;
|
|
1172
|
+
padding-top: 16px;
|
|
1173
|
+
border-top: 1px solid var(--ld-color-border);
|
|
1174
|
+
color: var(--ld-color-text);
|
|
1175
|
+
font-size: 0.8rem;
|
|
1176
|
+
font-weight: 600;
|
|
1177
|
+
text-decoration: none;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
996
1180
|
.searchResults {
|
|
997
1181
|
position: absolute;
|
|
998
1182
|
top: calc(100% + 8px);
|
|
@@ -1009,8 +1193,6 @@ html.mermaidFullscreenOpen {
|
|
|
1009
1193
|
}
|
|
1010
1194
|
|
|
1011
1195
|
.toc {
|
|
1012
|
-
|
|
1013
|
-
max-height: none;
|
|
1014
|
-
border-bottom: 1px solid var(--ld-color-border);
|
|
1196
|
+
display: none;
|
|
1015
1197
|
}
|
|
1016
1198
|
}
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%3E%3Cpath%20stroke%3D%22none%22%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%20%2F%3E%3Cpath%20d%3D%22M3%2010a7%207%200%201%200%2014%200a7%207%200%201%200%20-14%200%22%20%2F%3E%3Cpath%20d%3D%22M21%2021l-6%20-6%22%20%2F%3E%3C%2Fsvg%3E");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
.ti-link {
|
|
21
|
+
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%2015l6%20-6%22%2F%3E%3Cpath%20d%3D%22M11%206l.463%20-.536a5%205%200%200%201%207.071%207.072l-.534%20.464%22%2F%3E%3Cpath%20d%3D%22M13%2018l-.397%20.534a5.068%205.068%200%200%201%20-7.127%200a4.972%204.972%200%200%201%200%20-7.071l.524%20-.463%22%2F%3E%3C%2Fsvg%3E");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ti-check {
|
|
25
|
+
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%2012l5%205l10%20-10%22%2F%3E%3C%2Fsvg%3E");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.ti-align-left {
|
|
29
|
+
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%206l16%200%22%2F%3E%3Cpath%20d%3D%22M4%2012l10%200%22%2F%3E%3Cpath%20d%3D%22M4%2018l14%200%22%2F%3E%3C%2Fsvg%3E");
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
.ti-arrows-maximize {
|
|
21
33
|
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M16%204l4%200l0%204%22%2F%3E%3Cpath%20d%3D%22M14%2010l6%20-6%22%2F%3E%3Cpath%20d%3D%22M8%2020l-4%200l0%20-4%22%2F%3E%3Cpath%20d%3D%22M4%2020l6%20-6%22%2F%3E%3Cpath%20d%3D%22M16%2020l4%200l0%20-4%22%2F%3E%3Cpath%20d%3D%22M14%2014l6%206%22%2F%3E%3Cpath%20d%3D%22M8%204l-4%200l0%204%22%2F%3E%3Cpath%20d%3D%22M4%204l6%206%22%2F%3E%3C%2Fsvg%3E");
|
|
22
34
|
}
|
|
@@ -33,6 +45,10 @@
|
|
|
33
45
|
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20stroke%3D%22none%22%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3Cpath%20d%3D%22M4%206a2%202%200%200%201%202%20-2h12a2%202%200%200%201%202%202v12a2%202%200%200%201%20-2%202h-12a2%202%200%200%201%20-2%20-2l0%20-12%22%2F%3E%3Cpath%20d%3D%22M9%204v16%22%2F%3E%3Cpath%20d%3D%22M14%2010l2%202l-2%202%22%2F%3E%3C%2Fsvg%3E");
|
|
34
46
|
}
|
|
35
47
|
|
|
48
|
+
.ti-menu-2 {
|
|
49
|
+
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20stroke%3D%22none%22%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3Cpath%20d%3D%22M4%206l16%200%22%2F%3E%3Cpath%20d%3D%22M4%2012l16%200%22%2F%3E%3Cpath%20d%3D%22M4%2018l16%200%22%2F%3E%3C%2Fsvg%3E");
|
|
50
|
+
}
|
|
51
|
+
|
|
36
52
|
.ti-copy {
|
|
37
53
|
--ld-tabler-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%3E%3Cpath%20stroke%3D%22none%22%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%20%2F%3E%3Cpath%20d%3D%22M7%209.667a2.667%202.667%200%200%201%202.667%20-2.667h8.666a2.667%202.667%200%200%201%202.667%202.667v8.666a2.667%202.667%200%200%201%20-2.667%202.667h-8.666a2.667%202.667%200%200%201%20-2.667%20-2.667l0%20-8.666%22%20%2F%3E%3Cpath%20d%3D%22M4.012%2016.737a2.005%202.005%200%200%201%20-1.012%20-1.737v-10c0%20-1.1%20.9%20-2%202%20-2h10c.75%200%201.158%20.385%201.5%201%22%20%2F%3E%3C%2Fsvg%3E");
|
|
38
54
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
let animationFrame: number | undefined;
|
|
2
|
+
|
|
3
|
+
export function initTocVisibility() {
|
|
4
|
+
window.addEventListener("scroll", scheduleTocVisibilityUpdate, {
|
|
5
|
+
passive: true,
|
|
6
|
+
});
|
|
7
|
+
window.addEventListener("resize", scheduleTocVisibilityUpdate);
|
|
8
|
+
document.addEventListener("lildocs:page-view", scheduleTocVisibilityUpdate);
|
|
9
|
+
void document.fonts?.ready.then(scheduleTocVisibilityUpdate);
|
|
10
|
+
scheduleTocVisibilityUpdate();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function scheduleTocVisibilityUpdate() {
|
|
14
|
+
if (animationFrame !== undefined) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
animationFrame = window.requestAnimationFrame(() => {
|
|
19
|
+
animationFrame = undefined;
|
|
20
|
+
updateTocVisibility();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function updateTocVisibility() {
|
|
25
|
+
const container = document.querySelector<HTMLElement>("[data-toc-links]");
|
|
26
|
+
const indicator = container?.querySelector<HTMLElement>(
|
|
27
|
+
"[data-toc-visibility]",
|
|
28
|
+
);
|
|
29
|
+
if (!container || !indicator) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const items = Array.from(
|
|
34
|
+
container.querySelectorAll<HTMLAnchorElement>('a[href^="#"]'),
|
|
35
|
+
)
|
|
36
|
+
.map((link) => {
|
|
37
|
+
const heading = headingForLink(link);
|
|
38
|
+
return heading ? { heading, link } : undefined;
|
|
39
|
+
})
|
|
40
|
+
.filter((item): item is { heading: HTMLElement; link: HTMLAnchorElement } =>
|
|
41
|
+
Boolean(item),
|
|
42
|
+
);
|
|
43
|
+
const visibleItems = items.filter(({ heading }) => {
|
|
44
|
+
const bounds = heading.getBoundingClientRect();
|
|
45
|
+
return bounds.bottom > 0 && bounds.top < window.innerHeight;
|
|
46
|
+
});
|
|
47
|
+
if (visibleItems.length === 0 || visibleItems.length === items.length) {
|
|
48
|
+
indicator.classList.remove("isVisible");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const containerBounds = container.getBoundingClientRect();
|
|
53
|
+
const firstBounds = visibleItems[0].link.getBoundingClientRect();
|
|
54
|
+
const lastBounds =
|
|
55
|
+
visibleItems.at(-1)?.link.getBoundingClientRect() ?? firstBounds;
|
|
56
|
+
indicator.style.setProperty(
|
|
57
|
+
"--ld-toc-visibility-top",
|
|
58
|
+
`${firstBounds.top - containerBounds.top}px`,
|
|
59
|
+
);
|
|
60
|
+
indicator.style.setProperty(
|
|
61
|
+
"--ld-toc-visibility-height",
|
|
62
|
+
`${lastBounds.bottom - firstBounds.top}px`,
|
|
63
|
+
);
|
|
64
|
+
indicator.classList.add("isVisible");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function headingForLink(link: HTMLAnchorElement): HTMLElement | null {
|
|
68
|
+
const id = link.hash.slice(1);
|
|
69
|
+
if (!id) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
return document.getElementById(decodeURIComponent(id));
|
|
75
|
+
} catch {
|
|
76
|
+
return document.getElementById(id);
|
|
77
|
+
}
|
|
78
|
+
}
|
package/package.json
CHANGED