简体   繁体   中英

Node.js - How to read/write a markdown file changing its front matter metadata?

I have a few hundred markdown files and I would like to loop through them and add a new data to their front matter metadata.

For example, this is what my files look like now:

---
title: My title here
---


Markdown content here

And I want to add an id property to them:

---
title: My title here
id: 1982n1x23981u1
---


Markdown content

What would be the cleanest way to do that in Node? I've found a few packages to handle markdown, but all of them aims to convert it to JSON instead.

Thanks in advance!

Here a basic script I used to update frontmatter of all my notes in Markdown script:

// @ts-check
const { readdir, readFile, writeFile } = require("fs/promises");
const matter = require("gray-matter");
const { stringify } = require("yaml");

const directory = "<YOUR-DIRECTORY>";

async function updateFrontMatter(filename) {
  const filepath = `${directory}/${filename}`;

  const { data: frontMatter, content } = matter(await readFile(filepath));

  // remove desc attribute
  if (frontMatter.desc === "") {
    delete frontMatter["desc"];
  }

  // parse created date attribute and convert it as timestamp
  if (typeof frontMatter.created === "string") {
    frontMatter.created = new Date(frontMatter.created).getTime();
  }

  const newContent = `---\n${stringify(frontMatter)}---\n${content}`;

  await writeFile(filepath, newContent);

  console.log(`- [x] ${filepath}`);
}

async function main() {
  const filenames = await readdir(directory);
  const markdownFilenames = filenames.filter((f) => f.endsWith(".md"));

  await Promise.all(markdownFilenames.map(updateFrontMatter));
}

main().catch(console.error);

Assuming you are actually talking about YAML and not Markdown/CommonMark , YAML being data markup like XML or JSON; Markdown / CommonMark being markup for text formatting...

You'll be wanting to user either of these NPM packages:

  • js-yaml @ 15.6 million downloads/week
  • YAML @ 4.9 million downloads/week

If you actually have Markdown / CommonMark , you can use a tool like NPM's commonmark which parses the document and loads it into an abstract syntax tree (AST) that you can manipulate and rewrite as Markdown.

Note that there are [many] other Markdown processors in NPM, including this one. Where they are compatible with the Markdown you are using... you'll have to figure that out yourself. CommonMark exists because of how the many Markdown implementations have diverged.

Another option would be to use pandoc and write a filter to process the AST that it produces.

I run into a similar challenge and came up with a generalised solution:

import matter from "gray-matter";

function processFrontmatter(md, options) {
  const frontmatter = matter(md).data;
  Object.entries(options).forEach(function ([fieldName, value]) {
    if (value === "del" || value === "-") {
      delete frontmatter[fieldName];
    } else {
      frontmatter[fieldName] = value;
    }
  });

  return matter.stringify(matter(md));
}

This function accepts markdown content (in string format), parses the frontmatter and changes it according to the options dictionary parameter:

// ---
// field: example value
// another_field: some value
// ---
// Markdown content
const md = '---\nfield: example value\nanother_field: some value\n---\nMarkdown content'

const options = {
    field: 'new example value',
    another_field: 'del',
    new_field: 'a new field!'
}

console.log(processFrontmatter(md, options))

Which will yield:

---
field: new example value
new_field: a new field!
---
Markdown content

I published this solution as a node module, see here .

For reading the Markdown content from a file and writing it, I'd refer to the fs module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM