Skip to content

Commit ac92804

Browse files
authored
pager config (#247)
1 parent 6300bb8 commit ac92804

File tree

6 files changed

+31
-23
lines changed

6 files changed

+31
-23
lines changed

docs/.observablehq/config.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,5 @@ export default {
2929
]
3030
},
3131
{name: "Contributing", path: "/contributing"}
32-
],
33-
toc: {
34-
show: true
35-
}
32+
]
3633
};

src/config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export interface TableOfContents {
2222
export interface Config {
2323
title?: string;
2424
pages: (Page | Section)[]; // TODO rename to sidebar?
25+
pager: boolean; // defaults to true
2526
toc: TableOfContents;
2627
}
2728

@@ -56,11 +57,12 @@ async function readPages(root: string): Promise<Page[]> {
5657
}
5758

5859
export async function normalizeConfig(spec: any, root: string): Promise<Config> {
59-
let {title, pages = await readPages(root), toc = true} = spec;
60+
let {title, pages = await readPages(root), pager = true, toc = true} = spec;
6061
if (title !== undefined) title = String(title);
6162
pages = Array.from(pages, normalizePageOrSection);
63+
pager = Boolean(pager);
6264
toc = normalizeToc(toc);
63-
return {title, pages, toc};
65+
return {title, pages, pager, toc};
6466
}
6567

6668
function normalizePageOrSection(spec: any): Page | Section {

src/pager.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ export type PageLink =
66
| {prev: Page; next: undefined}; // last page
77

88
// Pager links in the footer are computed once for a given navigation.
9-
const pagers = new WeakMap<Config["pages"], Map<string, PageLink>>();
9+
const linkCache = new WeakMap<Config["pages"], Map<string, PageLink>>();
1010

11-
export function pager(path: string, options: Pick<Config, "pages" | "title"> = {pages: []}): PageLink | undefined {
11+
export function findLink(path: string, options: Pick<Config, "pages" | "title"> = {pages: []}): PageLink | undefined {
1212
const {pages, title} = options;
13-
let links = pagers.get(pages);
13+
let links = linkCache.get(pages);
1414
if (!links) {
1515
links = new Map<string, PageLink>();
1616
let prev: Page | undefined;
@@ -24,7 +24,7 @@ export function pager(path: string, options: Pick<Config, "pages" | "title"> = {
2424
prev = page;
2525
}
2626
if (links.size === 1) links.clear(); // no links if only one page
27-
pagers.set(pages, links);
27+
linkCache.set(pages, links);
2828
}
2929
return links.get(path);
3030
}

src/render.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {type Html, html} from "./html.js";
44
import {type ImportResolver, createImportResolver} from "./javascript/imports.js";
55
import {type FileReference, type ImportReference} from "./javascript.js";
66
import {type CellPiece, type ParseResult, parseMarkdown} from "./markdown.js";
7-
import {type PageLink, pager} from "./pager.js";
7+
import {type PageLink, findLink} from "./pager.js";
88
import {relativeUrl} from "./url.js";
99

1010
export interface Render {
@@ -49,11 +49,9 @@ type RenderInternalOptions =
4949
| {preview?: false} // serverless
5050
| {preview: true}; // preview
5151

52-
function render(
53-
parseResult: ParseResult,
54-
{root, path, pages, title, toc, preview, resolver}: RenderOptions & RenderInternalOptions
55-
): string {
56-
toc = mergeToc(parseResult.data?.toc, toc);
52+
function render(parseResult: ParseResult, options: RenderOptions & RenderInternalOptions): string {
53+
const {root, path, pages, title, preview, resolver} = options;
54+
const toc = mergeToc(parseResult.data?.toc, options.toc);
5755
const headers = toc.show ? findHeaders(parseResult) : [];
5856
return String(html`<!DOCTYPE html>
5957
<meta charset="utf-8">${path === "/404" ? html`\n<base href="/">` : ""}
@@ -83,7 +81,7 @@ ${pages.length > 0 ? renderSidebar(title, pages, path) : ""}
8381
${headers.length > 0 ? renderToc(headers, toc.label) : ""}<div id="observablehq-center">
8482
<main id="observablehq-main" class="observablehq">
8583
${html.unsafe(parseResult.html)}</main>
86-
${renderFooter(path, {pages, title})}
84+
${renderFooter(path, options)}
8785
</div>
8886
`);
8987
}
@@ -174,8 +172,8 @@ function renderImportPreloads(parseResult: ParseResult, path: string, resolver:
174172
return html`${Array.from(preloads, (href) => html`\n<link rel="modulepreload" href="${href}">`)}`;
175173
}
176174

177-
function renderFooter(path: string, options?: Pick<Config, "pages" | "title">): Html {
178-
const link = pager(path, options);
175+
function renderFooter(path: string, options: Pick<Config, "pages" | "pager" | "title">): Html {
176+
const link = options.pager ? findLink(path, options) : null;
179177
return html`<footer id="observablehq-footer">${link ? renderPager(path, link) : ""}
180178
<div>© ${new Date().getUTCFullYear()} Observable, Inc.</div>
181179
</footer>`;

test/config-test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ describe("readConfig(root)", () => {
1212
{path: "/sub/two", name: "Two"}
1313
],
1414
title: undefined,
15-
toc: {label: "On this page", show: true}
15+
toc: {label: "On this page", show: true},
16+
pager: true
1617
});
1718
});
1819
it("returns the default config if no config file is found", async () => {
1920
assert.deepStrictEqual(await readConfig("test/input/build/simple"), {
2021
pages: [{name: "Build test case", path: "/simple"}],
2122
title: undefined,
22-
toc: {label: "Contents", show: true}
23+
toc: {label: "Contents", show: true},
24+
pager: true
2325
});
2426
});
2527
});
@@ -72,6 +74,15 @@ describe("normalizeConfig(spec, root)", () => {
7274
assert.deepStrictEqual((await config({pages: [], toc: true}, root)).toc, {label: "Contents", show: true});
7375
assert.deepStrictEqual((await config({pages: [], toc: false}, root)).toc, {label: "Contents", show: false});
7476
});
77+
it("coerces pager", async () => {
78+
assert.strictEqual((await config({pages: [], pager: 0}, root)).pager, false);
79+
assert.strictEqual((await config({pages: [], pager: 1}, root)).pager, true);
80+
assert.strictEqual((await config({pages: [], pager: ""}, root)).pager, false);
81+
assert.strictEqual((await config({pages: [], pager: "0"}, root)).pager, true);
82+
});
83+
it("populates default pager", async () => {
84+
assert.strictEqual((await config({pages: []}, root)).pager, true);
85+
});
7586
});
7687

7788
describe("mergeToc(spec, toc)", () => {

test/pager-test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from "node:assert";
2-
import {pager} from "../src/pager.js";
2+
import {findLink as pager} from "../src/pager.js";
33

4-
describe("pager(path, options)", () => {
4+
describe("findLink(path, options)", () => {
55
it("returns the previous and next links for three pages", () => {
66
const config = {
77
pages: [

0 commit comments

Comments
 (0)