diff options
author | 2022-12-22 10:38:03 -0500 | |
---|---|---|
committer | 2022-12-22 10:38:03 -0500 | |
commit | 853081d1c857d8ad8a9634c37ed8fd123d32d241 (patch) | |
tree | 39bbad51f665c2f771fc0d9900656e7d09640b76 /packages/integrations/mdx/src/plugins.ts | |
parent | b64081deed88271a4aa55d66468a10fea235e0a9 (diff) | |
download | astro-853081d1c857d8ad8a9634c37ed8fd123d32d241.tar.gz astro-853081d1c857d8ad8a9634c37ed8fd123d32d241.tar.zst astro-853081d1c857d8ad8a9634c37ed8fd123d32d241.zip |
[Content] Throw on relative image usage (#5648)
* chore: add rel image error plugin
* deps: mdast, mdast types
* chore: add rel image throw to mdx
* refactor: doc rel image path plugin
* fix: respect experimental flag in md remark
* chore: changeset
* deps: remove mdast package
* fix: resolve contentDir from config
* fix: apply MDX plugin after user plugins
* fix: stub out contentDir
Diffstat (limited to 'packages/integrations/mdx/src/plugins.ts')
-rw-r--r-- | packages/integrations/mdx/src/plugins.ts | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/packages/integrations/mdx/src/plugins.ts b/packages/integrations/mdx/src/plugins.ts index d46ab6cd4..a93db383b 100644 --- a/packages/integrations/mdx/src/plugins.ts +++ b/packages/integrations/mdx/src/plugins.ts @@ -1,9 +1,11 @@ import { rehypeHeadingIds } from '@astrojs/markdown-remark'; +import type { Image } from 'mdast'; import { nodeTypes } from '@mdx-js/mdx'; import type { PluggableList } from '@mdx-js/mdx/lib/core.js'; import type { Options as MdxRollupPluginOptions } from '@mdx-js/rollup'; import type { AstroConfig, MarkdownAstroData } from 'astro'; import type { Literal, MemberExpression } from 'estree'; +import { visit } from 'unist-util-visit'; import { visit as estreeVisit } from 'estree-util-visit'; import { bold, yellow } from 'kleur/colors'; import rehypeRaw from 'rehype-raw'; @@ -15,7 +17,8 @@ import { rehypeInjectHeadingsExport } from './rehype-collect-headings.js'; import rehypeMetaString from './rehype-meta-string.js'; import remarkPrism from './remark-prism.js'; import remarkShiki from './remark-shiki.js'; -import { jsToTreeNode } from './utils.js'; +import { jsToTreeNode, isRelativePath } from './utils.js'; +import { pathToFileURL } from 'node:url'; export function recmaInjectImportMetaEnvPlugin({ importMetaEnv, @@ -113,6 +116,34 @@ export function rehypeApplyFrontmatterExport(pageFrontmatter: Record<string, any }; } +/** + * `src/content/` does not support relative image paths. + * This plugin throws an error if any are found + */ +function toRemarkContentRelImageError({ srcDir }: { srcDir: URL }) { + const contentDir = new URL('content/', srcDir); + return function remarkContentRelImageError() { + return (tree: any, vfile: VFile) => { + const isContentFile = pathToFileURL(vfile.path).href.startsWith(contentDir.href); + if (!isContentFile) return; + + const relImagePaths = new Set<string>(); + visit(tree, 'image', function raiseError(node: Image) { + if (isRelativePath(node.url)) { + relImagePaths.add(node.url); + } + }); + if (relImagePaths.size === 0) return; + + const errorMessage = + `Relative image paths are not supported in the content/ directory. Place local images in the public/ directory and use absolute paths (see https://docs.astro.build/en/guides/images/#in-markdown-files):\n` + + [...relImagePaths].map((path) => JSON.stringify(path)).join(',\n'); + + throw new Error(errorMessage); + }; + }; +} + const DEFAULT_REMARK_PLUGINS: PluggableList = [remarkGfm, remarkSmartypants]; const DEFAULT_REHYPE_PLUGINS: PluggableList = []; @@ -146,6 +177,11 @@ export async function getRemarkPlugins( } remarkPlugins = [...remarkPlugins, ...(mdxOptions.remarkPlugins ?? [])]; + + // Apply last in case user plugins resolve relative image paths + if (config.experimental.contentCollections) { + remarkPlugins.push(toRemarkContentRelImageError(config)); + } return remarkPlugins; } |