-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MDX] Add Prism and Shiki support (#4002)
* deps: add rehype-prism, shiki, rehype-pretty-code * wip: apply rehype plugins depending on config * wip: cherry-pick jsx-runtime fix? * deps: rehype-pretty-code -> shiki-twoslash, add rehype-raw * wip: add jsx-runtime fix * feat: get shiki working! * deps: add @astrojs/prism, prismjs, unist-util-visit * feat: add prism support * example: add small syntax highlight demo to with-mdx * deps: remove rehype-prism * chore: remove unused async * chore: add .test.js to all mdx tests * test: shiki, shikiConfig, prism * fix: remove "is:raw" from prism output * docs: add syntax highlighting section * chore: add changeset * nit: "Shiki config" -> Shiki config Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Revert "wip: add jsx-runtime fix" This reverts commit 07f4528. * docs: link to integration README from example Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
- Loading branch information
1 parent
3f7b5f1
commit 3b8a744
Showing
11 changed files
with
339 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@astrojs/mdx': minor | ||
--- | ||
|
||
Support Prism and Shiki syntax highlighting based on project config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// TODO: discuss extracting this file to @astrojs/prism | ||
import { addAstro } from '@astrojs/prism/internal'; | ||
import Prism from 'prismjs'; | ||
import loadLanguages from 'prismjs/components/index.js'; | ||
import { visit } from 'unist-util-visit'; | ||
|
||
const languageMap = new Map([['ts', 'typescript']]); | ||
|
||
function runHighlighter(lang: string, code: string) { | ||
let classLanguage = `language-${lang}`; | ||
|
||
if (lang == null) { | ||
lang = 'plaintext'; | ||
} | ||
|
||
const ensureLoaded = (language: string) => { | ||
if (language && !Prism.languages[language]) { | ||
loadLanguages([language]); | ||
} | ||
}; | ||
|
||
if (languageMap.has(lang)) { | ||
ensureLoaded(languageMap.get(lang)!); | ||
} else if (lang === 'astro') { | ||
ensureLoaded('typescript'); | ||
addAstro(Prism); | ||
} else { | ||
ensureLoaded('markup-templating'); // Prism expects this to exist for a number of other langs | ||
ensureLoaded(lang); | ||
} | ||
|
||
if (lang && !Prism.languages[lang]) { | ||
// eslint-disable-next-line no-console | ||
console.warn(`Unable to load the language: ${lang}`); | ||
} | ||
|
||
const grammar = Prism.languages[lang]; | ||
let html = code; | ||
if (grammar) { | ||
html = Prism.highlight(code, grammar, lang); | ||
} | ||
|
||
return { classLanguage, html }; | ||
} | ||
|
||
/** */ | ||
export default function remarkPrism() { | ||
return (tree: any) => visit(tree, 'code', (node: any) => { | ||
let { lang, value } = node; | ||
node.type = 'html'; | ||
|
||
let { html, classLanguage } = runHighlighter(lang, value); | ||
let classes = [classLanguage]; | ||
node.value = `<pre class="${classes.join( | ||
' ' | ||
)}"><code class="${classLanguage}">${html}</code></pre>`; | ||
return node; | ||
}); | ||
} |
9 changes: 9 additions & 0 deletions
9
...ges/integrations/mdx/test/fixtures/mdx-syntax-hightlighting/src/pages/index.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Syntax highlighting | ||
|
||
```astro | ||
--- | ||
const handlesAstroSyntax = true | ||
--- | ||
<h1>{handlesAstroSyntax}</h1> | ||
``` |
File renamed without changes.
67 changes: 67 additions & 0 deletions
67
packages/integrations/mdx/test/mdx-syntax-highlighting.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import mdx from '@astrojs/mdx'; | ||
|
||
import { expect } from 'chai'; | ||
import { parseHTML } from 'linkedom'; | ||
import { loadFixture } from '../../../astro/test/test-utils.js'; | ||
|
||
const FIXTURE_ROOT = new URL('./fixtures/mdx-syntax-hightlighting/', import.meta.url); | ||
|
||
describe('MDX syntax highlighting', () => { | ||
describe('shiki', () => { | ||
it('works', async () => { | ||
const fixture = await loadFixture({ | ||
root: FIXTURE_ROOT, | ||
markdown: { | ||
syntaxHighlight: 'shiki', | ||
}, | ||
integrations: [mdx()], | ||
}); | ||
await fixture.build(); | ||
|
||
const html = await fixture.readFile('/index.html'); | ||
const { document } = parseHTML(html); | ||
|
||
const shikiCodeBlock = document.querySelector('pre.shiki'); | ||
expect(shikiCodeBlock).to.not.be.null; | ||
}); | ||
|
||
it('respects markdown.shikiConfig.theme', async () => { | ||
const fixture = await loadFixture({ | ||
root: FIXTURE_ROOT, | ||
markdown: { | ||
syntaxHighlight: 'shiki', | ||
shikiConfig: { | ||
theme: 'dracula', | ||
}, | ||
}, | ||
integrations: [mdx()], | ||
}); | ||
await fixture.build(); | ||
|
||
const html = await fixture.readFile('/index.html'); | ||
const { document } = parseHTML(html); | ||
|
||
const shikiCodeBlock = document.querySelector('pre.shiki.dracula'); | ||
expect(shikiCodeBlock).to.not.be.null; | ||
}); | ||
}); | ||
|
||
describe('prism', () => { | ||
it('works', async () => { | ||
const fixture = await loadFixture({ | ||
root: FIXTURE_ROOT, | ||
markdown: { | ||
syntaxHighlight: 'prism', | ||
}, | ||
integrations: [mdx()], | ||
}); | ||
await fixture.build(); | ||
|
||
const html = await fixture.readFile('/index.html'); | ||
const { document } = parseHTML(html); | ||
|
||
const prismCodeBlock = document.querySelector('pre.language-astro'); | ||
expect(prismCodeBlock).to.not.be.null; | ||
}); | ||
}); | ||
}); |
File renamed without changes.
Oops, something went wrong.