diff --git a/packages/gatsby-plugin-mdx/package.json b/packages/gatsby-plugin-mdx/package.json index 13adfa1afce92..bf02e6b7d9d14 100644 --- a/packages/gatsby-plugin-mdx/package.json +++ b/packages/gatsby-plugin-mdx/package.json @@ -53,10 +53,12 @@ "change-case": "^4.1.2", "deepmerge": "^4.2.2", "fs-extra": "^10.1.0", - "gatsby-plugin-utils": "^3.10.0-next.1", + "gatsby-plugin-utils": "^3.12.0-next.1", "gray-matter": "^4.0.3", "mdast-util-mdx": "^2.0.0", + "mdast-util-toc": "^6.1.0", "mdast-util-to-markdown": "^1.3.0", + "rehype-infer-description-meta": "^1.0.1", "unified": "^10.1.2", "unist-util-visit": "^4.1.0", "vfile": "^5.3.2" @@ -64,7 +66,8 @@ "devDependencies": { "@babel/cli": "^7.17.10", "@babel/core": "^7.18.2", - "babel-preset-gatsby-package": "^2.16.0-next.0", + "@types/mdast": "^3.0.10", + "babel-preset-gatsby-package": "^2.18.0-next.0", "cross-env": "^7.0.3", "typescript": "^4.7.2" }, diff --git a/packages/gatsby-plugin-mdx/src/compile-mdx.ts b/packages/gatsby-plugin-mdx/src/compile-mdx.ts index bf56331c2a12c..f3130feca4889 100644 --- a/packages/gatsby-plugin-mdx/src/compile-mdx.ts +++ b/packages/gatsby-plugin-mdx/src/compile-mdx.ts @@ -1,27 +1,115 @@ +import deepmerge from "deepmerge" +import type { NodePluginArgs } from "gatsby" import type { ProcessorOptions } from "@mdx-js/mdx" -import type { IFileNode, IMdxNode } from "./types" +import type { IFileNode, IMdxMetadata, IMdxNode } from "./types" + +import { enhanceMdxOptions, IMdxPluginOptions } from "./plugin-options" +import { ERROR_CODES } from "./error-utils" // Compiles MDX into JS -// This could be replaced by @mdx-js/mdx if MDX compile would -// accept custom data passed to the unified pipeline via processor.data() -export default async function compileMDX( - source: string, +// Differences to original @mdx-js/loader: +// * We pass the MDX node and a metadata object to the processor +// * We inject the path to the original mdx file into the VFile which is used by the processor +export async function compileMDX( mdxNode: IMdxNode, fileNode: IFileNode, - options: ProcessorOptions -): Promise { - const { createProcessor } = await import(`@mdx-js/mdx`) - const { VFile } = await import(`vfile`) + options: ProcessorOptions, + reporter: NodePluginArgs["reporter"] +): Promise<{ processedMDX: string; metadata: IMdxMetadata } | null> { + try { + const { createProcessor } = await import(`@mdx-js/mdx`) + const { VFile } = await import(`vfile`) + + const processor = createProcessor(options) + + // Pass required custom data into the processor + const metadata: IMdxMetadata = {} + processor.data(`mdxNode`, mdxNode) + processor.data(`mdxMetadata`, metadata) + + const result = await processor.process( + // Inject path to original file for remark plugins. See: https://github.com/gatsbyjs/gatsby/issues/26914 + new VFile({ value: mdxNode.body, path: fileNode.absolutePath }) + ) - const processor = createProcessor(options) + // Clone metadata so ensure it won't be overridden by later processings + const clonedMetadata = Object.assign( + {}, + processor.data(`mdxMetadata`) as IMdxMetadata + ) + const processedMDX = result.toString() - // If we could pass this via MDX loader config, this whole custom loader might be obsolete. - processor.data(`mdxNode`, mdxNode) + return { processedMDX, metadata: clonedMetadata } + } catch (err) { + const errorMeta = [ + mdxNode.title && `Title: ${mdxNode.title}`, + mdxNode.slug && `Slug: ${mdxNode.slug}`, + fileNode.relativePath && `Path: ${fileNode.relativePath}`, + ] + .filter(Boolean) + .join(`\n`) - const result = await processor.process( - // Inject path to original file for remark plugins. See: https://github.com/gatsbyjs/gatsby/issues/26914 - new VFile({ value: source, path: fileNode.absolutePath }) + reporter.panicOnBuild( + { + id: ERROR_CODES.MdxCompilation, + context: { + errorMeta, + }, + }, + err + ) + return null + } +} + +/** + * This helper function allows you to inject additional plugins and configuration into the MDX + * compilation pipeline. Very useful to create your own resolvers that return custom metadata. + * Internally used to generate the tables of contents and the excerpts. + */ +export const compileMDXWithCustomOptions = async ({ + pluginOptions, + customOptions, + getNode, + getNodesByType, + pathPrefix, + reporter, + cache, + mdxNode, +}: { + pluginOptions: IMdxPluginOptions + customOptions: Partial + getNode: NodePluginArgs["getNode"] + getNodesByType: NodePluginArgs["getNodesByType"] + pathPrefix: string + reporter: NodePluginArgs["reporter"] + cache: NodePluginArgs["cache"] + mdxNode: IMdxNode +}): Promise<{ + processedMDX: string + metadata: IMdxMetadata +} | null> => { + const customPluginOptions = deepmerge( + Object.assign({}, pluginOptions), + customOptions ) - return result.toString() + // Prepare MDX compile + const mdxOptions = await enhanceMdxOptions(customPluginOptions, { + getNode, + getNodesByType, + pathPrefix, + reporter, + cache, + }) + if (!mdxNode.parent) { + return null + } + const fileNode = getNode(mdxNode.parent) + if (!fileNode) { + return null + } + + // Compile MDX and extract metadata + return compileMDX(mdxNode, fileNode, mdxOptions, reporter) } diff --git a/packages/gatsby-plugin-mdx/src/error-utils.ts b/packages/gatsby-plugin-mdx/src/error-utils.ts new file mode 100644 index 0000000000000..93c73e5a5ddbc --- /dev/null +++ b/packages/gatsby-plugin-mdx/src/error-utils.ts @@ -0,0 +1,13 @@ +export const ERROR_CODES = { + MdxCompilation: `10001`, +} + +export const ERROR_MAP = { + [ERROR_CODES.MdxCompilation]: { + text: (context: { errorMeta: string }): string => + `Failed to compile MDX. Information about the file:\n${context.errorMeta}`, + level: `ERROR`, + type: `PLUGIN`, + category: `USER`, + }, +} diff --git a/packages/gatsby-plugin-mdx/src/gatsby-layout-loader.ts b/packages/gatsby-plugin-mdx/src/gatsby-layout-loader.ts index 4d33a00175e71..c7cb142c417ed 100644 --- a/packages/gatsby-plugin-mdx/src/gatsby-layout-loader.ts +++ b/packages/gatsby-plugin-mdx/src/gatsby-layout-loader.ts @@ -4,7 +4,6 @@ import type { Options } from "mdast-util-to-markdown" import type { NodeMap } from "./types" import type { IMdxPluginOptions } from "./plugin-options" -import grayMatter from "gray-matter" import { getOptions } from "loader-utils" export interface IGatsbyLayoutLoaderOptions { @@ -13,7 +12,7 @@ export interface IGatsbyLayoutLoaderOptions { } // Wrap MDX content with Gatsby Layout component -const gatsbyLayoutLoader: LoaderDefinition = async function (source) { +const gatsbyLayoutLoader: LoaderDefinition = async function () { const { options, nodeMap }: IGatsbyLayoutLoaderOptions = getOptions(this) const res = nodeMap.get(this.resourcePath) @@ -24,6 +23,12 @@ const gatsbyLayoutLoader: LoaderDefinition = async function (source) { ) } + if (!res.mdxNode.body) { + throw new Error( + `MDX node is empty: ${JSON.stringify(res.mdxNode, null, 2)}` + ) + } + const { sourceInstanceName } = res.fileNode // Get the default layout for the file source instance group name, @@ -34,12 +39,9 @@ const gatsbyLayoutLoader: LoaderDefinition = async function (source) { // No default layout set? Nothing to do here! if (!layoutPath) { - return source + return res.mdxNode.body } - // Remove frontmatter - const { content } = grayMatter(source) - const { fromMarkdown } = await import(`mdast-util-from-markdown`) const { toMarkdown } = await import(`mdast-util-to-markdown`) @@ -47,7 +49,7 @@ const gatsbyLayoutLoader: LoaderDefinition = async function (source) { const { mdxFromMarkdown, mdxToMarkdown } = await import(`mdast-util-mdx`) // Parse MDX to AST - const tree = fromMarkdown(content, { + const tree = fromMarkdown(res.mdxNode.body, { extensions: [mdxjs()], mdastExtensions: [mdxFromMarkdown()], }) @@ -59,14 +61,13 @@ const gatsbyLayoutLoader: LoaderDefinition = async function (source) { ) if (hasDefaultExport) { - return content + return res.mdxNode.body } tree.children.unshift({ type: `mdxjsEsm` as `text`, value: `import GatsbyMDXLayout from "${layoutPath}"`, }) - tree.children.push({ type: `mdxjsEsm` as `text`, value: `export default GatsbyMDXLayout`, diff --git a/packages/gatsby-plugin-mdx/src/gatsby-mdx-loader.ts b/packages/gatsby-plugin-mdx/src/gatsby-mdx-loader.ts index 07b0314f78842..eaa074030053e 100644 --- a/packages/gatsby-plugin-mdx/src/gatsby-mdx-loader.ts +++ b/packages/gatsby-plugin-mdx/src/gatsby-mdx-loader.ts @@ -1,22 +1,25 @@ /* eslint-disable @babel/no-invalid-this */ -import type { LoaderDefinition } from "webpack" import type { ProcessorOptions } from "@mdx-js/mdx" +import type { NodePluginArgs } from "gatsby" +import type { LoaderDefinition } from "webpack" import type { NodeMap } from "./types" import { getOptions } from "loader-utils" -import compileMDX from "./compile-mdx" +import { compileMDX } from "./compile-mdx" export interface IGatsbyMDXLoaderOptions { options: ProcessorOptions nodeMap: NodeMap + reporter: NodePluginArgs["reporter"] } // Custom MDX Loader that injects the GraphQL MDX node into plugin data // This whole loaded could be replaced by @mdx-js/loader if MDX would // accept custom data passed to the unified pipeline via processor.data() const gatsbyMDXLoader: LoaderDefinition = async function (source) { - const { options, nodeMap }: IGatsbyMDXLoaderOptions = getOptions(this) + const { options, nodeMap, reporter }: IGatsbyMDXLoaderOptions = + getOptions(this) const res = nodeMap.get(this.resourcePath) if (!res) { @@ -25,7 +28,19 @@ const gatsbyMDXLoader: LoaderDefinition = async function (source) { const { mdxNode, fileNode } = res - return compileMDX(source, mdxNode, fileNode, options) + const compileRes = await compileMDX( + // We want to work with the transformed source from our layout plugin + { ...mdxNode, body: source }, + fileNode, + options, + reporter + ) + + if (compileRes && compileRes.processedMDX) { + return compileRes.processedMDX + } + + return source } export default gatsbyMDXLoader diff --git a/packages/gatsby-plugin-mdx/src/gatsby-node.ts b/packages/gatsby-plugin-mdx/src/gatsby-node.ts index de8ce715c2353..75417d934bb85 100644 --- a/packages/gatsby-plugin-mdx/src/gatsby-node.ts +++ b/packages/gatsby-plugin-mdx/src/gatsby-node.ts @@ -1,5 +1,6 @@ import type { GatsbyNode, NodeInput } from "gatsby" import type { FileSystemNode } from "gatsby-source-filesystem" +import type { Options } from "rehype-infer-description-meta" import type { IFileNode, NodeMap } from "./types" import path from "path" @@ -13,8 +14,10 @@ import { IMdxPluginOptions, } from "./plugin-options" import { IGatsbyLayoutLoaderOptions } from "./gatsby-layout-loader" -import compileMDX from "./compile-mdx" +import { compileMDX, compileMDXWithCustomOptions } from "./compile-mdx" import { IGatsbyMDXLoaderOptions } from "./gatsby-mdx-loader" +import remarkInferTocMeta from "./remark-infer-toc-meta" +import { ERROR_MAP } from "./error-utils" /** * Add support for MDX files including using Gatsby layout components @@ -50,6 +53,7 @@ export const onCreateWebpackConfig: GatsbyNode["onCreateWebpackConfig"] = const mdxLoaderOptions: IGatsbyMDXLoaderOptions = { options: mdxOptions, nodeMap, + reporter, } const layoutLoaderOptions: IGatsbyLayoutLoaderOptions = { @@ -119,13 +123,14 @@ export const preprocessSource: GatsbyNode["preprocessSource"] = async ( return undefined } - const code = await compileMDX( - contents, + const compileRes = await compileMDX( { id: ``, children: [], parent: ``, internal: { contentDigest: ``, owner: ``, type: `` }, + body: contents, + rawBody: ``, }, { id: ``, @@ -135,14 +140,21 @@ export const preprocessSource: GatsbyNode["preprocessSource"] = async ( absolutePath: filename, sourceInstanceName: `mocked`, }, - mdxOptions + mdxOptions, + reporter ) - return code.toString() + if (!compileRes?.processedMDX) { + return undefined + } + return compileRes.processedMDX.toString() } export const createSchemaCustomization: GatsbyNode["createSchemaCustomization"] = - async ({ actions, schema }) => { + async ( + { getNode, getNodesByType, pathPrefix, reporter, cache, actions, schema }, + pluginOptions: IMdxPluginOptions + ) => { const { createTypes } = actions const typeDefs = [ schema.buildObjectType({ @@ -155,9 +167,85 @@ export const createSchemaCustomization: GatsbyNode["createSchemaCustomization"] name: `Mdx`, fields: { rawBody: `String!`, + body: `String!`, frontmatter: `MdxFrontmatter!`, slug: `String`, title: `String`, + excerpt: { + type: `String`, + args: { + pruneLength: { + type: `Int`, + defaultValue: 140, + }, + }, + async resolve(mdxNode, { pruneLength }: { pruneLength: number }) { + const rehypeInferDescriptionMeta = ( + await import(`rehype-infer-description-meta`) + ).default + + const descriptionOptions: Options = { truncateSize: pruneLength } + + const result = await compileMDXWithCustomOptions({ + mdxNode, + pluginOptions, + customOptions: { + mdxOptions: { + rehypePlugins: [ + [rehypeInferDescriptionMeta, descriptionOptions], + ], + }, + }, + getNode, + getNodesByType, + pathPrefix, + reporter, + cache, + }) + + if (!result) { + return null + } + + return result.metadata.description + }, + }, + tableOfContents: { + type: `JSON`, + args: { + maxDepth: { + type: `Int`, + default: 6, + }, + }, + async resolve(mdxNode, { maxDepth }) { + const { visit } = await import(`unist-util-visit`) + const { toc } = await import(`mdast-util-toc`) + + const result = await compileMDXWithCustomOptions({ + mdxNode, + pluginOptions, + customOptions: { + mdxOptions: { + remarkPlugins: [ + [remarkInferTocMeta, { visit, toc, maxDepth }], + ], + }, + }, + getNode, + getNodesByType, + pathPrefix, + reporter, + cache, + }) + + if (!result) { + return null + } + + return result.metadata.toc + }, + }, }, interfaces: [`Node`], }), @@ -181,9 +269,9 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async ({ actions: { createNode, createParentChildLink }, createNodeId, }) => { - const content = await loadNodeContent(node) + const rawBody = await loadNodeContent(node) - const { data: frontmatter } = grayMatter(content) + const { data: frontmatter, content: body } = grayMatter(rawBody) // Use slug from frontmatter, otherwise fall back to the file name and path const slug = @@ -200,11 +288,12 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async ({ children: [], parent: node.id, internal: { - content: content, + content: rawBody, type: `Mdx`, contentDigest: node.internal.contentDigest, }, - rawBody: content, + rawBody, + body, slug, title, frontmatter, @@ -226,7 +315,7 @@ export const onCreatePage: GatsbyNode["onCreatePage"] = async ( const ext = path.extname(page.component) // Only apply on pages based on .mdx files and avoid loops - if (extensions.includes(ext) && !page.context.frontmatter) { + if (extensions.includes(ext) && !page.context?.frontmatter) { const content = await fs.readFile(page.component, `utf8`) const { data: frontmatter } = grayMatter(content) @@ -241,6 +330,11 @@ export const onCreatePage: GatsbyNode["onCreatePage"] = async ( } } +export const onPluginInit: GatsbyNode["onPluginInit"] = ({ reporter }) => { + // @ts-ignore - We only expose this type from gatsby-cli and we don't want to import from there + reporter.setErrorMap(ERROR_MAP) +} + /** * Plugin option validation */ diff --git a/packages/gatsby-plugin-mdx/src/get-source-plugins-as-remark-plugins.ts b/packages/gatsby-plugin-mdx/src/get-source-plugins-as-remark-plugins.ts index b6be95c4251b6..9218bcd0a0d0b 100644 --- a/packages/gatsby-plugin-mdx/src/get-source-plugins-as-remark-plugins.ts +++ b/packages/gatsby-plugin-mdx/src/get-source-plugins-as-remark-plugins.ts @@ -1,17 +1,15 @@ import type { ProcessorOptions } from "@mdx-js/mdx" -import type { GatsbyCache, Reporter, NodePluginArgs } from "gatsby" +import type { GatsbyCache, NodePluginArgs } from "gatsby" import type { Pluggable } from "unified" import { IMdxPluginOptions } from "./plugin-options" -import { remarkMdxHtmlPlugin } from "./remark-mdx-html-plugin" -import { pathPlugin } from "./remark-path-prefix-plugin" interface IGetSourcePluginsAsRemarkPlugins { gatsbyRemarkPlugins: IMdxPluginOptions["gatsbyRemarkPlugins"] getNode: NodePluginArgs["getNode"] getNodesByType: NodePluginArgs["getNodesByType"] pathPrefix: NodePluginArgs["pathPrefix"] - reporter: Reporter + reporter: NodePluginArgs["reporter"] cache: GatsbyCache } @@ -30,7 +28,7 @@ export async function getSourcePluginsAsRemarkPlugins({ ) if (!userPluginsFiltered.length) { - return pathPrefix ? [[pathPlugin, { pathPrefix }]] : [] + return [] } const userPlugins = userPluginsFiltered.map(plugin => { @@ -62,9 +60,5 @@ export async function getSourcePluginsAsRemarkPlugins({ return wrappedGatsbyPlugin }) - if (pathPrefix) { - return [[pathPlugin, { pathPrefix }], ...userPlugins, remarkMdxHtmlPlugin] - } else { - return [...userPlugins, remarkMdxHtmlPlugin] - } + return userPlugins } diff --git a/packages/gatsby-plugin-mdx/src/index.ts b/packages/gatsby-plugin-mdx/src/index.ts index 172f1ae6a468c..74012dea0aa5a 100644 --- a/packages/gatsby-plugin-mdx/src/index.ts +++ b/packages/gatsby-plugin-mdx/src/index.ts @@ -1 +1 @@ -// noop +export * from "./compile-mdx" diff --git a/packages/gatsby-plugin-mdx/src/plugin-options.ts b/packages/gatsby-plugin-mdx/src/plugin-options.ts index 14c12561bb903..7451e71656f87 100644 --- a/packages/gatsby-plugin-mdx/src/plugin-options.ts +++ b/packages/gatsby-plugin-mdx/src/plugin-options.ts @@ -1,13 +1,11 @@ import type { ProcessorOptions } from "@mdx-js/mdx" -import type { - PluginOptions, - GatsbyCache, - Reporter, - NodePluginArgs, -} from "gatsby" +import type { PluginOptions, GatsbyCache, NodePluginArgs } from "gatsby" import deepmerge from "deepmerge" import { IPluginRefObject } from "gatsby-plugin-utils/types" import { getSourcePluginsAsRemarkPlugins } from "./get-source-plugins-as-remark-plugins" +import rehypeMdxMetadataExtractor from "./rehype-metadata-extractor" +import { remarkMdxHtmlPlugin } from "./remark-mdx-html-plugin" +import { remarkPathPlugin } from "./remark-path-prefix-plugin" export interface IMdxPluginOptions extends PluginOptions { extensions: [string] @@ -19,7 +17,7 @@ interface IHelpers { getNode: NodePluginArgs["getNode"] getNodesByType: NodePluginArgs["getNodesByType"] pathPrefix: NodePluginArgs["pathPrefix"] - reporter: Reporter + reporter: NodePluginArgs["reporter"] cache: GatsbyCache } type MdxDefaultOptions = (pluginOptions: IMdxPluginOptions) => IMdxPluginOptions @@ -29,6 +27,7 @@ export const defaultOptions: MdxDefaultOptions = pluginOptions => { format: `mdx`, useDynamicImport: true, providerImportSource: `@mdx-js/react`, + jsxRuntime: `classic`, } const options: IMdxPluginOptions = deepmerge( { @@ -53,12 +52,20 @@ export const enhanceMdxOptions: EnhanceMdxOptions = async ( ) => { const options = defaultOptions(pluginOptions) + if (!options.mdxOptions.remarkPlugins) { + options.mdxOptions.remarkPlugins = [] + } + + // Inject Gatsby path prefix if needed + if (helpers.pathPrefix) { + options.mdxOptions.remarkPlugins.push([ + remarkPathPlugin, + { pathPrefix: helpers.pathPrefix }, + ]) + } + // Support gatsby-remark-* plugins if (Object.keys(options.gatsbyRemarkPlugins).length) { - if (!options.mdxOptions.remarkPlugins) { - options.mdxOptions.remarkPlugins = [] - } - // Parser plugins for (const plugin of options.gatsbyRemarkPlugins) { const requiredPlugin = plugin.module @@ -87,5 +94,14 @@ export const enhanceMdxOptions: EnhanceMdxOptions = async ( } } + options.mdxOptions.remarkPlugins.push(remarkMdxHtmlPlugin) + + if (!options.mdxOptions.rehypePlugins) { + options.mdxOptions.rehypePlugins = [] + } + + // Extract metadata generated from by rehype-infer-* and similar plugins + options.mdxOptions.rehypePlugins.push(rehypeMdxMetadataExtractor) + return options.mdxOptions } diff --git a/packages/gatsby-plugin-mdx/src/rehype-metadata-extractor.ts b/packages/gatsby-plugin-mdx/src/rehype-metadata-extractor.ts new file mode 100644 index 0000000000000..a37c677e7ffa5 --- /dev/null +++ b/packages/gatsby-plugin-mdx/src/rehype-metadata-extractor.ts @@ -0,0 +1,16 @@ +import type { Plugin } from "unified" + +/** + * This plugin extracts metadata from the file and stores it + * within the unified processor data for later extraction. + */ +const rehypeMdxMetadataExtractor: Plugin = function () { + const metadata = {} + // eslint-disable-next-line @babel/no-invalid-this + this.data(`mdxMetadata`, metadata) + return (_tree, file): void => { + Object.assign(metadata, file.data.meta) + } +} + +export default rehypeMdxMetadataExtractor diff --git a/packages/gatsby-plugin-mdx/src/remark-infer-toc-meta.ts b/packages/gatsby-plugin-mdx/src/remark-infer-toc-meta.ts new file mode 100644 index 0000000000000..35da1650abe18 --- /dev/null +++ b/packages/gatsby-plugin-mdx/src/remark-infer-toc-meta.ts @@ -0,0 +1,53 @@ +import type { Plugin } from "unified" + +import type { BlockContent, DefinitionContent, ListItem } from "mdast" +import type { IMdxVFile } from "./types" + +type TocNodeType = BlockContent | DefinitionContent | ListItem + +const remarkInferTocMeta: Plugin = (options = { maxDepth: 6 }) => { + const { toc, visit, maxDepth } = options + + const processToC = ( + node: TocNodeType, + current: Partial + ): Partial => { + if (!node) { + return {} + } else if (node.type === `paragraph`) { + visit(node, item => { + if (item.type === `link`) { + current.url = item.url + } + if (item.type === `text`) { + current.title = item.value + } + }) + return current + } else if (Array.isArray(node.children)) { + if (node.type === `list`) { + current.items = node.children.map(i => processToC(i, {})) + return current + } else if (node.type === `listItem`) { + const heading = processToC(node.children[0], {}) + if (node.children.length > 1) { + processToC(node.children[1], heading) + } + return heading + } + } + return {} + } + + return (tree, file): void => { + const generatedToC = toc(tree, { maxDepth }) + const mdxFile: IMdxVFile = file + if (!mdxFile.data.meta) { + mdxFile.data.meta = {} + } + + mdxFile.data.meta.toc = processToC(generatedToC.map, {}) + } +} + +export default remarkInferTocMeta diff --git a/packages/gatsby-plugin-mdx/src/remark-mdx-html-plugin.ts b/packages/gatsby-plugin-mdx/src/remark-mdx-html-plugin.ts index 630dfd0073add..97e34ab759223 100644 --- a/packages/gatsby-plugin-mdx/src/remark-mdx-html-plugin.ts +++ b/packages/gatsby-plugin-mdx/src/remark-mdx-html-plugin.ts @@ -8,7 +8,7 @@ export const remarkMdxHtmlPlugin = () => const { visit } = await import(`unist-util-visit`) visit(markdownAST, node => { - if (node.type !== `html`) { + if (![`html`, `raw`].includes(node.type)) { return } node.type = `mdxJsxFlowElement` diff --git a/packages/gatsby-plugin-mdx/src/remark-path-prefix-plugin.ts b/packages/gatsby-plugin-mdx/src/remark-path-prefix-plugin.ts index defb2e5881b95..b252ed3805a97 100644 --- a/packages/gatsby-plugin-mdx/src/remark-path-prefix-plugin.ts +++ b/packages/gatsby-plugin-mdx/src/remark-path-prefix-plugin.ts @@ -5,7 +5,7 @@ const withPathPrefix = (url: string, pathPrefix: string): string => (pathPrefix + url).replace(/\/\//, `/`) // Ensure relative links include `pathPrefix` -export const pathPlugin = ({ pathPrefix }: { pathPrefix: string }) => +export const remarkPathPlugin = ({ pathPrefix }: { pathPrefix: string }) => async function transformer(markdownAST: Node): Promise { if (!pathPrefix) { return markdownAST diff --git a/packages/gatsby-plugin-mdx/src/types.ts b/packages/gatsby-plugin-mdx/src/types.ts index 9cf4627a81918..2d6afbdbcfadb 100644 --- a/packages/gatsby-plugin-mdx/src/types.ts +++ b/packages/gatsby-plugin-mdx/src/types.ts @@ -1,6 +1,10 @@ +import type { VFile, VFileData } from "vfile" import type { Node } from "gatsby" -export type IMdxNode = Node +export interface IMdxNode extends Node { + rawBody?: string + body?: string +} export interface IFileNode extends Node { sourceInstanceName?: string @@ -8,3 +12,19 @@ export interface IFileNode extends Node { } export type NodeMap = Map + +interface IMdxVFileDataMeta { + [key: string]: unknown +} + +interface IMdxVFileData extends VFileData { + meta?: IMdxVFileDataMeta +} + +export interface IMdxVFile extends VFile { + data: IMdxVFileData +} + +export interface IMdxMetadata { + [key: string]: unknown +} diff --git a/packages/gatsby-remark-autolink-headers/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-autolink-headers/src/__tests__/__snapshots__/index.js.snap index 71e6da32ac43e..42bc6c31b1b05 100644 --- a/packages/gatsby-remark-autolink-headers/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-remark-autolink-headers/src/__tests__/__snapshots__/index.js.snap @@ -6,13 +6,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "heading uno permalink", "class": "anchor before", }, @@ -71,13 +71,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "heading uno permalink", "class": "custom-class before", }, @@ -136,13 +136,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "heading uno permalink", "class": "anchor before", }, @@ -247,13 +247,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "heading uno permalink", "class": "anchor before", }, @@ -328,13 +328,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "heading uno permalink", "class": "anchor after", }, @@ -451,13 +451,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "Heading One permalink", "class": "anchor before", }, @@ -516,13 +516,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "Heading Two permalink", "class": "anchor before", }, @@ -581,13 +581,13 @@ Object { Object { "children": Array [], "data": Object { - "hChildren": Array [ + "children": Array [ Object { "type": "raw", "value": "", }, ], - "hProperties": Object { + "properties": Object { "aria-label": "Heading Three permalink", "class": "anchor before", }, diff --git a/packages/gatsby-remark-autolink-headers/src/__tests__/index.js b/packages/gatsby-remark-autolink-headers/src/__tests__/index.js index 23c439581efd6..e95ecf0b8ff92 100644 --- a/packages/gatsby-remark-autolink-headers/src/__tests__/index.js +++ b/packages/gatsby-remark-autolink-headers/src/__tests__/index.js @@ -249,7 +249,7 @@ describe(`gatsby-remark-autolink-headers`, () => { visit(transformed, `heading`, node => { expect(node.data.hProperties.style).toContain(`position:relative`) expect(node.children).toHaveLength(2) - expect(node.children[1].data.hProperties.class).toContain(`after`) + expect(node.children[1].data.properties.class).toContain(`after`) expect(node).toMatchSnapshot() }) diff --git a/packages/gatsby-remark-autolink-headers/src/index.js b/packages/gatsby-remark-autolink-headers/src/index.js index 8389184e303ad..bdd77cbe57cdc 100644 --- a/packages/gatsby-remark-autolink-headers/src/index.js +++ b/packages/gatsby-remark-autolink-headers/src/index.js @@ -71,11 +71,11 @@ module.exports = ( title: null, children: [], data: { - hProperties: { + properties: { "aria-label": `${label} permalink`, class: `${className} ${isIconAfterHeader ? `after` : `before`}`, }, - hChildren: [ + children: [ { type: `raw`, // The Octicon link icon is the default. But users can set their own icon via the "icon" option. diff --git a/yarn.lock b/yarn.lock index fb8f72a3558e6..d3c2ea757bc12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4937,6 +4937,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/extend@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/extend/-/extend-3.0.1.tgz#923dc2d707d944382433e01d6cc0c69030ab2c75" + integrity sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw== + "@types/fs-extra@^9.0.13": version "9.0.13" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" @@ -4949,6 +4954,11 @@ resolved "https://registry.yarnpkg.com/@types/get-port/-/get-port-3.2.0.tgz#f9e0a11443cc21336470185eae3dfba4495d29bc" integrity sha512-TiNg8R1kjDde5Pub9F9vCwZA/BNW9HeXP5b9j7Qucqncy/McfPZ6xze/EyBdXS5FhMIGN6Fx3vg75l5KHy3V1Q== +"@types/github-slugger@^1.0.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@types/github-slugger/-/github-slugger-1.3.0.tgz#16ab393b30d8ae2a111ac748a015ac05a1fc5524" + integrity sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g== + "@types/glob@*", "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" @@ -5091,6 +5101,13 @@ dependencies: "@types/unist" "*" +"@types/mdast@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + "@types/mdurl@^1.0.0": version "1.0.2" resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" @@ -6873,23 +6890,6 @@ babel-preset-fbjs@^3.4.0: "@babel/plugin-transform-template-literals" "^7.0.0" babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" -babel-preset-gatsby-package@^2.16.0-next.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/babel-preset-gatsby-package/-/babel-preset-gatsby-package-2.17.0.tgz#332ed5b14ab2083c5412e40d762b3364a655c47a" - integrity sha512-t7BtwAFz3kUujHsPZ6DAvVvZEfljbTgGzihKGnV8GWsIeD7MRIBfaJK8j00s2dm+t4OtmH5HNrwGNjORL8ibZw== - dependencies: - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.15.0" - "@babel/plugin-transform-typescript" "^7.15.4" - "@babel/preset-env" "^7.15.4" - "@babel/preset-flow" "^7.14.0" - "@babel/preset-react" "^7.14.0" - "@babel/runtime" "^7.15.4" - babel-plugin-dynamic-import-node "^2.3.3" - core-js "^3.22.3" - babel-preset-jest@^27.4.0: version "27.4.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz#70d0e676a282ccb200fbabd7f415db5fdf393bca" @@ -6972,6 +6972,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +bcp-47-match@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.2.tgz#3323e221eb5b40ddc3b91ed29d847ab459d549c4" + integrity sha512-zy5swVXwQ25ttElhoN9Dgnqm6VFlMkeDNljvHSGqGNr4zClUosdFzxD+fQHJVmx3g3KY+r//wV/fmBHsa1ErnA== + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -9905,6 +9910,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +direction@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz#71800dd3c4fa102406502905d3866e65bdebb985" + integrity sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA== + dns-packet@^5.1.2: version "5.2.1" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.2.1.tgz#26cec0be92252a1b97ed106482921192a7e08f72" @@ -12049,52 +12059,6 @@ gather-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gather-stream/-/gather-stream-1.0.0.tgz#b33994af457a8115700d410f317733cbe7a0904b" -gatsby-core-utils@^3.17.0: - version "3.17.0" - resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.17.0.tgz#5fe33c4267a3d0a7439b8065ee9c16f5cc2aead1" - integrity sha512-1e0YaqTAEpSSBkpWkY703lu+Bl76ASXUvUcpnNO3CavCYZsRQxAXtMXIKIEvhm1z6zWJmY9HILo6/DjP+PHeyw== - dependencies: - "@babel/runtime" "^7.15.4" - ci-info "2.0.0" - configstore "^5.0.1" - fastq "^1.13.0" - file-type "^16.5.3" - fs-extra "^10.1.0" - got "^11.8.3" - import-from "^4.0.0" - lmdb "2.5.2" - lock "^1.1.0" - node-object-hash "^2.3.10" - proper-lockfile "^4.1.2" - resolve-from "^5.0.0" - tmp "^0.2.1" - xdg-basedir "^4.0.0" - -gatsby-plugin-utils@^3.10.0-next.1: - version "3.11.0" - resolved "https://registry.yarnpkg.com/gatsby-plugin-utils/-/gatsby-plugin-utils-3.11.0.tgz#cffbd98ab0cafe2ff9b8eb513c980024605dcadf" - integrity sha512-v2D6O2aME9p7tqlGykq5mgtj7Jqp/CWatgo0zJ7bFWSYPPUpQ7jRVAph1PIgFTAV/CaUrrvt9sxdRaZrglJyug== - dependencies: - "@babel/runtime" "^7.15.4" - "@gatsbyjs/potrace" "^2.2.0" - fs-extra "^10.1.0" - gatsby-core-utils "^3.17.0" - gatsby-sharp "^0.11.0" - graphql-compose "^9.0.7" - import-from "^4.0.0" - joi "^17.4.2" - mime "^3.0.0" - mini-svg-data-uri "^1.4.4" - svgo "^2.8.0" - -gatsby-sharp@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/gatsby-sharp/-/gatsby-sharp-0.11.0.tgz#f672e26a4134e2ff264a335ab6efd35782de8052" - integrity sha512-RIbU8qi/Qs7G/KJiY0zyGS9Yic5n4RpDUf/1W3gvRl78Uo3LSuIeGEpaai6mYEnreuGb5fQIcqdkYs/UV3e8WA== - dependencies: - "@types/sharp" "^0.30.0" - sharp "^0.30.3" - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -13029,6 +12993,14 @@ hast-to-hyperscript@^9.0.0: unist-util-is "^4.0.0" web-namespaces "^1.0.0" +hast-util-excerpt@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/hast-util-excerpt/-/hast-util-excerpt-1.0.1.tgz#6d32dbcde8d945c6ddb0a4b204f9a78018fcc175" + integrity sha512-N7NO08ie0IwJGCRbSkbCUGGlWK5FN80BvYtty+6PEzm14D+gNxR/h+S4ZMqkSFge7yhiFyARPWBGkonuDRNN4w== + dependencies: + "@types/hast" "^2.0.0" + hast-util-truncate "^1.0.0" + hast-util-from-parse5@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.0.tgz#b38793c81e1a99f5fd592a4a88fc2731dccd0f30" @@ -13041,10 +13013,23 @@ hast-util-from-parse5@^6.0.0: vfile "^4.0.0" web-namespaces "^1.0.0" +hast-util-has-property@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.0.tgz#c15cd6180f3e535540739fcc9787bcffb5708cae" + integrity sha512-4Qf++8o5v14us4Muv3HRj+Er6wTNGA/N9uCaZMty4JWvyFKLdhULrv4KE1b65AthsSO9TXSZnjuxS8ecIyhb0w== + hast-util-is-element@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.0.1.tgz#c76e8aafbdb6e5c83265bf50324e2f2e024eb12a" +hast-util-is-element@^2.0.0: + version "2.1.2" + resolved "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.2.tgz#fc0b0dc7cef3895e839b8d66979d57b0338c68f3" + integrity sha512-thjnlGAnwP8ef/GSO1Q8BfVk2gundnc2peGQqEg2kUt/IqesiGg/5mSwN2fE7nLzy61pg88NG6xV+UrGOrx9EA== + dependencies: + "@types/hast" "^2.0.0" + "@types/unist" "^2.0.0" + hast-util-parse-selector@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.0.tgz#2175f18cdd697308fc3431d5c29a9e48dfa4817a" @@ -13071,6 +13056,28 @@ hast-util-sanitize@^1.0.0: dependencies: xtend "^4.0.1" +hast-util-select@^5.0.0: + version "5.0.2" + resolved "https://registry.npmjs.org/hast-util-select/-/hast-util-select-5.0.2.tgz#8c603ebacf0f47e154c5fa2e5b7efc520813866b" + integrity sha512-QGN5o7N8gq1BhUX96ApLE8izOXlf+IPkOVGXcp9Dskdd3w0OqZrn6faPAmS0/oVogwJOd0lWFSYmBK75e+030g== + dependencies: + "@types/hast" "^2.0.0" + "@types/unist" "^2.0.0" + bcp-47-match "^2.0.0" + comma-separated-tokens "^2.0.0" + css-selector-parser "^1.0.0" + direction "^2.0.0" + hast-util-has-property "^2.0.0" + hast-util-is-element "^2.0.0" + hast-util-to-string "^2.0.0" + hast-util-whitespace "^2.0.0" + not "^0.1.0" + nth-check "^2.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + unist-util-visit "^4.0.0" + zwitch "^2.0.0" + hast-util-to-estree@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.0.2.tgz#79c5bf588915610b3f0d47ca83a74dc0269c7dc2" @@ -13133,6 +13140,30 @@ hast-util-to-parse5@^6.0.0: xtend "^4.0.0" zwitch "^1.0.0" +hast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz#b008b0a4ea472bf34dd390b7eea1018726ae152a" + integrity sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A== + dependencies: + "@types/hast" "^2.0.0" + +hast-util-to-text@^3.0.0: + version "3.1.1" + resolved "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.1.tgz#b7699a75f7a61af6e0befb67660cd78460d96dc6" + integrity sha512-7S3mOBxACy8syL45hCn3J7rHqYaXkxRfsX6LXEU5Shz4nt4GxdjtMUtG+T6G/ZLUHd7kslFAf14kAN71bz30xA== + dependencies: + "@types/hast" "^2.0.0" + hast-util-is-element "^2.0.0" + unist-util-find-after "^4.0.0" + +hast-util-truncate@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/hast-util-truncate/-/hast-util-truncate-1.0.1.tgz#38e3566c9de95d840c939fdd5dfcec3e93f17811" + integrity sha512-7xT0sShgZiDhSn8K/ZTvpUUOdBqZ8ZnyW35pIzFyT9c+3WxDdDr9oMRwwyMZrA5sTdm/Cv/OnPPiMp1Uu+Bf+g== + dependencies: + "@types/hast" "^2.0.0" + micromark-util-character "^1.0.0" + hast-util-whitespace@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.1.tgz#d67da2c87637b1ce1d85dd15b270ba057930149a" @@ -17046,6 +17077,20 @@ mdast-util-toc@^5.1.0: unist-util-is "^4.0.0" unist-util-visit "^2.0.0" +mdast-util-toc@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-toc/-/mdast-util-toc-6.1.0.tgz#1f38419f5ce774449c8daa87b39a4d940b24be7c" + integrity sha512-0PuqZELXZl4ms1sF7Lqigrqik4Ll3UhbI+jdTrfw7pZ9QPawgl7LD4GQ8MkU7bT/EwiVqChNTbifa2jLLKo76A== + dependencies: + "@types/extend" "^3.0.0" + "@types/github-slugger" "^1.0.0" + "@types/mdast" "^3.0.0" + extend "^3.0.0" + github-slugger "^1.0.0" + mdast-util-to-string "^3.1.0" + unist-util-is "^5.0.0" + unist-util-visit "^3.0.0" + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -21494,6 +21539,19 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" +rehype-infer-description-meta@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/rehype-infer-description-meta/-/rehype-infer-description-meta-1.0.1.tgz#2c1c133903bbaf0b294f2731beebb5f80643c386" + integrity sha512-aVYXhbclzkLjbStqsz9z7Wbh4ZYBJrHuKgqRfsIEJeoZJABHvknfRs+1UIXqoyG9zhPSEi0zjeWemPu00BmuLA== + dependencies: + "@types/hast" "^2.0.0" + hast-util-excerpt "^1.0.0" + hast-util-select "^5.0.0" + hast-util-to-text "^3.0.0" + hast-util-truncate "^1.0.0" + unified "^10.0.0" + unist-util-remove-position "^4.0.0" + rehype-parse@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57" @@ -25668,6 +25726,14 @@ unist-util-find-after@^3.0.0: dependencies: unist-util-is "^4.0.0" +unist-util-find-after@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-4.0.0.tgz#1101cebf5fed88ae3c6f3fa676e86fd5772a4f32" + integrity sha512-gfpsxKQde7atVF30n5Gff2fQhAc4/HTOV4CvkXpTg9wRfQhZWdXitpyXHWB6YcYgnsxLx+4gGHeVjCTAAp9sjw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-find@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unist-util-find/-/unist-util-find-1.0.2.tgz#4d5b01a69fca2a382ad4f55f9865e402129ecf56"