Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save rdela/32603eecc215cab3374e9a973f07bca0 to your computer and use it in GitHub Desktop.
Save rdela/32603eecc215cab3374e9a973f07bca0 to your computer and use it in GitHub Desktop.
Prettier plugin for formatting JS frontmatter
import prettier from 'prettier';
import babelParser from 'prettier/plugins/babel';
import htmlParser from 'prettier/plugins/html';
const frontmatterRegex = /^---js\n([\s\S]*?)\n---\n/;
function parse(text, options) {
const match = text.match(frontmatterRegex);
if (match) {
const frontmatter = match[1];
const content = text.slice(match[0].length);
return {
type: 'frontmatterDocument',
frontmatter,
content,
};
}
return {
type: 'root',
text: text,
};
}
async function print(path, options, print) {
const node = path.getValue();
if (node.type === 'frontmatterDocument') {
// Ensure babel can interpret the frontmatter by wrapping it as an expression.
const prependedFrontmatter = `(${node.frontmatter})`;
const formattedFrontmatterWithReturn = await prettier.format(
prependedFrontmatter,
{
...options,
parser: 'babel',
plugins: [babelParser],
},
);
// Switch formatted code back to object literal by removing `(` and `);\n`.
const formattedFrontmatterWithoutReturn =
formattedFrontmatterWithReturn.slice(1, -3);
// Format remaining context as HTML
const formattedContent = await prettier.format(node.content, {
...options,
parser: 'html',
plugins: [htmlParser],
});
return `---js\n${formattedFrontmatterWithoutReturn}\n---\n\n${formattedContent}`;
}
// No js frontmatter detected, just format as HTML.
const formattedContent = await prettier.format(node.text, {
...options,
parser: 'html',
plugins: [htmlParser],
});
return formattedContent;
}
export default {
parsers: {
'js-frontmatter': {
parse,
astFormat: 'js-frontmatter',
locStart: () => 0,
locEnd: () => 0,
},
},
printers: {
'js-frontmatter': {
print,
},
},
options: {},
};
/** @type {import('prettier').Config} */
export default {
plugins: ['./prettier-plugin-js-frontmatter.js'],
overrides: [
{
files: '*.webc',
options: {
parser: 'js-frontmatter',
},
},
],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment