diff options
Diffstat (limited to 'packages/markdown/remark/src/frontmatter-injection.ts')
-rw-r--r-- | packages/markdown/remark/src/frontmatter-injection.ts | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/packages/markdown/remark/src/frontmatter-injection.ts b/packages/markdown/remark/src/frontmatter-injection.ts new file mode 100644 index 000000000..921d01297 --- /dev/null +++ b/packages/markdown/remark/src/frontmatter-injection.ts @@ -0,0 +1,41 @@ +import type { Data, VFile } from 'vfile'; +import type { MarkdownAstroData } from './types.js'; + +function isValidAstroData(obj: unknown): obj is MarkdownAstroData { + if (typeof obj === 'object' && obj !== null && obj.hasOwnProperty('frontmatter')) { + const { frontmatter } = obj as any; + try { + // ensure frontmatter is JSON-serializable + JSON.stringify(frontmatter); + } catch { + return false; + } + return typeof frontmatter === 'object' && frontmatter !== null; + } + return false; +} + +export class InvalidAstroDataError extends TypeError {} + +export function safelyGetAstroData(vfileData: Data): MarkdownAstroData | InvalidAstroDataError { + const { astro } = vfileData; + + if (!astro || !isValidAstroData(astro)) { + return new InvalidAstroDataError(); + } + + return astro; +} + +export function toRemarkInitializeAstroData({ + userFrontmatter, +}: { + userFrontmatter: Record<string, any>; +}) { + return () => + function (tree: any, vfile: VFile) { + if (!vfile.data.astro) { + vfile.data.astro = { frontmatter: userFrontmatter }; + } + }; +} |