diff --git a/.changeset/giant-pandas-roll.md b/.changeset/giant-pandas-roll.md new file mode 100644 index 000000000000..e37002d86201 --- /dev/null +++ b/.changeset/giant-pandas-roll.md @@ -0,0 +1,6 @@ +--- +'astro': minor +'@astrojs/markdown-remark': minor +--- + +Makes remark-rehype options available in astro.config.mjs diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 8958605cefca..458fa0fe067a 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -4,6 +4,7 @@ import type { MarkdownRenderingResult, RehypePlugins, RemarkPlugins, + RemarkRehype, ShikiConfig, } from '@astrojs/markdown-remark'; import type * as babel from '@babel/core'; @@ -680,6 +681,23 @@ export interface AstroUserConfig { * ``` */ rehypePlugins?: RehypePlugins; + /** + * @docs + * @name markdown.remarkRehype + * @type {RemarkRehype} + * @description + * Pass options to [remark-rehype](https://github.com/remarkjs/remark-rehype#api) . + * + * ```js + * { + * markdown: { + * // Example: Translate the footnotes text to another language, here are the default English values + * remarkRehype: { footnoteLabel: "Footnotes", footnoteBackLabel: "Back to content"}, + * }, + * }; + * ``` + */ + remarkRehype?: RemarkRehype; }; /** diff --git a/packages/astro/src/core/config.ts b/packages/astro/src/core/config.ts index 094680721946..6b9f83e13601 100644 --- a/packages/astro/src/core/config.ts +++ b/packages/astro/src/core/config.ts @@ -1,4 +1,4 @@ -import type { RehypePlugin, RemarkPlugin } from '@astrojs/markdown-remark'; +import type { RehypePlugin, RemarkPlugin, RemarkRehype } from '@astrojs/markdown-remark'; import type * as Postcss from 'postcss'; import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki'; import type { Arguments as Flags } from 'yargs-parser'; @@ -51,6 +51,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = { }, remarkPlugins: [], rehypePlugins: [], + remarkRehype: {}, }, vite: {}, legacy: { @@ -214,6 +215,10 @@ export const AstroConfigSchema = z.object({ ]) .array() .default(ASTRO_CONFIG_DEFAULTS.markdown.rehypePlugins), + remarkRehype: z + .custom((data) => data instanceof Object && !Array.isArray(data)) + .optional() + .default(ASTRO_CONFIG_DEFAULTS.markdown.remarkRehype), }) .default({}), vite: z diff --git a/packages/astro/test/astro-markdown-remarkRehype.test.js b/packages/astro/test/astro-markdown-remarkRehype.test.js new file mode 100644 index 000000000000..59b0eeda6f15 --- /dev/null +++ b/packages/astro/test/astro-markdown-remarkRehype.test.js @@ -0,0 +1,43 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Astro Markdown without remark-rehype config', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-markdown-remarkRehype/', + }); + await fixture.build(); + }); + it('Renders footnotes with default English labels', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + expect($('#footnote-label').text()).to.equal('Footnotes'); + expect($('.data-footnote-backref').first().attr('aria-label')).to.equal('Back to content'); + }); +}); + +describe('Astro Markdown with remark-rehype config', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-markdown-remarkRehype/', + markdown: { + remarkRehype: { + footnoteLabel: 'Catatan kaki', + footnoteBackLabel: 'Kembali ke konten', + }, + }, + }); + await fixture.build(); + }); + it('Renders footnotes with values from the configuration', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + expect($('#footnote-label').text()).to.equal('Catatan kaki'); + expect($('.data-footnote-backref').first().attr('aria-label')).to.equal('Kembali ke konten'); + }); +}); diff --git a/packages/astro/test/fixtures/astro-markdown-remarkRehype/package.json b/packages/astro/test/fixtures/astro-markdown-remarkRehype/package.json new file mode 100644 index 000000000000..c40b6b91e9cb --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-remarkRehype/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/astro-markdown-remarkRehype", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/astro-markdown-remarkRehype/src/pages/index.md b/packages/astro/test/fixtures/astro-markdown-remarkRehype/src/pages/index.md new file mode 100644 index 000000000000..fa54ca7a6953 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-remarkRehype/src/pages/index.md @@ -0,0 +1,9 @@ +--- +foo: bar +--- + +# Hello world + +This[^1] should be visible. + +[^1]: And there would be a footnote. diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts index a50b3ad19a56..da64a5459902 100644 --- a/packages/markdown/remark/src/index.ts +++ b/packages/markdown/remark/src/index.ts @@ -38,6 +38,7 @@ export async function renderMarkdown( shikiConfig = {}, remarkPlugins = [], rehypePlugins = [], + remarkRehype = {}, isAstroFlavoredMd = false, } = opts; const input = new VFile({ value: content, path: fileURL }); @@ -85,6 +86,7 @@ export async function renderMarkdown( 'mdxTextExpression', ] : [], + ...remarkRehype, }, ], ]); diff --git a/packages/markdown/remark/src/types.ts b/packages/markdown/remark/src/types.ts index 3569e8d04148..bf3d10904d1e 100644 --- a/packages/markdown/remark/src/types.ts +++ b/packages/markdown/remark/src/types.ts @@ -1,6 +1,11 @@ import type * as hast from 'hast'; import type * as mdast from 'mdast'; import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki'; +import type { + Options as RemarkRehypeOptions, + all as Handlers, + one as Handler, +} from 'remark-rehype'; import type * as unified from 'unified'; import type { VFile } from 'vfile'; @@ -20,6 +25,10 @@ export type RehypePlugin = unified.Plugi export type RehypePlugins = (string | [string, any] | RehypePlugin | [RehypePlugin, any])[]; +export type RemarkRehype = Omit & { + handlers: typeof Handlers; +} & { handler: typeof Handler }; + export interface ShikiConfig { langs?: ILanguageRegistration[]; theme?: Theme | IThemeRegistration; @@ -33,6 +42,7 @@ export interface AstroMarkdownOptions { shikiConfig?: ShikiConfig; remarkPlugins?: RemarkPlugins; rehypePlugins?: RehypePlugins; + remarkRehype?: RemarkRehype; } export interface MarkdownRenderingOptions extends AstroMarkdownOptions { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 05e7e4eceada..3a51eacbda84 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1296,6 +1296,12 @@ importers: hast-util-select: 5.0.2 rehype-slug: 5.0.1 + packages/astro/test/fixtures/astro-markdown-remarkRehype: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + packages/astro/test/fixtures/astro-markdown-shiki/langs: specifiers: astro: workspace:*