diff --git a/config/index.js b/config/index.js index 83a373d5..ba0a9128 100644 --- a/config/index.js +++ b/config/index.js @@ -9,7 +9,9 @@ require("dotenv").config(); module.exports = (eleventyConfig) => { const env = process.env.NODE_ENV || "development"; // enables JSX-based templates and components - eleventyConfig.addPlugin(require("eleventy-hast-jsx").plugin); + eleventyConfig.addPlugin(require("eleventy-hast-jsx").plugin, { + componentsDir: "components", + }); // minify and/or format HTML, purge unused CSS in production eleventyConfig.addPlugin(require("./minify")); @@ -24,7 +26,11 @@ module.exports = (eleventyConfig) => { eleventyConfig.addExtension("md", { async compile(inputContent, inputPath) { let result = import("./markdown.mjs").then(({ render }) => - render(inputContent, inputPath) + render( + inputContent, + inputPath, + eleventyConfig[require("eleventy-hast-jsx").renderComponent] + ) ); return () => result; }, diff --git a/config/markdown.mjs b/config/markdown.mjs index eb4e40fd..d47ef270 100644 --- a/config/markdown.mjs +++ b/config/markdown.mjs @@ -2,7 +2,6 @@ import fs from "node:fs"; import path from "node:path"; -import { map } from "unist-util-map"; import { unified } from "unified"; import rehypeParse from "rehype-parse"; @@ -35,9 +34,17 @@ const processorToString = processor // convert the HTML nodes to an HTML string .use(rehypeStringify, { allowDangerousHtml: true }); -/** @param {string} str */ -export async function render(str, path) { - const file = await processorToString.process({ value: str, path }); +/** + * @param {string} str + * @param {string} path + * @param {import("eleventy-hast-jsx").RenderComponent} renderComponent + */ +export async function render(str, path, renderComponent) { + const file = await processorToString.process({ + value: str, + path, + data: { renderComponent }, + }); return file.value.toString("utf8"); } @@ -226,6 +233,20 @@ function directivesPlugin() { }); } + // component: run eleventy-hast-jsx + if (node.type === "leafDirective" && node.name === "component") { + if (node.children.length !== 1 || node.children[0].type !== "text") { + throw new Error(`Expected a component name`); + } + const name = node.children[0].value; + return file.data + .renderComponent(name, node.attributes) + .then((renderedHtml) => ({ + type: "html", + value: renderedHtml, + })); + } + // otherwise, return the node unchanged return node; }); @@ -358,3 +379,20 @@ function findPrefix(paragraph) { }), }; } + +// Copied from unist-util-map to make it async +function map(tree, mapFunction) { + return preorder(tree, null, null); + + async function preorder(node, index, parent) { + const newNode = Object.assign({}, await mapFunction(node, index, parent)); + + if ("children" in node) { + newNode.children = await Promise.all( + node.children.map((child, index) => preorder(child, index, node)) + ); + } + + return newNode; + } +} diff --git a/package.json b/package.json index 3fbdbceb..a6f8d1ba 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "date-fns": "^2.29.3", "date-fns-tz": "^1.3.7", "dotenv": "^16.0.3", - "eleventy-hast-jsx": "^0.3.1", + "eleventy-hast-jsx": "^0.3.4", "fast-glob": "^3.2.12", "hast-util-to-html": "^8.0.3", "listify": "^1.0.3", @@ -50,7 +50,6 @@ "subset-font": "^2.0.0", "title": "^3.5.3", "unified": "^10.1.2", - "unist-util-map": "^3.1.2", "vfile": "^5.3.6", "yaml": "^2.1.3" }, diff --git a/pages/index.md b/pages/index.md index 8aea2c32..1690c2e7 100644 --- a/pages/index.md +++ b/pages/index.md @@ -6,7 +6,7 @@ summary = "Are you a Brown University undergraduate, grad student, or employee? **[Commencement Schedule 2023 →](/commencement/)** -{% component "Carousel", folder="homepage" %} +::component[Carousel]{folder="homepage"} ## Why join the band? diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 403efec5..4fa1e7f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,8 +56,8 @@ devDependencies: specifier: ^16.0.3 version: 16.0.3 eleventy-hast-jsx: - specifier: ^0.3.1 - version: 0.3.3 + specifier: ^0.3.4 + version: 0.3.4 fast-glob: specifier: ^3.2.12 version: 3.2.12 @@ -124,9 +124,6 @@ devDependencies: unified: specifier: ^10.1.2 version: 10.1.2 - unist-util-map: - specifier: ^3.1.2 - version: 3.1.3 vfile: specifier: ^5.3.6 version: 5.3.7 @@ -1472,8 +1469,8 @@ packages: resolution: {integrity: sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==} dev: true - /eleventy-hast-jsx@0.3.3: - resolution: {integrity: sha512-3BbrGpgnKydLaE0PzbFqsJGMgGjTOHdyhmVL8eK2VY0ildf8yjC7CJrE6G3RKfrmarEjeR2EnJu8YFG/tpAXKQ==} + /eleventy-hast-jsx@0.3.4: + resolution: {integrity: sha512-fSjOWou02dcxZwfhqtmqyJvuhTye2/uOPrZ03fbzjlNFP5iD0Mnoog293GnQJ9RKk1luvZsQESOl0XcBzRNf6g==} engines: {node: '>=16.0.0'} dependencies: '@11ty/eleventy-utils': 1.0.1 @@ -4453,12 +4450,6 @@ packages: '@types/unist': 2.0.6 dev: true - /unist-util-map@3.1.3: - resolution: {integrity: sha512-4/mDauoxqZ6geK97lJ6n2kDk6JK88Vh+hWMSJqyaaP/7eqN1dDhjcjnNxKNm3YU6Sw7PVJtcFMUbnmHvYzb6Vg==} - dependencies: - '@types/unist': 2.0.6 - dev: true - /unist-util-position@4.0.4: resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} dependencies: