Last active
September 4, 2021 15:59
-
-
Save brianwisti/9334dfb194a5ffd8e4f9d6abbea2df23 to your computer and use it in GitHub Desktop.
Use markdown-it to transform markdown files for consumption by other static site generators (Hugo specifically)
This file contains hidden or 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
// This file processes a mess of FILE.md.txt files under Hugo `content/`, | |
// creating `index.html` files with HTML fragments and frontmatter. | |
// As far as Hugo's concerned it's just some more content, and I can prep | |
// for Astro or another Node-based SSG without disrupting the live site | |
// too much. | |
// | |
// Why? The Hugo version of my site is now SIX years old, and is a | |
// disorganized mishmash of formats and shortcodes. Porting it to | |
// anything else is what they call "non-trivial." | |
// | |
// Also this way I know what plugins to add in any SSG that uses markdown-it. | |
'use strict'; | |
const fs = require('fs'); | |
const path = require('path'); | |
const MarkdownIt = require('markdown-it'); | |
const glob = require("glob"); | |
const matter = require('gray-matter'); | |
const yargs = require('yargs/yargs'); | |
const { hideBin } = require('yargs/helpers'); | |
const admonitionPattern = /^(?<category>note|admonition)\s?(?<title>.*)$/; | |
const md = MarkdownIt({ html: true, }) | |
.use(require('markdown-it-abbr')) | |
.use(require('markdown-it-container'), 'note', { | |
validate: function(params) { | |
return params.trim().match(admonitionPattern); | |
}, | |
render: function (tokens, idx) { | |
const m = tokens[idx].info.trim().match(admonitionPattern); | |
if (tokens[idx].nesting === 1) { | |
// opening tag | |
let { category, title } = m.groups; | |
if (! category ) { | |
return console.error("Incomplete admonition"); | |
} | |
if (!title) { | |
title = category; | |
} | |
title = md.render(title); | |
return `<aside class="${category}">\n<header>${title}</header>\n`; | |
} else { | |
// closing tag | |
return '</aside>\n'; | |
} | |
} | |
} | |
) | |
.use(require('markdown-it-deflist')) | |
.use(require('markdown-it-figure')) | |
.use(require('markdown-it-footnote')) | |
.use(require('markdown-it-kbd')) | |
.use(require('markdown-it-prism'), { | |
defaultLanguage: 'text', | |
}); | |
const getTargetPath = (sourcePath) => | |
path.join( path.dirname(sourcePath), 'index.html'); | |
const transformFile = (sourcePath, targetPath) => { | |
fs.readFile(sourcePath, 'utf8', function (err, data) { | |
if (err) { | |
return console.error(err); | |
} | |
let post = matter(data); | |
post.content = md.render(post.content); | |
const transformed = post.stringify(); | |
console.log(`${sourcePath} -> ${targetPath}`); | |
fs.writeFile(targetPath, transformed, (err) => { | |
if (err) { | |
return console.error(err); | |
} | |
console.log("Saved!"); | |
}) | |
}); | |
}; | |
const transformAllFiles = (contentDir) => { | |
console.log(`Transforming all files in ${contentDir}`); | |
const sourceGlob = `${contentDir}/**/*.md.txt`; | |
glob(sourceGlob, (err, sourcePaths) => { | |
if (err) { | |
return console.error(err); | |
} | |
for (let sourcePath of sourcePaths) { | |
const targetPath = getTargetPath(sourcePath); | |
fs.stat(sourcePath, (err, sourceStat) => { | |
if (err) { | |
return console.error(err); | |
} | |
fs.stat(targetPath, (err, targetStat) => { | |
if (err) { | |
return console.error(err); | |
} | |
if (sourceStat.mtime > targetStat.mtime) { | |
transformFile(sourcePath, targetPath); | |
} | |
}); | |
}); | |
} | |
}); | |
}; | |
yargs(hideBin(process.argv)) | |
.command( | |
'file [md]', 'transform a markdown file', | |
(yargs) => { | |
return yargs | |
.positional('md', { | |
describe: 'markdown file to transform', | |
}) | |
}, | |
(argv) => { | |
const sourcePath = argv.md; | |
console.log(`Transforming ${sourcePath}`); | |
const targetPath = getTargetPath(sourcePath); | |
transformFile(sourcePath, targetPath); | |
} | |
) | |
.command( | |
'all [dir]', 'transform all markdown files', | |
(yargs) => { | |
return yargs | |
.positional('dir', { | |
describe: 'directory to work in', | |
default: 'content', | |
}); | |
}, | |
(argv) => { | |
transformAllFiles(argv.dir); | |
} | |
) | |
.argv; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment