summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/markdown/remark/src')
-rw-r--r--packages/markdown/remark/src/index.ts18
-rw-r--r--packages/markdown/remark/src/remark-prism.ts20
-rw-r--r--packages/markdown/remark/src/remark-scoped-styles.ts18
-rw-r--r--packages/markdown/remark/src/remark-shiki.ts46
-rw-r--r--packages/markdown/remark/src/types.ts4
5 files changed, 33 insertions, 73 deletions
diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts
index 43ab885b6..c54826bdc 100644
--- a/packages/markdown/remark/src/index.ts
+++ b/packages/markdown/remark/src/index.ts
@@ -9,9 +9,8 @@ import { toRemarkInitializeAstroData } from './frontmatter-injection.js';
import { loadPlugins } from './load-plugins.js';
import { rehypeHeadingIds } from './rehype-collect-headings.js';
import { remarkCollectImages } from './remark-collect-images.js';
-import remarkPrism from './remark-prism.js';
-import scopedStyles from './remark-scoped-styles.js';
-import remarkShiki from './remark-shiki.js';
+import { remarkPrism } from './remark-prism.js';
+import { remarkShiki } from './remark-shiki.js';
import rehypeRaw from 'rehype-raw';
import rehypeStringify from 'rehype-stringify';
@@ -25,6 +24,8 @@ import { rehypeImages } from './rehype-images.js';
export { rehypeHeadingIds } from './rehype-collect-headings.js';
export { remarkCollectImages } from './remark-collect-images.js';
+export { remarkPrism } from './remark-prism.js';
+export { remarkShiki } from './remark-shiki.js';
export * from './types.js';
export const markdownConfigDefaults: Omit<Required<AstroMarkdownOptions>, 'drafts'> = {
@@ -61,7 +62,6 @@ export async function renderMarkdown(
frontmatter: userFrontmatter = {},
} = opts;
const input = new VFile({ value: content, path: fileURL });
- const scopedClassName = opts.$?.scopedClassName;
let parser = unified()
.use(markdown)
@@ -85,18 +85,14 @@ export async function renderMarkdown(
});
if (!isPerformanceBenchmark) {
- if (scopedClassName) {
- parser.use([scopedStyles(scopedClassName)]);
- }
-
if (syntaxHighlight === 'shiki') {
- parser.use([await remarkShiki(shikiConfig, scopedClassName)]);
+ parser.use(remarkShiki, shikiConfig);
} else if (syntaxHighlight === 'prism') {
- parser.use([remarkPrism(scopedClassName)]);
+ parser.use(remarkPrism);
}
// Apply later in case user plugins resolve relative image paths
- parser.use([remarkCollectImages]);
+ parser.use(remarkCollectImages);
}
parser.use([
diff --git a/packages/markdown/remark/src/remark-prism.ts b/packages/markdown/remark/src/remark-prism.ts
index 6147d9ee9..a3f476d6e 100644
--- a/packages/markdown/remark/src/remark-prism.ts
+++ b/packages/markdown/remark/src/remark-prism.ts
@@ -1,31 +1,19 @@
import { runHighlighterWithAstro } from '@astrojs/prism/dist/highlighter';
import { visit } from 'unist-util-visit';
+import type { RemarkPlugin } from './types.js';
-type MaybeString = string | null | undefined;
-
-/** */
-function transformer(className: MaybeString) {
+export function remarkPrism(): ReturnType<RemarkPlugin> {
return function (tree: any) {
- const visitor = (node: any) => {
+ visit(tree, 'code', (node) => {
let { lang, value } = node;
node.type = 'html';
let { html, classLanguage } = runHighlighterWithAstro(lang, value);
let classes = [classLanguage];
- if (className) {
- classes.push(className);
- }
node.value = `<pre class="${classes.join(
' '
)}"><code is:raw class="${classLanguage}">${html}</code></pre>`;
return node;
- };
- return visit(tree, 'code', visitor);
+ });
};
}
-
-function plugin(className: MaybeString) {
- return transformer.bind(null, className);
-}
-
-export default plugin;
diff --git a/packages/markdown/remark/src/remark-scoped-styles.ts b/packages/markdown/remark/src/remark-scoped-styles.ts
deleted file mode 100644
index ba8780bb7..000000000
--- a/packages/markdown/remark/src/remark-scoped-styles.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { visit } from 'unist-util-visit';
-const noVisit = new Set(['root', 'html', 'text']);
-
-/** */
-export default function scopedStyles(className: string) {
- const visitor = (node: any) => {
- if (noVisit.has(node.type)) return;
-
- const { data } = node;
- let currentClassName = data?.hProperties?.class ?? '';
- node.data = node.data || {};
- node.data.hProperties = node.data.hProperties || {};
- node.data.hProperties.class = `${className} ${currentClassName}`.trim();
-
- return node;
- };
- return () => (tree: any) => visit(tree, visitor);
-}
diff --git a/packages/markdown/remark/src/remark-shiki.ts b/packages/markdown/remark/src/remark-shiki.ts
index 77cbf16c6..6cd3861e5 100644
--- a/packages/markdown/remark/src/remark-shiki.ts
+++ b/packages/markdown/remark/src/remark-shiki.ts
@@ -1,7 +1,7 @@
import type * as shiki from 'shiki';
import { getHighlighter } from 'shiki';
import { visit } from 'unist-util-visit';
-import type { ShikiConfig } from './types.js';
+import type { RemarkPlugin, ShikiConfig } from './types.js';
/**
* getHighlighter() is the most expensive step of Shiki. Instead of calling it on every page,
@@ -10,10 +10,11 @@ import type { ShikiConfig } from './types.js';
*/
const highlighterCacheAsync = new Map<string, Promise<shiki.Highlighter>>();
-const remarkShiki = async (
- { langs = [], theme = 'github-dark', wrap = false }: ShikiConfig,
- scopedClassName?: string | null
-) => {
+export function remarkShiki({
+ langs = [],
+ theme = 'github-dark',
+ wrap = false,
+}: ShikiConfig = {}): ReturnType<RemarkPlugin> {
const cacheID: string = typeof theme === 'string' ? theme : theme.name;
let highlighterAsync = highlighterCacheAsync.get(cacheID);
if (!highlighterAsync) {
@@ -35,15 +36,22 @@ const remarkShiki = async (
});
highlighterCacheAsync.set(cacheID, highlighterAsync);
}
- const highlighter = await highlighterAsync;
- // NOTE: There may be a performance issue here for large sites that use `lang`.
- // Since this will be called on every page load. Unclear how to fix this.
- for (const lang of langs) {
- await highlighter.loadLanguage(lang);
- }
+ let highlighter: shiki.Highlighter;
+
+ return async (tree: any) => {
+ // Lazily assign the highlighter as async can only happen within this function,
+ // and not on `remarkShiki` directly.
+ if (!highlighter) {
+ highlighter = await highlighterAsync!;
+
+ // NOTE: There may be a performance issue here for large sites that use `lang`.
+ // Since this will be called on every page load. Unclear how to fix this.
+ for (const lang of langs) {
+ await highlighter.loadLanguage(lang);
+ }
+ }
- return () => (tree: any) => {
visit(tree, 'code', (node) => {
let lang: string;
@@ -69,10 +77,7 @@ const remarkShiki = async (
// &lt;span class=&quot;line&quot;
// Replace "shiki" class naming with "astro" and add "is:raw".
- html = html.replace(
- /<pre class="(.*?)shiki(.*?)"/,
- `<pre is:raw class="$1astro-code$2${scopedClassName ? ' ' + scopedClassName : ''}"`
- );
+ html = html.replace(/<pre class="(.*?)shiki(.*?)"/, `<pre is:raw class="$1astro-code$2"`);
// Add "user-select: none;" for "+"/"-" diff symbols
if (node.lang === 'diff') {
html = html.replace(
@@ -91,16 +96,9 @@ const remarkShiki = async (
);
}
- // Apply scopedClassName to all nested lines
- if (scopedClassName) {
- html = html.replace(/\<span class="line"\>/g, `<span class="line ${scopedClassName}"`);
- }
-
node.type = 'html';
node.value = html;
node.children = [];
});
};
-};
-
-export default remarkShiki;
+}
diff --git a/packages/markdown/remark/src/types.ts b/packages/markdown/remark/src/types.ts
index 6d8ecf8f2..caeebec93 100644
--- a/packages/markdown/remark/src/types.ts
+++ b/packages/markdown/remark/src/types.ts
@@ -61,10 +61,6 @@ export interface ImageMetadata {
export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
/** @internal */
fileURL?: URL;
- /** @internal */
- $?: {
- scopedClassName: string | null;
- };
/** Used for frontmatter injection plugins */
frontmatter?: Record<string, any>;
}