-
Notifications
You must be signed in to change notification settings - Fork 193
Description
Feature:
I'd like to use an MDX plugin to create programmatic meta (variable declarations) that can then be exposed in the final object contentlayer provides.
Use case:
An example of here this would be useful is generating a TOC, creating a list of unique keywords, etc.
Work around:
Use computed fields (which don't expose the the raw AST)
Related issues: kentcdodds/mdx-bundler#169
Consider the following config structure
export default makeSource({
contentDirPath: "content",
documentTypes: [Posts, Things, People],
mdx: {
rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings, searchMeta],
},
});
Where searchMeta
looks at paragraph nodes of mhast, grabs a list of unique words, and adds them to the metadata as searchMeta
.
A markdown file with the structure of:
---
title: Hello World
slug: hello-world
---
Hello World! Please say Hello!
Would generate a final object of:
{
"title": "Hello World",
"slug": "hello-world",
"searchMeta": ["hello", "world", "please", "say"],
"code": "().....",
"_raw": "..."
}
For sake of complete, if not ugly code, here's a working example of the plugin that adds searchMeta
to the data attribute of the vFile in the rehype plugin chain.
import { visit } from "unist-util-visit";
export default function searchMeta() {
return (tree, file) => {
visit(tree, { tagName: "p" }, (node) => {
let words = node.children.reduce((collector, current) => {
if (typeof current.value === "string") {
let wordList = current.value
.split(" ")
.filter((word) => !word.includes(":"))
.map((word) => word.toLowerCase().replace(/[^a-z0-9]/gi, ""))
.filter((word) => word.length > 3);
let newCollector = new Set([...wordList, ...collector]);
return newCollector;
} else {
return collector;
}
}, new Set());
file.data.searchMeta = [...words];
});
};
}