summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src
diff options
context:
space:
mode:
authorGravatar Chris Swithinbank <swithinbank@gmail.com> 2023-01-09 10:23:21 +0100
committerGravatar GitHub <noreply@github.com> 2023-01-09 10:23:21 +0100
commit16107b6a10514ef1b563e585ec9add4b14f42b94 (patch)
tree7aeedf42016e63b81f58dd24050cc83eae7a3dd8 /packages/markdown/remark/src
parent54076a41ebf5da421370a130b97a6406f094042e (diff)
downloadastro-16107b6a10514ef1b563e585ec9add4b14f42b94.tar.gz
astro-16107b6a10514ef1b563e585ec9add4b14f42b94.tar.zst
astro-16107b6a10514ef1b563e585ec9add4b14f42b94.zip
Remove Astro-flavored Markdown from `@astrojs/markdown-remark` (#5785)
Diffstat (limited to 'packages/markdown/remark/src')
-rw-r--r--packages/markdown/remark/src/index.ts29
-rw-r--r--packages/markdown/remark/src/mdast-util-mdxish.ts12
-rw-r--r--packages/markdown/remark/src/mdxjs.ts27
-rw-r--r--packages/markdown/remark/src/rehype-collect-headings.ts21
-rw-r--r--packages/markdown/remark/src/rehype-escape.ts22
-rw-r--r--packages/markdown/remark/src/rehype-expressions.ts18
-rw-r--r--packages/markdown/remark/src/rehype-islands.ts43
-rw-r--r--packages/markdown/remark/src/rehype-jsx.ts65
-rw-r--r--packages/markdown/remark/src/remark-escape.ts15
-rw-r--r--packages/markdown/remark/src/remark-mark-and-unravel.ts72
-rw-r--r--packages/markdown/remark/src/remark-mdxish.ts61
-rw-r--r--packages/markdown/remark/src/remark-unwrap.ts44
-rw-r--r--packages/markdown/remark/src/types.ts1
13 files changed, 6 insertions, 424 deletions
diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts
index 24cffa287..91680f3fd 100644
--- a/packages/markdown/remark/src/index.ts
+++ b/packages/markdown/remark/src/index.ts
@@ -8,18 +8,10 @@ import type {
import { toRemarkInitializeAstroData } from './frontmatter-injection.js';
import { loadPlugins } from './load-plugins.js';
import { rehypeHeadingIds } from './rehype-collect-headings.js';
-import rehypeEscape from './rehype-escape.js';
-import rehypeExpressions from './rehype-expressions.js';
-import rehypeIslands from './rehype-islands.js';
-import rehypeJsx from './rehype-jsx.js';
import toRemarkContentRelImageError from './remark-content-rel-image-error.js';
-import remarkEscape from './remark-escape.js';
-import remarkMarkAndUnravel from './remark-mark-and-unravel.js';
-import remarkMdxish from './remark-mdxish.js';
import remarkPrism from './remark-prism.js';
import scopedStyles from './remark-scoped-styles.js';
import remarkShiki from './remark-shiki.js';
-import remarkUnwrap from './remark-unwrap.js';
import rehypeRaw from 'rehype-raw';
import rehypeStringify from 'rehype-stringify';
@@ -61,7 +53,6 @@ export async function renderMarkdown(
remarkRehype = markdownConfigDefaults.remarkRehype,
gfm = markdownConfigDefaults.gfm,
smartypants = markdownConfigDefaults.smartypants,
- isAstroFlavoredMd = false,
isExperimentalContentCollections = false,
contentDir,
frontmatter: userFrontmatter = {},
@@ -72,7 +63,7 @@ export async function renderMarkdown(
let parser = unified()
.use(markdown)
.use(toRemarkInitializeAstroData({ userFrontmatter }))
- .use(isAstroFlavoredMd ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : []);
+ .use([]);
if (gfm) {
parser.use(remarkGfm);
@@ -109,15 +100,7 @@ export async function renderMarkdown(
markdownToHtml as any,
{
allowDangerousHtml: true,
- passThrough: isAstroFlavoredMd
- ? [
- 'raw',
- 'mdxFlowExpression',
- 'mdxJsxFlowElement',
- 'mdxJsxTextElement',
- 'mdxTextExpression',
- ]
- : [],
+ passThrough: [],
...remarkRehype,
},
],
@@ -127,13 +110,7 @@ export async function renderMarkdown(
parser.use([[plugin, pluginOpts]]);
});
- parser
- .use(
- isAstroFlavoredMd
- ? [rehypeJsx, rehypeExpressions, rehypeEscape, rehypeIslands, rehypeHeadingIds]
- : [rehypeHeadingIds, rehypeRaw]
- )
- .use(rehypeStringify, { allowDangerousHtml: true });
+ parser.use([rehypeHeadingIds, rehypeRaw]).use(rehypeStringify, { allowDangerousHtml: true });
let vfile: MarkdownVFile;
try {
diff --git a/packages/markdown/remark/src/mdast-util-mdxish.ts b/packages/markdown/remark/src/mdast-util-mdxish.ts
deleted file mode 100644
index 10b19f5be..000000000
--- a/packages/markdown/remark/src/mdast-util-mdxish.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { mdxExpressionFromMarkdown, mdxExpressionToMarkdown } from 'mdast-util-mdx-expression';
-import { mdxJsxFromMarkdown, mdxJsxToMarkdown } from 'mdast-util-mdx-jsx';
-
-export function mdxFromMarkdown(): any {
- return [mdxExpressionFromMarkdown, mdxJsxFromMarkdown];
-}
-
-export function mdxToMarkdown(): any {
- return {
- extensions: [mdxExpressionToMarkdown, mdxJsxToMarkdown],
- };
-}
diff --git a/packages/markdown/remark/src/mdxjs.ts b/packages/markdown/remark/src/mdxjs.ts
deleted file mode 100644
index c3a9849ea..000000000
--- a/packages/markdown/remark/src/mdxjs.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-// Note: The code in this file is based on `micromark-extension-mdxjs`
-// and was adapted to use our fork `@astrojs/micromark-extension-mdx-jsx`
-// instead of `micromark-extension-mdx-jsx` to allow some extended syntax.
-// See `@astrojs/micromark-extension-mdx-jsx` on NPM for more details.
-// Also, support for ESM imports & exports in Markdown content was removed.
-
-import { mdxJsx } from '@astrojs/micromark-extension-mdx-jsx';
-import { Parser } from 'acorn';
-import acornJsx from 'acorn-jsx';
-import type { Options } from 'micromark-extension-mdx-expression';
-import { mdxExpression } from 'micromark-extension-mdx-expression';
-import { mdxMd } from 'micromark-extension-mdx-md';
-import { combineExtensions } from 'micromark-util-combine-extensions';
-import type { Extension } from 'micromark-util-types';
-
-export function mdxjs(options: Options): Extension {
- const settings: any = Object.assign(
- {
- acorn: Parser.extend(acornJsx()),
- acornOptions: { ecmaVersion: 2020, sourceType: 'module' },
- addResult: true,
- },
- options
- );
-
- return combineExtensions([mdxExpression(settings), mdxJsx(settings), mdxMd]);
-}
diff --git a/packages/markdown/remark/src/rehype-collect-headings.ts b/packages/markdown/remark/src/rehype-collect-headings.ts
index 03a3c6a23..142f796d6 100644
--- a/packages/markdown/remark/src/rehype-collect-headings.ts
+++ b/packages/markdown/remark/src/rehype-collect-headings.ts
@@ -21,7 +21,6 @@ export function rehypeHeadingIds(): ReturnType<RehypePlugin> {
const depth = Number.parseInt(level);
let text = '';
- let isJSX = false;
visit(node, (child, __, parent) => {
if (child.type === 'element' || parent == null) {
return;
@@ -36,31 +35,17 @@ export function rehypeHeadingIds(): ReturnType<RehypePlugin> {
text += child.value;
} else {
text += child.value.replace(/\{/g, '${');
- isJSX = isJSX || child.value.includes('{');
}
}
});
node.properties = node.properties || {};
if (typeof node.properties.id !== 'string') {
- if (isJSX) {
- // HACK: serialized JSX from internal plugins, ignore these for slug
- const raw = toHtml(node.children, { allowDangerousHtml: true })
- .replace(/\n(<)/g, '<')
- .replace(/(>)\n/g, '>');
- // HACK: for ids that have JSX content, use $$slug helper to generate slug at runtime
- node.properties.id = `$$slug(\`${text}\`)`;
- (node as any).type = 'raw';
- (
- node as any
- ).value = `<${node.tagName} id={${node.properties.id}}>${raw}</${node.tagName}>`;
- } else {
- let slug = slugger.slug(text);
+ let slug = slugger.slug(text);
- if (slug.endsWith('-')) slug = slug.slice(0, -1);
+ if (slug.endsWith('-')) slug = slug.slice(0, -1);
- node.properties.id = slug;
- }
+ node.properties.id = slug;
}
headings.push({ depth, slug: node.properties.id, text });
diff --git a/packages/markdown/remark/src/rehype-escape.ts b/packages/markdown/remark/src/rehype-escape.ts
deleted file mode 100644
index a4cc32cf7..000000000
--- a/packages/markdown/remark/src/rehype-escape.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { SKIP, visit } from 'unist-util-visit';
-
-export function escapeEntities(value: string): string {
- return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
-}
-
-export default function rehypeEscape(): any {
- return function (node: any): any {
- return visit(node, 'element', (el) => {
- if (el.tagName === 'code' || el.tagName === 'pre') {
- el.properties['is:raw'] = true;
- // Visit all raw children and escape HTML tags to prevent Markdown code
- // like "This is a `<script>` tag" from actually opening a script tag
- visit(el, 'raw', (raw) => {
- raw.value = escapeEntities(raw.value);
- });
- // Do not visit children to prevent double escaping
- return SKIP;
- }
- });
- };
-}
diff --git a/packages/markdown/remark/src/rehype-expressions.ts b/packages/markdown/remark/src/rehype-expressions.ts
deleted file mode 100644
index f06f242e2..000000000
--- a/packages/markdown/remark/src/rehype-expressions.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { map } from 'unist-util-map';
-
-export default function rehypeExpressions(): any {
- return function (node: any): any {
- return map(node, (child) => {
- if (child.type === 'text') {
- return { ...child, type: 'raw' };
- }
- if (child.type === 'mdxTextExpression') {
- return { type: 'raw', value: `{${(child as any).value}}` };
- }
- if (child.type === 'mdxFlowExpression') {
- return { type: 'raw', value: `{${(child as any).value}}` };
- }
- return child;
- });
- };
-}
diff --git a/packages/markdown/remark/src/rehype-islands.ts b/packages/markdown/remark/src/rehype-islands.ts
deleted file mode 100644
index a8b78848d..000000000
--- a/packages/markdown/remark/src/rehype-islands.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { SKIP, visit as _visit } from 'unist-util-visit';
-
-// This is a workaround.
-// It fixes a compatibility issue between different, incompatible ASTs given by plugins to Unist
-const visit = _visit as (
- node: any,
- type: string,
- callback?: (node: any, index: number, parent: any) => any
-) => any;
-
-// This fixes some confusing bugs coming from somewhere inside of our Markdown pipeline.
-// `unist`/`remark`/`rehype` (not sure) often generate malformed HTML inside of <astro-island>
-// For hydration to work properly, frameworks need the DOM to be the exact same on server/client.
-// This reverts some "helpful corrections" that are applied to our perfectly valid HTML!
-export default function rehypeIslands(): any {
- return function (node: any): any {
- return visit(node, 'element', (el) => {
- // Bugs only happen inside of <astro-island> islands
- if (el.tagName == 'astro-island') {
- visit(el, 'text', (child, index, parent) => {
- if (child.type === 'text') {
- // Sometimes comments can be trapped as text, which causes them to be escaped
- // This casts them back to real HTML comments
- if (parent && child.value.indexOf('<!--') > -1 && index != null) {
- parent.children.splice(index, 1, {
- ...child,
- type: 'comment',
- value: child.value.replace('<!--', '').replace('-->', '').trim(),
- });
- return [SKIP, index];
- }
- // For some reason `rehype` likes to inject extra linebreaks,
- // but React and Vue throw hydration errors when they see these!
- // This removes any extra linebreaks, which is fine because
- // framework compilers don't preserve them anyway
- child.value = child.value.replace(/\n+/g, '');
- return child;
- }
- });
- }
- });
- };
-}
diff --git a/packages/markdown/remark/src/rehype-jsx.ts b/packages/markdown/remark/src/rehype-jsx.ts
deleted file mode 100644
index 7082997e2..000000000
--- a/packages/markdown/remark/src/rehype-jsx.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { visit } from 'unist-util-visit';
-import type { RehypePlugin } from './types.js';
-
-const MDX_ELEMENTS = ['mdxJsxFlowElement', 'mdxJsxTextElement'];
-
-export default function rehypeJsx(): ReturnType<RehypePlugin> {
- return function (tree) {
- visit(tree, MDX_ELEMENTS, (node: any, index: number | null, parent: any) => {
- if (index === null || !Boolean(parent)) return;
-
- const attrs = node.attributes.reduce((acc: any[], entry: any) => {
- let attr = entry.value;
- if (attr && typeof attr === 'object') {
- attr = `{${attr.value}}`;
- } else if (attr && entry.type === 'mdxJsxExpressionAttribute') {
- attr = `{${attr}}`;
- } else if (attr === null) {
- attr = '';
- } else if (typeof attr === 'string') {
- attr = `"${attr}"`;
- }
- if (!entry.name) {
- return acc + ` ${attr}`;
- }
- return acc + ` ${entry.name}${attr ? '=' : ''}${attr}`;
- }, '');
-
- if (node.children.length === 0) {
- node.type = 'raw';
- node.value = `<${node.name}${attrs} />`;
- return;
- }
-
- // If the current node is a JSX <a> element, remove autolinks from its children
- // to prevent Markdown code like `<a href="/">**Go to www.example.com now!**</a>`
- // from creating a nested link to `www.example.com`
- if (node.name === 'a') {
- visit(node, 'element', (el, elIndex, elParent) => {
- const isAutolink =
- el.tagName === 'a' &&
- el.children.length === 1 &&
- el.children[0].type === 'text' &&
- el.children[0].value.match(/^(https?:\/\/|www\.)/i);
-
- // If we found an autolink, remove it by replacing it with its text-only child
- if (isAutolink) {
- elParent.children.splice(elIndex, 1, el.children[0]);
- }
- });
- }
-
- // Replace the current node with its children
- // wrapped by raw opening and closing tags
- const openingTag = {
- type: 'raw',
- value: `<${node.name}${attrs}>`,
- };
- const closingTag = {
- type: 'raw',
- value: `</${node.name}>`,
- };
- parent.children.splice(index, 1, openingTag, ...node.children, closingTag);
- });
- };
-}
diff --git a/packages/markdown/remark/src/remark-escape.ts b/packages/markdown/remark/src/remark-escape.ts
deleted file mode 100644
index 84cdf2efa..000000000
--- a/packages/markdown/remark/src/remark-escape.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { Literal } from 'unist';
-import { visit } from 'unist-util-visit';
-
-// In code blocks, this removes the JS comment wrapper added to
-// HTML comments by vite-plugin-markdown-legacy.
-export default function remarkEscape() {
- return (tree: any) => {
- visit(tree, 'code', removeCommentWrapper);
- visit(tree, 'inlineCode', removeCommentWrapper);
- };
-
- function removeCommentWrapper(node: Literal<string>) {
- node.value = node.value.replace(/{\/\*<!--/gs, '<!--').replace(/-->\*\/}/gs, '-->');
- }
-}
diff --git a/packages/markdown/remark/src/remark-mark-and-unravel.ts b/packages/markdown/remark/src/remark-mark-and-unravel.ts
deleted file mode 100644
index 294d4211d..000000000
--- a/packages/markdown/remark/src/remark-mark-and-unravel.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-// https://github.com/mdx-js/mdx/blob/main/packages/mdx/lib/plugin/remark-mark-and-unravel.js
-/**
- * @typedef {import('mdast').Root} Root
- * @typedef {import('mdast').Content} Content
- * @typedef {Root|Content} Node
- * @typedef {Extract<Node, import('unist').Parent>} Parent
- *
- * @typedef {import('remark-mdx')} DoNotTouchAsThisImportItIncludesMdxInTree
- */
-
-import { visit } from 'unist-util-visit';
-
-/**
- * A tiny plugin that unravels `<p><h1>x</h1></p>` but also
- * `<p><Component /></p>` (so it has no knowledge of “HTML”).
- * It also marks JSX as being explicitly JSX, so when a user passes a `h1`
- * component, it is used for `# heading` but not for `<h1>heading</h1>`.
- *
- * @type {import('unified').Plugin<Array<void>, Root>}
- */
-export default function remarkMarkAndUnravel() {
- return (tree: any) => {
- visit(tree, (node, index, parent_) => {
- const parent = /** @type {Parent} */ parent_;
- let offset = -1;
- let all = true;
- /** @type {boolean|undefined} */
- let oneOrMore;
-
- if (parent && typeof index === 'number' && node.type === 'paragraph') {
- const children = node.children;
-
- while (++offset < children.length) {
- const child = children[offset];
-
- if (child.type === 'mdxJsxTextElement' || child.type === 'mdxTextExpression') {
- oneOrMore = true;
- } else if (child.type === 'text' && /^[\t\r\n ]+$/.test(String(child.value))) {
- // Empty.
- } else {
- all = false;
- break;
- }
- }
-
- if (all && oneOrMore) {
- offset = -1;
-
- while (++offset < children.length) {
- const child = children[offset];
-
- if (child.type === 'mdxJsxTextElement') {
- child.type = 'mdxJsxFlowElement';
- }
-
- if (child.type === 'mdxTextExpression') {
- child.type = 'mdxFlowExpression';
- }
- }
-
- parent.children.splice(index, 1, ...children);
- return index;
- }
- }
-
- if (node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement') {
- const data = node.data || (node.data = {});
- data._mdxExplicitJsx = true;
- }
- });
- };
-}
diff --git a/packages/markdown/remark/src/remark-mdxish.ts b/packages/markdown/remark/src/remark-mdxish.ts
deleted file mode 100644
index 0f70f87b3..000000000
--- a/packages/markdown/remark/src/remark-mdxish.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import type * as fromMarkdown from 'mdast-util-from-markdown';
-import type { Tag } from 'mdast-util-mdx-jsx';
-import { mdxFromMarkdown, mdxToMarkdown } from './mdast-util-mdxish.js';
-import { mdxjs } from './mdxjs.js';
-
-// Prepare markdown extensions once to prevent performance issues
-const extMdxJs = mdxjs({});
-const extMdxFromMarkdown = makeFromMarkdownLessStrict(mdxFromMarkdown());
-const extMdxToMarkdown = mdxToMarkdown();
-
-export default function remarkMdxish(this: any) {
- const data = this.data();
-
- add('micromarkExtensions', extMdxJs);
- add('fromMarkdownExtensions', extMdxFromMarkdown);
- add('toMarkdownExtensions', extMdxToMarkdown);
-
- function add(field: string, value: unknown) {
- const list = data[field] ? data[field] : (data[field] = []);
- list.push(value);
- }
-}
-
-function makeFromMarkdownLessStrict(extensions: fromMarkdown.Extension[]) {
- extensions.forEach((extension) => {
- // Fix exit handlers that are too strict
- ['mdxJsxFlowTag', 'mdxJsxTextTag'].forEach((exitHandler) => {
- if (!extension.exit || !extension.exit[exitHandler]) return;
- extension.exit[exitHandler] = chainHandlers(fixSelfClosing, extension.exit[exitHandler]);
- });
- });
-
- return extensions;
-}
-
-const selfClosingTags = new Set([
- 'area',
- 'base',
- 'br',
- 'col',
- 'embed',
- 'hr',
- 'img',
- 'input',
- 'link',
- 'meta',
- 'source',
- 'track',
- 'wbr',
-]);
-
-function fixSelfClosing(this: fromMarkdown.CompileContext) {
- const tag = this.getData('mdxJsxTag') as Tag;
- if (tag.name && selfClosingTags.has(tag.name)) tag.selfClosing = true;
-}
-
-function chainHandlers(...handlers: fromMarkdown.Handle[]) {
- return function handlerChain(this: fromMarkdown.CompileContext, token: fromMarkdown.Token) {
- handlers.forEach((handler) => handler.call(this, token));
- };
-}
diff --git a/packages/markdown/remark/src/remark-unwrap.ts b/packages/markdown/remark/src/remark-unwrap.ts
deleted file mode 100644
index 399bd6cd6..000000000
--- a/packages/markdown/remark/src/remark-unwrap.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { SKIP, visit as _visit } from 'unist-util-visit';
-
-// This is a workaround.
-// It fixes a compatibility issue between different, incompatible ASTs given by plugins to Unist
-const visit = _visit as (
- node: any,
- type: string,
- callback?: (node: any, index: number, parent: any) => any
-) => any;
-
-// Remove the wrapping paragraph for <astro-island> islands
-export default function remarkUnwrap() {
- const astroRootNodes = new Set();
- let insideAstroRoot = false;
-
- return (tree: any) => {
- // reset state
- insideAstroRoot = false;
- astroRootNodes.clear();
-
- visit(tree, 'html', (node) => {
- if (node.value.indexOf('<astro-island') > -1 && !insideAstroRoot) {
- insideAstroRoot = true;
- }
- if (node.value.indexOf('</astro-island') > -1 && insideAstroRoot) {
- insideAstroRoot = false;
- }
- astroRootNodes.add(node);
- });
-
- visit(tree, 'paragraph', (node, index, parent) => {
- if (parent && typeof index === 'number' && containsAstroRootNode(node)) {
- parent.children.splice(index, 1, ...node.children);
- return [SKIP, index];
- }
- });
- };
-
- function containsAstroRootNode(node: any) {
- return node.children
- .map((child: any) => astroRootNodes.has(child))
- .reduce((all: boolean, v: boolean) => (all ? all : v), false);
- }
-}
diff --git a/packages/markdown/remark/src/types.ts b/packages/markdown/remark/src/types.ts
index d5133aaf0..40b2ac841 100644
--- a/packages/markdown/remark/src/types.ts
+++ b/packages/markdown/remark/src/types.ts
@@ -58,7 +58,6 @@ export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
$?: {
scopedClassName: string | null;
};
- isAstroFlavoredMd?: boolean;
/** Used to prevent relative image imports from `src/content/` */
isExperimentalContentCollections?: boolean;
/** Used to prevent relative image imports from `src/content/` */