astro-custom-embeds
Version:
Astro integration to easily add your own embeds (that replace matching URLs in mdx files)
103 lines (87 loc) • 2.5 kB
text/typescript
import type { AstroConfig, AstroIntegration } from 'astro';
import AutoImport from 'astro-auto-import';
import remarkDirective from 'remark-directive';
import createEmbedPlugin from './remark-plugin.ts';
const importNamespace = 'AuToImPoRtEdAstroCusToMEmbed';
/**
* Embeds can be triggered by a single URL or a directive.
*/
export type EmbedsOption = {
componentName: string;
/**
* path to import component from (default is 'src/components/embeds')
*/
importPath?: string;
/**
* for matching single urls on a single line
* function that should return a string with the argument to pass to the component or undefined if it doesn't match
*
* @param url
* @returns
*/
urlMatcher?: (url: string) => string | undefined | null;
/**
* what argument to pass the url as to the component (default is 'href')
*/
urlArgument?: string;
/**
* for matching a directive, name of the directive, can also be an array of names
*
* @param directive
* @returns
*/
directiveName?: string | string[];
}
/**
* Astro embed MDX integration.
*/
export default function customEmbeds({
embeds = [],
}: {
embeds?: EmbedsOption[]
} = {}) {
const AstroCustomEmbeds: AstroIntegration = {
name: 'astro-custom-embeds',
hooks: {
'astro:config:setup': ({ config, updateConfig }) => {
checkIntegrationsOrder(config);
updateConfig({
markdown: {
remarkPlugins: [
remarkDirective,
createEmbedPlugin({ embeds, importNamespace }),
],
},
});
},
},
};
const imports: Record<string, [string, string][]> = {};
for(const embed of embeds) {
let importPath = embed.importPath ?? 'src/components/embeds';
if(!imports[importPath]) {
imports[importPath] = [];
}
imports[importPath].push([embed.componentName, importNamespace + '_' + embed.componentName]);
}
return [
AutoImport({
imports: [
imports
],
}),
AstroCustomEmbeds,
];
}
function checkIntegrationsOrder({ integrations }: AstroConfig) {
const indexOf = (name: string) =>
integrations.findIndex((i) => i.name === name);
const mdxIndex = indexOf('@astrojs/mdx');
const embedIndex = indexOf('astro-custom-embeds');
if (mdxIndex > -1 && mdxIndex < embedIndex) {
throw new Error(
'MDX integration configured before astro-custom-embeds.\n' +
'Please move `mdx()` after `customEmbeds()` in the `integrations` array in astro.config.ts.'
);
}
}