Update Markdown type signature to match behavior (#4423)

* feat: "file" and "url" top-level layout props

* test: markdown file and url

* test: mdx file and url

* feat: update MarkdownInstance + JSDoc improvements

* chore: changeset
This commit is contained in:
Ben Holmes 2022-08-25 17:08:43 -04:00 committed by GitHub
parent 9cff515318
commit d4cd7a59fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 15 deletions

View file

@ -0,0 +1,6 @@
---
'astro': minor
'@astrojs/mdx': patch
---
Update Markdown type signature to match new markdown plugin,and update top-level layout props for better alignment

View file

@ -884,32 +884,29 @@ export interface AstroInstance {
export interface MarkdownInstance<T extends Record<string, any>> {
frontmatter: T;
/** Absolute file path (e.g. `/home/user/projects/.../file.md`) */
file: string;
/** Browser URL for files under `/src/pages` (e.g. `/en/guides/markdown-content`) */
url: string | undefined;
/** Component to render content in `.astro` files. Usage: `<Content />` */
Content: AstroComponentFactory;
/** raw Markdown file content, excluding frontmatter */
/** raw Markdown file content, excluding layout HTML and YAML frontmatter */
rawContent(): string;
/** Markdown file compiled to valid Astro syntax. Queryable with most HTML parsing libraries */
compiledContent(): Promise<string>;
getHeadings(): Promise<MarkdownHeading[]>;
/** Markdown file compiled to HTML, excluding layout HTML */
compiledContent(): string;
/** List of headings (h1 -> h6) with associated metadata */
getHeadings(): MarkdownHeading[];
/** @deprecated Renamed to `getHeadings()` */
getHeaders(): void;
default: () => Promise<{
metadata: MarkdownMetadata;
frontmatter: MarkdownContent<T>;
$$metadata: Metadata;
default: AstroComponentFactory;
}>;
default: AstroComponentFactory;
}
export interface MDXInstance<T>
extends Omit<MarkdownInstance<T>, 'rawContent' | 'compiledContent' | 'Content' | 'default'> {
extends Omit<MarkdownInstance<T>, 'rawContent' | 'compiledContent'> {
/** MDX does not support rawContent! If you need to read the Markdown contents to calculate values (ex. reading time), we suggest injecting frontmatter via remark plugins. Learn more on our docs: https://docs.astro.build/en/guides/integrations-guide/mdx/#inject-frontmatter-via-remark-or-rehype-plugins */
rawContent: never;
/** MDX does not support compiledContent! If you need to read the HTML contents to calculate values (ex. reading time), we suggest injecting frontmatter via rehype plugins. Learn more on our docs: https://docs.astro.build/en/guides/integrations-guide/mdx/#inject-frontmatter-via-remark-or-rehype-plugins */
compiledContent: never;
default: AstroComponentFactory;
Content: AstroComponentFactory;
}
export interface MarkdownLayoutProps<T extends Record<string, any>> {
@ -917,6 +914,8 @@ export interface MarkdownLayoutProps<T extends Record<string, any>> {
file: MarkdownInstance<T>['file'];
url: MarkdownInstance<T>['url'];
} & T;
file: MarkdownInstance<T>['file'];
url: MarkdownInstance<T>['url'];
headings: MarkdownHeading[];
rawContent: MarkdownInstance<T>['rawContent'];
compiledContent: MarkdownInstance<T>['compiledContent'];

View file

@ -106,6 +106,8 @@ export default function markdown({ config, logging }: AstroPluginOptions): Plugi
return ${
layout
? `h(Layout, {
file,
url,
content,
frontmatter: content,
headings: getHeadings(),

View file

@ -118,6 +118,24 @@ describe('Astro Markdown', () => {
expect(headingSlugs).to.contain('section-2');
});
it('passes "file" and "url" to layout', async () => {
const html = await fixture.readFile('/with-layout/index.html');
const $ = cheerio.load(html);
const frontmatterFile = $('[data-frontmatter-file]')?.text();
const frontmatterUrl = $('[data-frontmatter-url]')?.text();
const file = $('[data-file]')?.text();
const url = $('[data-url]')?.text();
expect(frontmatterFile?.endsWith('with-layout.md')).to.equal(
true,
'"file" prop does not end with correct path or is undefined'
);
expect(frontmatterUrl).to.equal('/with-layout');
expect(file).to.equal(frontmatterFile);
expect(url).to.equal(frontmatterUrl);
});
describe('Vite env vars (#3412)', () => {
it('Allows referencing import.meta.env in content', async () => {
const html = await fixture.readFile('/vite-env-vars/index.html');

View file

@ -1,7 +1,13 @@
---
const {
content = { title: "content didn't work" },
frontmatter = { title: "frontmatter didn't work" },
file = "file didn't work",
url = "url didn't work",
frontmatter = {
title: "frontmatter didn't work",
file: "file didn't work",
url: "url didn't work",
},
headings = [],
compiledContent = () => '',
rawContent = () => '',
@ -21,6 +27,10 @@ const {
<p data-content-title>{content.title}</p>
<p data-frontmatter-title>{frontmatter.title}</p>
<p data-compiled-content>{compiledContent()}</p>
<p data-frontmatter-file>{frontmatter.file}</p>
<p data-frontmatter-url>{frontmatter.url}</p>
<p data-file>{frontmatter.file}</p>
<p data-url>{frontmatter.url}</p>
<p data-raw-content>{rawContent()}</p>
<p data-layout-rendered>Layout rendered!</p>
<ul data-headings>

View file

@ -51,6 +51,8 @@ export function rehypeApplyFrontmatterExport(pageFrontmatter: Record<string, any
}
});
return layoutJsx(Layout, {
file,
url,
content,
frontmatter: content,
headings: getHeadings(),

View file

@ -1,6 +1,8 @@
---
const {
content = { title: "content didn't work" },
file = "file didn't work",
url = "url didn't work",
frontmatter = {
title: "frontmatter didn't work",
file: "file didn't work",
@ -24,6 +26,8 @@ const {
<p data-frontmatter-title>{frontmatter.title}</p>
<p data-frontmatter-file>{frontmatter.file}</p>
<p data-frontmatter-url>{frontmatter.url}</p>
<p data-file>{frontmatter.file}</p>
<p data-url>{frontmatter.url}</p>
<p data-layout-rendered>Layout rendered!</p>
<ul data-headings>
{headings.map(heading => <li>{heading.slug}</li>)}

View file

@ -57,17 +57,21 @@ describe('MDX frontmatter', () => {
expect(headingSlugs).to.contain('section-2');
});
it('passes "file" and "url" to layout via frontmatter', async () => {
it('passes "file" and "url" to layout', async () => {
const html = await fixture.readFile('/with-headings/index.html');
const { document } = parseHTML(html);
const frontmatterFile = document.querySelector('[data-frontmatter-file]')?.textContent;
const frontmatterUrl = document.querySelector('[data-frontmatter-url]')?.textContent;
const file = document.querySelector('[data-file]')?.textContent;
const url = document.querySelector('[data-url]')?.textContent;
expect(frontmatterFile?.endsWith('with-headings.mdx')).to.equal(
true,
'"file" prop does not end with correct path or is undefined'
);
expect(frontmatterUrl).to.equal('/with-headings');
expect(file).to.equal(frontmatterFile);
expect(url).to.equal(frontmatterUrl);
});
});