Last active
May 23, 2024 05:16
-
-
Save shazron/155d0c5f470ab9576318fd0c104d5560 to your computer and use it in GitHub Desktop.
Update the front-matter title property of Markdown files from the first heading title
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('node:fs'); | |
const path = require('node:path'); | |
const matter = require('gray-matter'); | |
const MarkdownIt = require('markdown-it'); | |
const MarkdownItFrontMatter = require('markdown-it-front-matter'); | |
if (!matter || !MarkdownIt || !MarkdownItFrontMatter) { | |
console.error('Module "gray-matter", "markdown-it", or "markdown-it-front-matter" not found. Run "npm install"'); | |
process.exit(1); | |
} | |
// Function to parse command line arguments | |
function parseArgs() { | |
const args = process.argv.slice(2); | |
const flags = {}; | |
const positionalArgs = []; | |
args.forEach(arg => { | |
if (arg.startsWith('--')) { | |
const [flag, value] = arg.split('='); | |
const flagName = flag.slice(2); | |
flags[flagName] = value || true; | |
} else if (arg.startsWith('-')) { | |
const flagName = arg.slice(1); | |
flags[flagName] = true; | |
} else { | |
positionalArgs.push(arg); | |
} | |
}); | |
return { flags, positionalArgs }; | |
} | |
// Function to get the first heading of a Markdown file | |
function getFirstHeading(filePath) { | |
// Read the file content | |
const fileContent = fs.readFileSync(filePath, 'utf8'); | |
// Initialize Markdown-It | |
const md = new MarkdownIt().use(MarkdownItFrontMatter, () => { }); | |
// Parse the Markdown content | |
const tokens = md.parse(fileContent, {}); | |
// Find the first heading | |
for (let token of tokens) { | |
if (token.type === 'heading_open') { | |
// The next token is the heading text | |
const headingTextToken = tokens[tokens.indexOf(token) + 1]; | |
return headingTextToken.content; | |
} | |
} | |
// No heading found | |
return null; | |
} | |
// Function to read, edit, and write the front matter of a Markdown file | |
function editFrontMatter(filePath, flags) { | |
// Read the file content | |
const fileContent = fs.readFileSync(filePath, 'utf8'); | |
// Parse the front matter | |
const parsedContent = matter(fileContent); | |
// Modify the front matter (example: adding a new field 'modified' with the current date) | |
const doWrite = !(flags['skip-existing'] && parsedContent.data.title) | |
if (doWrite) { | |
const firstHeading = getFirstHeading(filePath) | |
if (firstHeading) { | |
parsedContent.data.title = firstHeading; | |
} else { | |
parsedContent.data.title = 'TODO: please update with the correct title'; | |
} | |
// Convert back to string with updated front matter | |
const newContent = matter.stringify(parsedContent.content, parsedContent.data); | |
// Write the new content back to the file | |
fs.writeFileSync(filePath, newContent, 'utf8'); | |
} | |
} | |
// Function to iterate through a folder and process Markdown files | |
function processMarkdownFiles(folderPath, flags) { | |
// Read the contents of the folder | |
const files = fs.readdirSync(folderPath); | |
// Iterate through each file/directory in the folder | |
files.forEach(file => { | |
const filePath = path.join(folderPath, file); | |
// Check if the file is a directory | |
if (fs.statSync(filePath).isDirectory()) { | |
// Recursively process the subdirectory | |
processMarkdownFiles(filePath, flags); | |
} else if (path.extname(file) === '.md') { | |
// If it's a Markdown file, edit its front matter | |
console.log(`Processing file: ${filePath}`); | |
editFrontMatter(filePath, flags); | |
} | |
}); | |
} | |
async function main() { | |
const { flags, positionalArgs } = parseArgs(); | |
// Sample script functionality based on parsed arguments | |
if (flags.help) { | |
console.log('Update the front-matter title of your Markdown files based on the first heading'); | |
console.log(`Usage: node ${path.relative(process.cwd(), __filename)} [options] MD_FOLDER_PATH`); | |
console.log('Options:'); | |
console.log(' --help Show this help message'); | |
console.log(' --skip-existing Skip overwriting existing title front-matter'); | |
return; | |
} | |
if (positionalArgs.length < 1) { | |
throw new Error('Please provide the markdown folder path'); | |
} | |
const folderPath = positionalArgs[0]; | |
processMarkdownFiles(folderPath, flags); | |
} | |
main() | |
.catch(console.error) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Installation:
cd
into that new folderupdate_fm_in_md.js
npm init -y
npm install gray-matter markdown-it markdown-it-front-matter
node ./update_fm_in_md.js --help
to see instructions