Merge branch 'feat-local-header-links' into dev
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import nunjucks from "nunjucks";
|
||||
import path from "node:path";
|
||||
import { filters } from "../src/_filters/index.js";
|
||||
|
||||
const includesDir = path.resolve("src/_includes");
|
||||
const markdownExcerpt = "Read the [deployment guide](/guides/deploy/) before continuing.";
|
||||
|
||||
function renderTemplate(template, context) {
|
||||
const env = new nunjucks.Environment(new nunjucks.FileSystemLoader(includesDir), { autoescape: false });
|
||||
for (const [name, filter] of Object.entries(filters)) {
|
||||
env.addFilter(name, filter);
|
||||
}
|
||||
|
||||
return env.render(template, context);
|
||||
}
|
||||
|
||||
test("Excerpt Markdown: renders Markdown links as safe inline HTML", () => {
|
||||
assert.equal(
|
||||
filters.renderExcerptMarkdown(markdownExcerpt),
|
||||
'Read the <a href="/guides/deploy/">deployment guide</a> before continuing.'
|
||||
);
|
||||
});
|
||||
|
||||
test("Excerpt Markdown: renders links in post-card previews", () => {
|
||||
const output = renderTemplate("partials/post-card.njk", {
|
||||
post: {
|
||||
fileSlug: "example-dispatch",
|
||||
url: "/dispatches/example/",
|
||||
date: "2026-10-06",
|
||||
data: {
|
||||
title: "Example dispatch",
|
||||
excerpt: markdownExcerpt,
|
||||
tags: ["systems"]
|
||||
},
|
||||
templateContent: "A short article."
|
||||
}
|
||||
});
|
||||
|
||||
assert.match(output, /<p class="feed-excerpt">\s*Read the <a href="\/guides\/deploy\/">deployment guide<\/a> before continuing\.\s*<\/p>/);
|
||||
});
|
||||
|
||||
test("Excerpt Markdown: renders links in featured previews and escapes raw HTML", () => {
|
||||
const output = renderTemplate("partials/featured-card.njk", {
|
||||
collections: {
|
||||
posts: [{
|
||||
url: "/dispatches/example/",
|
||||
date: "2026-10-06",
|
||||
data: {
|
||||
featured: true,
|
||||
tags: ["systems"],
|
||||
title: "Example dispatch",
|
||||
excerpt: `${markdownExcerpt} <script>alert('unsafe')</script>`
|
||||
},
|
||||
templateContent: ""
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
assert.match(output, /<a href="\/guides\/deploy\/">deployment guide<\/a>/);
|
||||
assert.match(output, /<script>alert\('unsafe'\)<\/script>/);
|
||||
assert.doesNotMatch(output, /<script>/);
|
||||
});
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
filterTagList,
|
||||
isoDate,
|
||||
postDate,
|
||||
readingTime
|
||||
readingTime,
|
||||
renderExcerptMarkdown
|
||||
} from "../src/_filters/index.js";
|
||||
|
||||
const includesDir = path.resolve("src/_includes");
|
||||
@@ -19,6 +20,7 @@ function renderFeaturedCard(terminal) {
|
||||
env.addFilter("isoDate", isoDate);
|
||||
env.addFilter("postDate", postDate);
|
||||
env.addFilter("readingTime", readingTime);
|
||||
env.addFilter("renderExcerptMarkdown", renderExcerptMarkdown);
|
||||
|
||||
const featured = {
|
||||
url: "/dispatches/example/",
|
||||
|
||||
@@ -3,10 +3,27 @@ import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
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";
|
||||
|
||||
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 () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.cwd(), "test-tmp-site-"));
|
||||
const tmpPosts = fs.mkdtempSync(path.join(process.cwd(), "test-tmp-posts-"));
|
||||
|
||||
@@ -41,11 +41,7 @@ test("Site Config: correctly parses SITE_DOMAIN and derives service subdomains",
|
||||
const gitService = site.services.find((s) => s.name === "Gitea");
|
||||
assert.ok(gitService, "Gitea service exists");
|
||||
assert.equal(gitService.url, "https://git.riverrooks.dev/venus");
|
||||
assert.equal(gitService.tag, "git.testcluster.internal:2222");
|
||||
|
||||
const chefService = site.services.find((s) => s.name === "CyberChef");
|
||||
assert.ok(chefService, "CyberChef service exists");
|
||||
assert.equal(chefService.url, "https://chef.testcluster.internal");
|
||||
assert.equal(gitService.tag, "git.testcluster.internal:443");
|
||||
|
||||
// Verify navigation links
|
||||
const navHome = site.nav.find((n) => n.label === "Home");
|
||||
|
||||
Reference in New Issue
Block a user