astro-custom-embeds
Version:
Astro integration to easily add your own embeds (that replace matching URLs in mdx files)
176 lines (129 loc) • 4.89 kB
Markdown
# Astro Custom Embeds Integration
This Astro integration allows you to easily add custom embeds to your Astro components, that replace URLs (or directives) in `mdx` files with your custom components.
So for example you can replace a YouTube URL with an embedded youtube player, or a Twitter URL with an embedded tweet.
This integration is based on the [astro-embed](https://github.com/delucis/astro-embed) integration by delucis, with the ability to easily add your own custom embeds (and the option to use directives).
> [!WARNING]
> This integration is still in early development and might have some bugs or might change in the future.
## Installation
First, install the integration via npm:
```bash
npm install astro-custom-embeds
```
## Usage
To use the custom embeds integration, add it to your `astro.config.ts` file (**BEFORE** the `mdx` integration):
```ts
import { defineConfig } from 'astro/config';
import customEmbeds from 'astro-custom-embeds';
export default defineConfig({
integrations: [customEmbeds( ...options ), mdx()],
});
```
The `customEmbeds` function takes an options object with the following properties:
```ts
{
embeds: [{
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
*/
urlMatcher?: (url: string) => string | undefined;
/**
* what argument to pass the matched part of 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
*/
directiveName?: string | string[];
}]
}
```
so for example, to replace YouTube URLs with a youtube embed, you could install [`astro-embed`](https://github.com/delucis/astro-embed) and then change your `astro.config.ts` to:
```ts
// returns id of youtube video url or undefined if it's not a youtube url
import youtubeMatcher from '@astro-community/astro-embed-youtube/matcher';
import customEmbeds from 'astro-custom-embeds';
// https://astro.build/config
export default defineConfig({
integrations: [customEmbeds({
embeds: [
{
componentName: 'YouTube',
urlArgument: 'id',
urlMatcher: youtubeMatcher,
importPath: 'astro-embed',
directiveName: 'youtube'
}
]
}), mdx()],
});
```
Then in your `mdx` files you can add a YouTube video by just adding a youtube link (as long as it's on its own line):
```md
https://www.youtube.com/watch?v=dQw4w9WgXcQ
```
Or you can use the `youtube` directive:
```md
:youtube[https://www.youtube.com/watch?v=dQw4w9WgXcQ]
```
## Making your own custom embeds
To make your own custom embeds, you need first a function that takes a URL and returns the argument to pass to the component, or `undefined` if it doesn't match (e.g. by using a regex).
For a simple example, here's a function that matches all `https://` URLs:
```ts
// src/components/urlMatcher.ts
export default function urlMatcher(url: string): string | undefined {
if (url.startsWith('https://')) {
return url;
}
return undefined;
}
```
And a component that renders this URL:
```astro
---
// src/components/Link.astro
const { href } = Astro.props;
---
<a {href}>Click me!</a>
```
You also need to export this component as a named export, recommend is having a `embeds.ts` file in your `src/components` folder, where you export all your embeds:
```ts
// src/components/embeds.ts
export { default as Link } from './Link.astro';
```
Then you can use this in your `astro.config.ts`:
```ts
import urlMatcher from './src/components/urlMatcher';
import customEmbeds from 'astro-custom-embeds';
export default defineConfig({
integrations: [customEmbeds({
embeds: [
{
componentName: 'Link',
urlArgument: 'href', // this is the default
urlMatcher,
importPath: 'src/components/embeds', // this is the default
}
]
}), mdx()],
});
```
Now all paragraphs with just one link in your `mdx` files will be replaced with the `Link` component.
### Notes
- all components must be exported as named exports, so for example these options **WOULD NOT** work:
```ts
{
componentName: 'Link',
urlArgument: 'href',
urlMatcher,
importPath: 'src/components/Link.astro',
}
```
- embeds will process in the order they are defined in the `embeds` array, so if you have multiple embeds that could match the same URL, the first one will be used (so a general URL matcher should always be the last one)
## License
MIT