Open jonsage opened 1 year ago
Interesting idea! Might be possible I think. What do you think the API could look like? I guess we’d need a way to know what HTML elements an auto-imported component should map to.
Something like this:
integrations: [
AutoImport({
imports: [
{
blockquote: "@/components/MDXquote.astro"
},
],
}),
mdx(),
],
Interesting idea! Might be possible I think. What do you think the API could look like? I guess we’d need a way to know what HTML elements an auto-imported component should map to.
This is a bit new to me, but something I'm an interested to see working to streamline working with MDX - AutoImport already helps a lot with that - it might even make a great "built-in" feature of Astro in the future tbh.
So, my naive ideas to avoid breaking changes:
integrations: [
AutoImport({
imports: [
{
// third item named export
'./src/components/Link.astro': [['default', 'Link', 'a']],
},
// OR
{
// second item config object
'./src/components/Link.astro': [['default', { import_as: 'Link', export_as: 'a' }]],
},
]
}),
// OR (in a future ideal world)
mdx({
components: {
a: 'Link',
// OR (to avoid having to previously AutoImport)
h1: './src/components/Heading.astro',
// OR (to avoid having to previously AutoImport, and import a named export)
p: ['./src/components/Paragraph.astro', 'default']
}
}),
]
Also, I found this issue https://github.com/orgs/mdx-js/discussions/2271
EDIT: just adding the link to the existing mdx()
integration config object https://docs.astro.build/en/guides/integrations-guide/mdx/#options-inherited-from-markdown-config
Hey @delucis, sorry for the ping, but I've been researching this issue all day and your name keeps coming up when it comes to Astro and MDX.
I'm the creator and core maintainer for Skeleton: https://www.skeleton.dev/
We're currently porting our doc site to Astro and really interested in the prospect of custom HTML components in MDX: https://docs.astro.build/en/guides/markdown-content/#assigning-custom-components-to-html-elements
The reason being, we use semantic utility classes to assign all our typography styles: https://www.skeleton.dev/elements/typography
<h1 class="h1">Skeleton H1</h1>
<a class="anchor" href="/">Anchor</a>
<blockquote class="blockquote">Skeleton</blockquote>
Because of this, we'll have dozens of doc pages that will require replacing the MDX output elements. So far, the cleanest solution I've come up with is doing something like this:
/pages/**/index.mdx
---
---
import componentSet from '@components/mdx/index'; // index.ts
export const components = componentSet;
/components/mdx/index.ts
import Blockquote from './Blockquote.astro';
// ...(repeat for every component)...
export const componentSet = {
blockquote: Blockquote,
// ...(repeat for every component)...
};
export default componentSet;
I've come across your astro-auto-import
tool here. While this can remove one of the two lines per page, that still leave room for error if someone misses this.
So I was curious if you're aware of any movement on the proposal from @jonsage above, or have any sage advice on how I might approach this. Thanks in advance!
So I was curious if you're aware of any movement on the proposal from @jonsage above, or have any sage advice on how I might approach this. Thanks in advance!
A couple of people expressed interest in submitting PRs, but nothing has materialised just yet. But I’d be happy to guide a PR if you’re up for trying to implement it!
As a pointer, like you show, we’d need a way to generate the export const components = {};
statement and auto import any required components.
I’d suggest a config API something like:
AutoImport({
imports: [
// as currently supported, an array of auto-imported components
],
// a map of components, more or less 1:1 with what ends up in MDX’s `components` export:
defaultComponents: {
// quick syntax for default exports
p: './src/CustomParagraph.astro',
// some kind of syntax for named exports?
blockquote: { name: 'CustomBlockquote', from: './src/Components.ts' },
},
});
Internally we’d then need to build this into a string like:
import p from './src/CustomParagraph.astro';
import { CustomBlockquote as blockquote } from './src/Components.ts';
export const components = {
p,
blockquote,
};
A corner case that would need checking would be making sure we don’t have name clashes with anything in import
I guess. Or alternatively we insure against that with some namespacing like:
import AUTO_IMPORT_p from './src/CustomParagraph.astro';
import { CustomBlockquote as AUTO_IMPORT_blockquote } from './src/Components.ts';
export const components = {
p: AUTO_IMPORT_p,
blockquote: AUTO_IMPORT_blockquote,
};
And inject these imports much like we already do.
Kizu wrote this https://blog.kizu.dev/astro-mdx-components/ and I recommend he take a look at your integration to simplify things, however the part I think your integration doesn't handle when it comes to overriding default HTML elements in MDX is the export step.
I was wondering whether it would be simple to extend functionality to AutoImport to both import and re-export components for MDX and this way it would possible to provide overrides for HTML elements like
<a>
and<h1>
etc.