Files
blog/eleventy.config.js
T
venus e4601dbbcb feat: adopt strict TDD framework and add adversarial test suite
- Update AGENTS.md and .agents/rules/blog-system.md with strict TDD mandate
- Extract Eleventy custom filters into modular src/_filters/index.js for unit testing
- Add npm test script using Node.js native test runner (node:test)
- Create test/site-config.test.js for environment validation and fatal error assertions
- Create test/filters.test.js for adversarial filter edge cases (dates, limits, reading time, headings)
- Create test/frontmatter-schema.test.js enforcing post metadata contracts
- Create test/design-rules.test.js enforcing strict anti-patterns (no glassmorphism, no shadows, max 4px radius)
- Create test/build-integrity.test.js checking static output, zero 404 links, and TOC anchor targets
2026-09-13 01:16:20 -05:00

77 lines
2.1 KiB
JavaScript

import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import markdownIt from "markdown-it";
import markdownItAnchor from "markdown-it-anchor";
import { filters } from "./src/_filters/index.js";
export default function (eleventyConfig) {
// 1. Static Asset Passthrough Copy
eleventyConfig.addPassthroughCopy({ "src/assets": "assets" });
// 2. Syntax Highlighting Plugin
eleventyConfig.addPlugin(syntaxHighlight);
// 3. Markdown-It Library Customization
const markdownOptions = {
html: true,
breaks: false,
linkify: true
};
const markdownLib = markdownIt(markdownOptions).use(markdownItAnchor, {
permalink: markdownItAnchor.permalink.headerLink({
safariReaderFix: true
}),
slugify: (s) =>
s
.trim()
.toLowerCase()
.replace(/[^a-z0-9 -]/g, "")
.replace(/\s+/g, "-")
.replace(/-+/g, "-")
});
eleventyConfig.setLibrary("md", markdownLib);
// 4. Custom Filters (imported from modular src/_filters/index.js)
for (const [name, fn] of Object.entries(filters)) {
eleventyConfig.addFilter(name, fn);
}
// 5. Custom Collections
// Chronological blog posts collection
eleventyConfig.addCollection("posts", (collectionApi) => {
return collectionApi
.getFilteredByGlob("src/posts/*.md")
.filter((post) => !post.data.draft)
.sort((a, b) => b.date - a.date);
});
// Dynamic Tag List Collection across all posts
eleventyConfig.addCollection("tagList", (collectionApi) => {
const tagSet = new Set();
collectionApi.getFilteredByGlob("src/posts/*.md").forEach((item) => {
if ("tags" in item.data) {
let tags = item.data.tags;
if (typeof tags === "string") tags = [tags];
for (const tag of tags) {
const cleanTag = tag.replace(/^#/, "");
tagSet.add(cleanTag);
}
}
});
return [...tagSet].sort();
});
return {
dir: {
input: "src",
includes: "_includes",
data: "_data",
output: "_site"
},
templateFormats: ["njk", "md", "html"],
htmlTemplateEngine: "njk",
markdownTemplateEngine: "njk"
};
}