feat: added headers to links in local pages

This commit is contained in:
venus
2026-10-20 16:11:11 -05:00
parent 98e46644c0
commit efb0fbea94
2 changed files with 34 additions and 5 deletions
+16 -4
View File
@@ -57,20 +57,32 @@ export function normalizeObsidianMarkdown(content) {
// 2. Convert wikilinks with label: [[target-slug|Custom Label]] -> [Custom Label](/posts/target-slug/) // 2. Convert wikilinks with label: [[target-slug|Custom Label]] -> [Custom Label](/posts/target-slug/)
normalized = normalized.replace(/\[\[([^|\]]+)\|([^\]]+)\]\]/g, (match, target, label) => { normalized = normalized.replace(/\[\[([^|\]]+)\|([^\]]+)\]\]/g, (match, target, label) => {
const slug = slugify(target); return `[${label.trim()}](${wikilinkUrl(target)})`;
return `[${label.trim()}](/posts/${slug}/)`;
}); });
// 3. Convert simple wikilinks: [[target-slug]] -> [target-slug](/posts/target-slug/) // 3. Convert simple wikilinks: [[target-slug]] -> [target-slug](/posts/target-slug/)
normalized = normalized.replace(/\[\[([^\]]+)\]\]/g, (match, target) => { normalized = normalized.replace(/\[\[([^\]]+)\]\]/g, (match, target) => {
const trimmed = target.trim(); const trimmed = target.trim();
const slug = slugify(trimmed); return `[${trimmed}](${wikilinkUrl(trimmed)})`;
return `[${trimmed}](/posts/${slug}/)`;
}); });
return normalized; return normalized;
} }
function wikilinkUrl(target) {
const trimmed = target.trim();
const fragmentIndex = trimmed.indexOf("#");
if (fragmentIndex === -1) {
return `/posts/${slugify(trimmed)}/`;
}
const noteSlug = slugify(trimmed.slice(0, fragmentIndex));
const headerSlug = slugify(trimmed.slice(fragmentIndex + 1));
const fragment = headerSlug ? `#${headerSlug}` : "";
return `/posts/${noteSlug}/${fragment}`;
}
function slugify(text) { function slugify(text) {
return text return text
.toLowerCase() .toLowerCase()
+18 -1
View File
@@ -3,10 +3,27 @@ import assert from "node:assert/strict";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import http from "node:http"; import http from "node:http";
import { createServer, triggerEleventyBuild } from "../server.js"; import { createServer, normalizeObsidianMarkdown, triggerEleventyBuild } from "../server.js";
const TEST_SECRET = "super-secret-test-token"; const TEST_SECRET = "super-secret-test-token";
test("Obsidian normalization: preserves linked note header fragments", () => {
const normalized = normalizeObsidianMarkdown(
"See [[a note#header one]] and [[another note#Second Header|the other section]]."
);
assert.match(
normalized,
/\[a note#header one\]\(\/posts\/a-note\/#header-one\)/,
"A wikilink header must become a URL fragment on the linked note"
);
assert.match(
normalized,
/\[the other section\]\(\/posts\/another-note\/#second-header\)/,
"Aliased wikilinks must retain their linked-note header fragment"
);
});
test("Ingestion API: rejects requests without proper Bearer token", async () => { test("Ingestion API: rejects requests without proper Bearer token", async () => {
const tmpDir = fs.mkdtempSync(path.join(process.cwd(), "test-tmp-site-")); const tmpDir = fs.mkdtempSync(path.join(process.cwd(), "test-tmp-site-"));
const tmpPosts = fs.mkdtempSync(path.join(process.cwd(), "test-tmp-posts-")); const tmpPosts = fs.mkdtempSync(path.join(process.cwd(), "test-tmp-posts-"));