summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src/frontmatter-injection.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/markdown/remark/src/frontmatter-injection.ts')
-rw-r--r--packages/markdown/remark/src/frontmatter-injection.ts41
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 };
+ }
+ };
+}