Allow modify the file object when invoking `beforeParse` hook
Is your feature request related to a problem? Please describe
I tried to do a full-text search among all of markdown files under content directory, and this requires processing the raw text. I tried appending properties to file object:
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('content:file:beforeParse', (file) => {
if (file._id.endsWith('.md')) {
file.plainText = file.body
}
})
})
However, I noticed that the source simply does not mutate the file object; instead, it just passed properties needed for following procedures.
I wonder if beforeParse can behave the same just like afterParse?
Describe the solution you'd like
Mutate file object when invoking beforeParse hook
Describe alternatives you've considered
For now, I did:
import { Node as UnistNode } from 'unist'
interface Node extends UnistNode {
value: 'text' | string
children?: Node[]
tag?: 'style' | string
}
function toText (root: Node) {
let text = ''
function recurse (node: Node) {
if (node.type === 'text') {
text += ` ${node.value}`
}
if (node.children && node.tag !== 'style') {
for (const child of node.children) {
recurse(child)
}
}
}
recurse(root)
return text
}
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('content:file:afterParse', (file) => {
if (file._id.endsWith('.md')) {
file.plainText = toText(file.body)
}
})
})
And it is hecka annoying.
Additional context
Using patch to enable this temporarily:
diff --git a/src/runtime/server/storage.ts b/src/runtime/server/storage.ts
index 25cddb13..b607b743 100644
--- a/src/runtime/server/storage.ts
+++ b/src/runtime/server/storage.ts
@@ -182,7 +182,13 @@ export async function parseContent (id: string, content: string, opts: ParseCont
const file = { _id: id, body: content }
await nitroApp.hooks.callHook('content:file:beforeParse', file)
- const result = await transformContent(id, file.body, options)
+ const result: ParsedContent | {[key: string]: any} = await transformContent(id, file.body, options)
+
+ for (const [key, value] of Object.entries(file)) {
+ if (result[key] === undefined) {
+ result[key] = value
+ }
+ }
// Call hook after parsing the file
await nitroApp.hooks.callHook('content:file:afterParse', result)
@Kiyo5hi I found a simple solution (to add "plain text" field), but I don't like it
export default defineNitroPlugin((nitroApp) => {
let files = {}
nitroApp.hooks.hook("content:file:beforeParse", (file) => {
if (file._id.endsWith(".md")) {
files[file._id] = file.body
}
})
nitroApp.hooks.hook("content:file:afterParse", (file) => {
if (file._id.endsWith(".md")) {
file.plainText = files[file._id]
}
})
})
Hope this helps!
Same for my nuxt-content-body-html module :).
Just found this issue, my usecase is to support the Foam format https://foambubble.github.io/ Which allows you to inline #tags #like #this
Hoped something as simple as this would have worked:
const tagRegEx = /#(\w+)/g;
if (!file.tags) {
file.tags = [];
}
// Get all matches of #tag format
const tagMatches = [...file.body.matchAll(tagRegEx)];
tagMatches.forEach((match) => {
console.log("Tag: " + match)
// Add tag to frontmatter if it doesn't exist already
if (!file.tags.includes(match[1])) {
file.tags.push(match[1]);
// Replace #tag with a link to the corresponding tag page
file.body = file.body.replaceAll(match[0], `[#${match[1]}](/tags/${match[1]})`, 'g');
}
}
but as the others here, I need to do some extra trickery :) Thankfully, the solution from xdeq is smooth and gives me some more ideas for how to fix the support 8)
There is a simpler way to expose your markdown files ! Even more, it provides a direct URL access and works for all kind of files : md, yaml, csv...
Just expose your content directory as a public assets. In a module, add this :
nuxt.hook('nitro:config', (nitroConfig) => {
nitroConfig.publicAssets ||= []
nitroConfig.publicAssets.push({
dir: `${nitroConfig.rootDir}/content`,
baseURL: '',
maxAge: 60 * 60 * 24 * 365, // 1 year
})
})
Now, add the extension to a route and you get your files. Ex:
From the page /url-of-my-awesome-page, you can get the corresponding markdown file with /url-of-my-awesome-page.md.