summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src/frontmatter.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/markdown/remark/src/frontmatter.ts')
-rw-r--r--packages/markdown/remark/src/frontmatter.ts65
1 files changed, 65 insertions, 0 deletions
diff --git a/packages/markdown/remark/src/frontmatter.ts b/packages/markdown/remark/src/frontmatter.ts
index d8828a6fe..60ae0b5da 100644
--- a/packages/markdown/remark/src/frontmatter.ts
+++ b/packages/markdown/remark/src/frontmatter.ts
@@ -1,3 +1,5 @@
+import yaml from 'js-yaml';
+
export function isFrontmatterValid(frontmatter: Record<string, any>) {
try {
// ensure frontmatter is JSON-serializable
@@ -7,3 +9,66 @@ export function isFrontmatterValid(frontmatter: Record<string, any>) {
}
return typeof frontmatter === 'object' && frontmatter !== null;
}
+
+const frontmatterRE = /^---(.*?)^---/ms;
+export function extractFrontmatter(code: string): string | undefined {
+ return frontmatterRE.exec(code)?.[1];
+}
+
+export interface ParseFrontmatterOptions {
+ /**
+ * How the frontmatter should be handled in the returned `content` string.
+ * - `preserve`: Keep the frontmatter.
+ * - `remove`: Remove the frontmatter.
+ * - `empty-with-spaces`: Replace the frontmatter with empty spaces. (preserves sourcemap line/col/offset)
+ * - `empty-with-lines`: Replace the frontmatter with empty line breaks. (preserves sourcemap line/col)
+ *
+ * @default 'remove'
+ */
+ frontmatter: 'preserve' | 'remove' | 'empty-with-spaces' | 'empty-with-lines';
+}
+
+export interface ParseFrontmatterResult {
+ frontmatter: Record<string, any>;
+ rawFrontmatter: string;
+ content: string;
+}
+
+export function parseFrontmatter(
+ code: string,
+ options?: ParseFrontmatterOptions,
+): ParseFrontmatterResult {
+ const rawFrontmatter = extractFrontmatter(code);
+
+ if (rawFrontmatter == null) {
+ return { frontmatter: {}, rawFrontmatter: '', content: code };
+ }
+
+ const parsed = yaml.load(rawFrontmatter);
+ const frontmatter = (parsed && typeof parsed === 'object' ? parsed : {}) as Record<string, any>;
+
+ let content: string;
+ switch (options?.frontmatter ?? 'remove') {
+ case 'preserve':
+ content = code;
+ break;
+ case 'remove':
+ content = code.replace(`---${rawFrontmatter}---`, '');
+ break;
+ case 'empty-with-spaces':
+ content = code.replace(
+ `---${rawFrontmatter}---`,
+ ` ${rawFrontmatter.replace(/[^\r\n]/g, ' ')} `,
+ );
+ break;
+ case 'empty-with-lines':
+ content = code.replace(`---${rawFrontmatter}---`, rawFrontmatter.replace(/[^\r\n]/g, ''));
+ break;
+ }
+
+ return {
+ frontmatter,
+ rawFrontmatter,
+ content,
+ };
+}