import assert from 'node:assert/strict'; import path from 'node:path'; import test from 'node:test'; import documentLinks, { contentsRoot, documentHref, normalizeBase } from '../plugins/document-links.mjs'; const source = path.join(contentsRoot, '3-protocol.md'); 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), 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', () => { assert.equal(normalizeBase('/reference'), '/reference/'); assert.equal(documentHref('4-client.md?from=book#known-space', source, '/reference'), '/reference/book/4-client/?from=book#known-space'); }); test('external URLs, local anchors and non-Markdown assets are untouched', () => { for (const url of ['https://example.test/file.md', '//example.test/file.md', '#名前と文字列', 'mailto:user@example.test', './image.svg']) { assert.equal(documentHref(url, source), url); } }); 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: [] }, { type: 'definition', url: '4-client.md#known-space' }, { type: 'code', value: '[example](4-client.md)' }, ] }; documentLinks() (tree, { path: source }); assert.equal(tree.children[0].url, '/book/4-client/'); assert.equal(tree.children[1].url, '/book/4-client/#known-space'); assert.equal(tree.children[2].value, '[example](4-client.md)'); });