diff options
author | 2021-08-25 14:17:45 +0200 | |
---|---|---|
committer | 2021-08-25 08:17:45 -0400 | |
commit | 397d8f3d842e7e17d29c4f7862b6639f34f6a2e4 (patch) | |
tree | 3b7c98e31719d7116aa37052dee37acf8178b760 /packages/markdown-support | |
parent | 3bfd8c125e57879f6d0d3a828943a16199c8fb9c (diff) | |
download | astro-397d8f3d842e7e17d29c4f7862b6639f34f6a2e4.tar.gz astro-397d8f3d842e7e17d29c4f7862b6639f34f6a2e4.tar.zst astro-397d8f3d842e7e17d29c4f7862b6639f34f6a2e4.zip |
Upgrade unified deps and improve unified plugins types (#1200)
* Upgrade @astrojs/markdown-support deps and update types
* Add changeset
* Update changeset
* Switch astro-markdown-plugins example to use rehype-autolink-headings
Usage of remark-autolink-headings is discouraged in favor of the rehype counterpart: https://github.com/remarkjs/remark-autolink-headings\#remark-autolink-headings
* Add stricter types for unified plugins
This includes a few suggestions from a code review:
- use vfile.toString instead of vfile.value.toString
- refactor plugins to follow unified best practices instead of returning functions that return a plugin
- use any instead of any[] for plugin options types
* Narrow down types to more specific hast or mdast typings
Diffstat (limited to 'packages/markdown-support')
-rw-r--r-- | packages/markdown-support/package.json | 22 | ||||
-rw-r--r-- | packages/markdown-support/src/codeblock.ts | 58 | ||||
-rw-r--r-- | packages/markdown-support/src/index.ts | 8 | ||||
-rw-r--r-- | packages/markdown-support/src/load-plugins.ts | 2 | ||||
-rw-r--r-- | packages/markdown-support/src/rehype-collect-headers.ts | 53 | ||||
-rw-r--r-- | packages/markdown-support/src/types.ts | 2 |
6 files changed, 76 insertions, 69 deletions
diff --git a/packages/markdown-support/package.json b/packages/markdown-support/package.json index b927c2a9d..fc9563340 100644 --- a/packages/markdown-support/package.json +++ b/packages/markdown-support/package.json @@ -19,19 +19,19 @@ "dependencies": { "@silvenon/remark-smartypants": "^1.0.0", "github-slugger": "^1.3.0", - "gray-matter": "^4.0.2", - "mdast-util-mdx-expression": "^1.0.0", + "gray-matter": "^4.0.3", + "mdast-util-mdx-expression": "^1.1.0", "micromark-extension-mdx-expression": "^1.0.0", - "rehype-raw": "^5.1.0", - "rehype-stringify": "^8.0.0", - "remark-footnotes": "^3.0.0", - "remark-gfm": "^1.0.0", - "remark-parse": "^9.0.0", - "remark-rehype": "^8.1.0", - "remark-slug": "^6.1.0", - "unified": "^9.2.1", + "rehype-raw": "^6.0.0", + "rehype-stringify": "^9.0.1", + "remark-footnotes": "^4.0.1", + "remark-gfm": "^2.0.0", + "remark-parse": "^10.0.0", + "remark-rehype": "^9.0.0", + "remark-slug": "^7.0.0", + "unified": "^10.1.0", "unist-util-map": "^3.0.0", - "unist-util-visit": "^3.1.0" + "unist-util-visit": "^4.0.0" }, "devDependencies": { "@types/github-slugger": "^1.3.0" diff --git a/packages/markdown-support/src/codeblock.ts b/packages/markdown-support/src/codeblock.ts index 3f3e8237c..32adc0151 100644 --- a/packages/markdown-support/src/codeblock.ts +++ b/packages/markdown-support/src/codeblock.ts @@ -1,43 +1,43 @@ import { visit } from 'unist-util-visit'; +import type { Element, Root as HastRoot, Properties } from 'hast'; +import type { Root as MdastRoot } from 'mdast'; /** */ export function remarkCodeBlock() { - const visitor = (node: any) => { - const { data, meta } = node; - let lang = node.lang || 'html'; // default to html matches GFM behavior. + return function (tree: MdastRoot) { + visit(tree, 'code', (node) => { + const { data, meta } = node; + let lang = node.lang || 'html'; // default to html to match GFM behavior. - let currentClassName = data?.hProperties?.class ?? ''; - node.data = node.data || {}; - node.data.hProperties = node.data.hProperties || {}; - node.data.hProperties = { ...node.data.hProperties, class: `language-${lang} ${currentClassName}`.trim(), lang, meta }; - - return node; + let currentClassName = (data?.hProperties as Properties)?.class ?? ''; + node.data = node.data || {}; + node.data.hProperties = node.data.hProperties || {}; + node.data.hProperties = { ...(node.data.hProperties as Properties), class: `language-${lang} ${currentClassName}`.trim(), lang, meta }; + }); }; - return () => (tree: any) => visit(tree, 'code', visitor); } /** */ export function rehypeCodeBlock() { - const escapeCode = (code: any) => { - code.children = code.children.map((child: any) => { - if (child.type === 'text') { - return { ...child, value: child.value.replace(/\{/g, 'ASTRO_ESCAPED_LEFT_CURLY_BRACKET\0') }; + return function (tree: HastRoot) { + const escapeCode = (code: Element): void => { + code.children = code.children.map((child) => { + if (child.type === 'text') { + return { ...child, value: child.value.replace(/\{/g, 'ASTRO_ESCAPED_LEFT_CURLY_BRACKET\0') }; + } + return child; + }); + }; + visit(tree, 'element', (node) => { + if (node.tagName === 'code') { + escapeCode(node); + return; } - return child; - }); - }; - const visitor = (node: any) => { - if (node.tagName === 'code') { - escapeCode(node); - return; - } - - if (node.tagName !== 'pre') return; - const code = node.children[0]; - if (code.tagName !== 'code') return; - node.properties = { ...code.properties }; - return node; + if (node.tagName !== 'pre') return; + const code = node.children[0]; + if (code.type !== 'element' || code.tagName !== 'code') return; + node.properties = { ...code.properties }; + }); }; - return () => (tree: any) => visit(tree, 'element', visitor); } diff --git a/packages/markdown-support/src/index.ts b/packages/markdown-support/src/index.ts index 86d95a414..4973da7f9 100644 --- a/packages/markdown-support/src/index.ts +++ b/packages/markdown-support/src/index.ts @@ -8,7 +8,7 @@ import { remarkCodeBlock, rehypeCodeBlock } from './codeblock.js'; import { loadPlugins } from './load-plugins.js'; import raw from 'rehype-raw'; -import unified from 'unified'; +import { unified } from 'unified'; import markdown from 'remark-parse'; import markdownToHtml from 'remark-rehype'; import rehypeStringify from 'rehype-stringify'; @@ -56,7 +56,7 @@ export async function renderMarkdown(content: string, opts?: MarkdownRenderingOp parser.use(scopedStyles(scopedClassName)); } - parser.use(remarkCodeBlock()); + parser.use(remarkCodeBlock); parser.use(markdownToHtml, { allowDangerousHtml: true, passThrough: ['raw', 'mdxTextExpression'] }); parser.use(rehypeExpressions); @@ -69,10 +69,10 @@ export async function renderMarkdown(content: string, opts?: MarkdownRenderingOp const vfile = await parser .use(raw) .use(rehypeCollectHeaders) - .use(rehypeCodeBlock()) + .use(rehypeCodeBlock) .use(rehypeStringify, { entities: { useNamedReferences: true } }) .process(content); - result = vfile.contents.toString(); + result = vfile.toString(); } catch (err) { throw err; } diff --git a/packages/markdown-support/src/load-plugins.ts b/packages/markdown-support/src/load-plugins.ts index df19a082e..5b24f14f6 100644 --- a/packages/markdown-support/src/load-plugins.ts +++ b/packages/markdown-support/src/load-plugins.ts @@ -9,7 +9,7 @@ async function importPlugin(p: string | UnifiedPluginImport): UnifiedPluginImpor return await p; } -export function loadPlugins(items: Plugin[]): Promise<[unified.Plugin] | [unified.Plugin, unified.Settings]>[] { +export function loadPlugins(items: Plugin[]): Promise<[unified.Plugin] | [unified.Plugin, any]>[] { return items.map((p) => { return new Promise((resolve, reject) => { if (Array.isArray(p)) { diff --git a/packages/markdown-support/src/rehype-collect-headers.ts b/packages/markdown-support/src/rehype-collect-headers.ts index 78774e494..211b7177c 100644 --- a/packages/markdown-support/src/rehype-collect-headers.ts +++ b/packages/markdown-support/src/rehype-collect-headers.ts @@ -1,32 +1,39 @@ import { visit } from 'unist-util-visit'; +import type { Root, Properties } from 'hast'; import slugger from 'github-slugger'; /** */ export default function createCollectHeaders() { const headers: any[] = []; - const visitor = (node: any) => { - if (node.type !== 'element') return; - const { tagName, children } = node; - if (tagName[0] !== 'h') return; - let [_, depth] = tagName.match(/h([0-6])/) ?? []; - if (!depth) return; - depth = Number.parseInt(depth); - - let text = ''; - - visit(node, 'text', (child) => { - text += (child as any).value; - }); - - let slug = node.properties.id || slugger.slug(text); - - node.properties = node.properties || {}; - node.properties.id = slug; - headers.push({ depth, slug, text }); - - return node; + function rehypeCollectHeaders() { + return function (tree: Root) { + visit(tree, (node) => { + if (node.type !== 'element') return; + const { tagName } = node; + if (tagName[0] !== 'h') return; + const [_, level] = tagName.match(/h([0-6])/) ?? []; + if (!level) return; + const depth = Number.parseInt(level); + + let text = ''; + + visit(node, 'text', (child) => { + text += child.value; + }); + + let slug = node?.data?.id || slugger.slug(text); + + node.data = node.data || {}; + node.data.properties = node.data.properties || {}; + node.data.properties = { ...(node.data.properties as Properties), slug }; + headers.push({ depth, slug, text }); + }); + }; + } + + return { + headers, + rehypeCollectHeaders, }; - - return { headers, rehypeCollectHeaders: () => (tree: any) => visit(tree, visitor) }; } diff --git a/packages/markdown-support/src/types.ts b/packages/markdown-support/src/types.ts index 6df601ae4..e263bcd4d 100644 --- a/packages/markdown-support/src/types.ts +++ b/packages/markdown-support/src/types.ts @@ -1,7 +1,7 @@ import unified from 'unified'; export type UnifiedPluginImport = Promise<{ default: unified.Plugin }>; -export type Plugin = string | [string, unified.Settings] | UnifiedPluginImport | [UnifiedPluginImport, unified.Settings]; +export type Plugin = string | [string, any] | UnifiedPluginImport | [UnifiedPluginImport, any]; export interface AstroMarkdownOptions { /** Enable or disable footnotes syntax extension */ |