summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/markdown/remark/src')
-rw-r--r--packages/markdown/remark/src/frontmatter-injection.ts41
-rw-r--r--packages/markdown/remark/src/index.ts5
-rw-r--r--packages/markdown/remark/src/internal.ts5
-rw-r--r--packages/markdown/remark/src/remark-initialize-astro-data.ts9
-rw-r--r--packages/markdown/remark/src/types.ts6
5 files changed, 55 insertions, 11 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 };
+ }
+ };
+}
diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts
index 66889108e..480cc9e38 100644
--- a/packages/markdown/remark/src/index.ts
+++ b/packages/markdown/remark/src/index.ts
@@ -8,7 +8,7 @@ import rehypeIslands from './rehype-islands.js';
import rehypeJsx from './rehype-jsx.js';
import toRemarkContentRelImageError from './remark-content-rel-image-error.js';
import remarkEscape from './remark-escape.js';
-import { remarkInitializeAstroData } from './remark-initialize-astro-data.js';
+import { toRemarkInitializeAstroData } from './frontmatter-injection.js';
import remarkMarkAndUnravel from './remark-mark-and-unravel.js';
import remarkMdxish from './remark-mdxish.js';
import remarkPrism from './remark-prism.js';
@@ -45,13 +45,14 @@ export async function renderMarkdown(
isAstroFlavoredMd = false,
isExperimentalContentCollections = false,
contentDir,
+ frontmatter: userFrontmatter = {},
} = opts;
const input = new VFile({ value: content, path: fileURL });
const scopedClassName = opts.$?.scopedClassName;
let parser = unified()
.use(markdown)
- .use(remarkInitializeAstroData)
+ .use(toRemarkInitializeAstroData({ userFrontmatter }))
.use(isAstroFlavoredMd ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : []);
if (extendDefaultPlugins || (remarkPlugins.length === 0 && rehypePlugins.length === 0)) {
diff --git a/packages/markdown/remark/src/internal.ts b/packages/markdown/remark/src/internal.ts
new file mode 100644
index 000000000..0ab7e34bb
--- /dev/null
+++ b/packages/markdown/remark/src/internal.ts
@@ -0,0 +1,5 @@
+export {
+ InvalidAstroDataError,
+ safelyGetAstroData,
+ toRemarkInitializeAstroData,
+} from './frontmatter-injection.js';
diff --git a/packages/markdown/remark/src/remark-initialize-astro-data.ts b/packages/markdown/remark/src/remark-initialize-astro-data.ts
deleted file mode 100644
index 37af8aeaf..000000000
--- a/packages/markdown/remark/src/remark-initialize-astro-data.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { VFile } from 'vfile';
-
-export function remarkInitializeAstroData() {
- return function (tree: any, vfile: VFile) {
- if (!vfile.data.astro) {
- vfile.data.astro = { frontmatter: {} };
- }
- };
-}
diff --git a/packages/markdown/remark/src/types.ts b/packages/markdown/remark/src/types.ts
index 15465d950..f52fd4bf5 100644
--- a/packages/markdown/remark/src/types.ts
+++ b/packages/markdown/remark/src/types.ts
@@ -11,6 +11,10 @@ import type { VFile } from 'vfile';
export type { Node } from 'unist';
+export type MarkdownAstroData = {
+ frontmatter: Record<string, any>;
+};
+
export type RemarkPlugin<PluginParameters extends any[] = any[]> = unified.Plugin<
PluginParameters,
mdast.Root
@@ -58,6 +62,8 @@ export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
isExperimentalContentCollections?: boolean;
/** Used to prevent relative image imports from `src/content/` */
contentDir: URL;
+ /** Used for frontmatter injection plugins */
+ frontmatter?: Record<string, any>;
}
export interface MarkdownHeading {