feat: add persistent book navigation and public-only pages

This commit is contained in:
2026-10-15 17:53:48 +09:00
parent f6905074b1
commit 839eb2a6a4
22 changed files with 1191 additions and 269 deletions
+20 -2
View File
@@ -4,9 +4,11 @@ import test from 'node:test';
import documentLinks, { contentsRoot, documentHref, normalizeBase } from '../plugins/document-links.mjs';
const source = path.join(contentsRoot, '3-protocol.md');
test('canonical, draft and cross-directory links keep their fragments', () => {
test('published links keep fragments and draft targets stay unpublished', () => {
assert.equal(documentHref('4.2-text-view.md#参照表記', source), '/book/4.2-text-view/#参照表記');
assert.equal(documentHref('draft/unresolved-issues.md', source), '/book/draft/unresolved-issues/');
assert.equal(documentHref('draft/unresolved-issues.md', source), null);
assert.equal(documentHref('./draft/unresolved-issues.md?from=book#detail', source, '/wip'), null);
assert.equal(documentHref('%64raft/unresolved-issues.md', source), null);
assert.equal(documentHref('../3-protocol.md#value', path.join(contentsRoot, 'draft/rust-api-model.md')), '/book/3-protocol/#value');
});
test('base prefix and query are preserved', () => {
@@ -22,6 +24,22 @@ test('invalid base and links escaping contents are rejected', () => {
for (const base of ['relative', '//example.test', '/foo?x', '/../x']) assert.throws(() => normalizeBase(base));
assert.throws(() => documentHref('../secret.md', source));
});
test('draft links render only their text without changing source code examples', () => {
const text = { type: 'text', value: '未解決事項' };
const emphasis = { type: 'emphasis', children: [text] };
const code = { type: 'code', value: '[example](draft/unresolved-issues.md)' };
const tree = { type: 'root', children: [
{ type: 'paragraph', children: [
{ type: 'link', url: 'draft/unresolved-issues.md', children: [emphasis] },
{ type: 'linkReference', identifier: 'draft-ref', referenceType: 'full', children: [text] },
] },
{ type: 'definition', identifier: 'draft-ref', url: 'draft/unresolved-issues.md#detail' },
code,
] };
documentLinks()(tree, { path: source });
assert.deepEqual(tree.children, [{ type: 'paragraph', children: [emphasis, text] }, code]);
});
test('remark handles reference links but leaves code examples unchanged', () => {
const tree = { type: 'root', children: [
{ type: 'link', url: '4-client.md', children: [] },