summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/curly-queens-pay.md5
-rw-r--r--packages/astro/components/Prism.astro6
-rw-r--r--packages/astro/src/compiler/transform/prism.ts17
-rw-r--r--packages/astro/test/astro-markdown.test.js10
-rw-r--r--packages/astro/test/fixtures/astro-markdown/src/pages/scopedStyles-code.astro14
-rw-r--r--packages/markdown-support/src/index.ts3
6 files changed, 50 insertions, 5 deletions
diff --git a/.changeset/curly-queens-pay.md b/.changeset/curly-queens-pay.md
new file mode 100644
index 000000000..9199a6d02
--- /dev/null
+++ b/.changeset/curly-queens-pay.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+- Allow Markdown with scoped styles to coexist happily with code syntax highlighting via Prism
diff --git a/packages/astro/components/Prism.astro b/packages/astro/components/Prism.astro
index 9b1f99717..b96f4c358 100644
--- a/packages/astro/components/Prism.astro
+++ b/packages/astro/components/Prism.astro
@@ -3,7 +3,8 @@ import Prism from 'prismjs';
import { addAstro } from '@astrojs/prism';
import loadLanguages from 'prismjs/components/index.js';
-const { lang, code } = Astro.props;
+const { class: className, lang, code } = Astro.props;
+let classLanguage = `language-${lang}`
const languageMap = new Map([
['ts', 'typescript']
@@ -39,7 +40,6 @@ if (grammar) {
html = Prism.highlight(code, grammar, lang);
}
-let className = lang ? `language-${lang}` : '';
---
-<pre class={className}><code class={className}>{html}</code></pre>
+<pre class={className}><code class={classLanguage}>{html}</code></pre>
diff --git a/packages/astro/src/compiler/transform/prism.ts b/packages/astro/src/compiler/transform/prism.ts
index 0afb8194b..9fe241810 100644
--- a/packages/astro/src/compiler/transform/prism.ts
+++ b/packages/astro/src/compiler/transform/prism.ts
@@ -4,6 +4,7 @@ import { getAttrValue } from '../../ast.js';
export const PRISM_IMPORT = `import Prism from 'astro/components/Prism.astro';`;
const prismImportExp = /import Prism from ['"]astro\/components\/Prism.astro['"]/;
+
/** escaping code samples that contain template string replacement parts, ${foo} or example. */
function escape(code: string) {
return code
@@ -22,6 +23,7 @@ function unescapeCode(code: TemplateNode) {
return child;
});
}
+
/** default export - Transform prism */
export default function (module: Script): Transformer {
let usesPrism = false;
@@ -43,15 +45,17 @@ export default function (module: Script): Transformer {
const className = getAttrValue(codeEl.attributes, 'class') || '';
const classes = className.split(' ');
- let lang;
+ let lang: string | undefined;
for (let cn of classes) {
const matches = /language-(.+)/.exec(cn);
if (matches) {
lang = matches[1];
+ break;
}
}
if (!lang) return;
+ let classesWithoutLang = classes.filter((cn) => cn !== `language-${lang}`);
let codeData = codeEl.children && codeEl.children[0];
if (!codeData) return;
@@ -76,6 +80,17 @@ export default function (module: Script): Transformer {
},
{
type: 'Attribute',
+ name: 'class',
+ value: [
+ {
+ type: 'Text',
+ raw: classesWithoutLang.join(' '),
+ data: classesWithoutLang.join(' '),
+ },
+ ],
+ },
+ {
+ type: 'Attribute',
name: 'code',
value: [
{
diff --git a/packages/astro/test/astro-markdown.test.js b/packages/astro/test/astro-markdown.test.js
index b8b3c6bb0..72b976b73 100644
--- a/packages/astro/test/astro-markdown.test.js
+++ b/packages/astro/test/astro-markdown.test.js
@@ -35,6 +35,16 @@ Markdown('Runs code blocks through syntax highlighter', async ({ runtime }) => {
assert.ok($el.length > 0, 'There are child spans in code blocks');
});
+Markdown('Scoped styles should not break syntax highlight', async ({ runtime }) => {
+ const result = await runtime.load('/scopedStyles-code');
+ assert.ok(!result.error, `build error: ${result.error}`);
+
+ const $ = doc(result.contents);
+ assert.ok($('pre').is('[class]'), 'Pre tag has scopedStyle class passed down');
+ assert.ok($('code').hasClass('language-js'), 'Code tag has correct language');
+ assert.ok($('code span').length > 0, 'There are child spans in code blocks');
+});
+
Markdown('Bundles client-side JS for prod', async (context) => {
await context.build();
diff --git a/packages/astro/test/fixtures/astro-markdown/src/pages/scopedStyles-code.astro b/packages/astro/test/fixtures/astro-markdown/src/pages/scopedStyles-code.astro
new file mode 100644
index 000000000..17986d979
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-markdown/src/pages/scopedStyles-code.astro
@@ -0,0 +1,14 @@
+---
+import { Markdown } from 'astro/components';
+import Layout from '../layouts/content.astro';
+
+---
+<Markdown>
+<Layout>
+ ## Interesting Topic
+
+ ```js
+ const thing = () => {};
+ ```
+</Layout>
+</Markdown>
diff --git a/packages/markdown-support/src/index.ts b/packages/markdown-support/src/index.ts
index 5278d44d6..86d95a414 100644
--- a/packages/markdown-support/src/index.ts
+++ b/packages/markdown-support/src/index.ts
@@ -4,7 +4,7 @@ import createCollectHeaders from './rehype-collect-headers.js';
import scopedStyles from './remark-scoped-styles.js';
import remarkExpressions from './remark-expressions.js';
import rehypeExpressions from './rehype-expressions.js';
-import { rehypeCodeBlock } from './codeblock.js';
+import { remarkCodeBlock, rehypeCodeBlock } from './codeblock.js';
import { loadPlugins } from './load-plugins.js';
import raw from 'rehype-raw';
@@ -56,6 +56,7 @@ export async function renderMarkdown(content: string, opts?: MarkdownRenderingOp
parser.use(scopedStyles(scopedClassName));
}
+ parser.use(remarkCodeBlock());
parser.use(markdownToHtml, { allowDangerousHtml: true, passThrough: ['raw', 'mdxTextExpression'] });
parser.use(rehypeExpressions);