contentlayerdev / contentlayerdev/contentlayer

Provide a way to populate field values from Markdown/MDX processing pipeline

Open
#216 13 comments 5 reactions 0 assignees View on GitHub
topic: markdown/mdx topic: schema
Dominant language
TypeScript
Stars
3.5k
Forks
192
PR merge metrics
No merged PRs in 30d

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: https://github.com/kentcdodds/mdx-bundler/issues/169

Consider the following config structure

```js
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:

```markdown

---
title: Hello World
slug: hello-world
---
Hello World! Please say Hello!
```

Would generate a final object of:

```json
{
"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.

```js

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];
});
};
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.