Skip to content

Commit

Permalink
[v3] update rehype-pretty-code/shikiji to latest (#2679)
Browse files Browse the repository at this point in the history
* update

* update

* update

* update

* prettier
  • Loading branch information
Dimitri POSTOLOV authored Feb 2, 2024
1 parent 2fef889 commit 9f55bd1
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 120 deletions.
7 changes: 7 additions & 0 deletions .changeset/rare-ties-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'nextra-theme-blog': patch
'nextra-theme-docs': patch
'nextra': patch
---

update rehype-pretty-code/shikiji to latest
1 change: 0 additions & 1 deletion docs/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
25 changes: 15 additions & 10 deletions docs/pages/docs/guide/syntax-highlighting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,20 @@ nextra({
})
```

### Multiple Themes
### Multiple Themes (Dark and Light Mode)

Nextra currently doesn't support specifying multiple themes. Because Shiki
renders multiple code blocks for every theme and tags them with an attribute
`data-theme`, e.g. `data-theme="dark"`.
Pass your themes to `theme`, where the keys represent the color mode:

<Callout type="info">
However, in the future, multiple themes will be supported. You can track the
progress in shikiji (newly fork of Shiki)
https://github.com/antfu/shikiji#multiple-themes that already supports
multiple themes without rendering multiple code blocks.
</Callout>
```js copy=false filename="next.config.mjs" {5-8}
nextra({
// ...
mdxOptions: {
rehypePrettyCodeOptions: {
theme: {
dark: 'nord',
light: 'min-light'
}
}
}
})
```
2 changes: 1 addition & 1 deletion packages/nextra/__test__/compile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ describe('Code block', () => {
mdxOptions
})
expect(result).toMatch(
'<_components.pre data-language="text" data-word-wrap="" data-filename="test.js">'
'<_components.pre tabIndex="0" data-language="text" data-word-wrap="" data-filename="test.js">'
)
})

Expand Down
4 changes: 2 additions & 2 deletions packages/nextra/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,14 @@
"katex": "^0.16.9",
"p-limit": "^4.0.0",
"rehype-katex": "^7.0.0",
"rehype-pretty-code": "0.10.1",
"rehype-pretty-code": "0.12.6",
"rehype-raw": "^7.0.0",
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.0",
"remark-math": "^6.0.0",
"remark-reading-time": "^2.0.1",
"remark-smartypants": "^2.1.0",
"shiki": "npm:[email protected]",
"shikiji": "^0.10.2",
"slash": "^5.1.0",
"title": "^3.5.3",
"unist-util-remove": "^4.0.0",
Expand Down
14 changes: 7 additions & 7 deletions packages/nextra/src/server/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,6 @@ export async function compileMdx(
rehypePrettyCodeOptions
}: MdxOptions = mdxOptions

if (rehypePrettyCodeOptions) {
throw new Error(
"`rehypePrettyCodeOptions` is currently unsupported since `rehype-pretty-code` doesn't support `shikiji` package"
)
}

const format =
_format === 'detect' ? (filePath.endsWith('.mdx') ? 'mdx' : 'md') : _format

Expand Down Expand Up @@ -278,7 +272,13 @@ export async function compileMdx(
...(codeHighlight === false
? []
: [
[rehypePrettyCode, DEFAULT_REHYPE_PRETTY_CODE_OPTIONS] as any,
[
rehypePrettyCode,
{
...DEFAULT_REHYPE_PRETTY_CODE_OPTIONS,
...rehypePrettyCodeOptions
}
] as any,
!isRemoteContent && rehypeIcon,
rehypeAttachCodeMeta
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ describe('rehypeIcon', () => {
}
return (
<>
<_components.pre icon={CssIcon} data-language="css" data-word-wrap="" data-copy="">
<_components.pre icon={CssIcon} tabIndex="0" data-language="css" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CssIcon} data-language="css" data-word-wrap="" data-copy="">
<_components.pre icon={CssIcon} tabIndex="0" data-language="css" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
Expand Down Expand Up @@ -83,103 +83,103 @@ describe('rehypeIcon', () => {
}
return (
<>
<_components.pre icon={JavaScriptIcon} data-language="js" data-word-wrap="" data-copy="">
<_components.pre icon={JavaScriptIcon} tabIndex="0" data-language="js" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={JavaScriptIcon} data-language="jsx" data-word-wrap="" data-copy="">
<_components.pre icon={JavaScriptIcon} tabIndex="0" data-language="jsx" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={TypeScriptIcon} data-language="ts" data-word-wrap="" data-copy="">
<_components.pre icon={TypeScriptIcon} tabIndex="0" data-language="ts" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={TypeScriptIcon} data-language="tsx" data-word-wrap="" data-copy="">
<_components.pre icon={TypeScriptIcon} tabIndex="0" data-language="tsx" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={MarkdownIcon} data-language="md" data-word-wrap="" data-copy="">
<_components.pre icon={MarkdownIcon} tabIndex="0" data-language="md" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={MdxIcon} data-language="mdx" data-word-wrap="" data-copy="">
<_components.pre icon={MdxIcon} tabIndex="0" data-language="mdx" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={TerminalIcon} data-language="sh" data-word-wrap="" data-copy="">
<_components.pre icon={TerminalIcon} tabIndex="0" data-language="sh" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={TerminalIcon} data-language="bash" data-word-wrap="" data-copy="">
<_components.pre icon={TerminalIcon} tabIndex="0" data-language="bash" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CssIcon} data-language="css" data-word-wrap="" data-copy="">
<_components.pre icon={CssIcon} tabIndex="0" data-language="css" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CPPIcon} data-language="c++" data-word-wrap="" data-copy="">
<_components.pre icon={CPPIcon} tabIndex="0" data-language="c++" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CPPIcon} data-language="cpp" data-word-wrap="" data-copy="">
<_components.pre icon={CPPIcon} tabIndex="0" data-language="cpp" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CsharpIcon} data-language="csharp" data-word-wrap="" data-copy="">
<_components.pre icon={CsharpIcon} tabIndex="0" data-language="csharp" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CsharpIcon} data-language="cs" data-word-wrap="" data-copy="">
<_components.pre icon={CsharpIcon} tabIndex="0" data-language="cs" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={CsharpIcon} data-language="c#" data-word-wrap="" data-copy="">
<_components.pre icon={CsharpIcon} tabIndex="0" data-language="c#" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={GraphQLIcon} data-language="graphql" data-word-wrap="" data-copy="">
<_components.pre icon={GraphQLIcon} tabIndex="0" data-language="graphql" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={PythonIcon} data-language="python" data-word-wrap="" data-copy="">
<_components.pre icon={PythonIcon} tabIndex="0" data-language="python" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
</_components.pre>
{'\\n'}
<_components.pre icon={PythonIcon} data-language="py" data-word-wrap="" data-copy="">
<_components.pre icon={PythonIcon} tabIndex="0" data-language="py" data-word-wrap="" data-copy="">
<_components.code>
<_components.span> </_components.span>
</_components.code>
Expand Down
4 changes: 2 additions & 2 deletions packages/nextra/src/server/rehype-plugins/rehype-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ export const rehypeIcon: Plugin<[], any> =
isMdxJsEsm(node) && isImportDeclaration(node) && isImportFrom(node)
)

visit(ast, { tagName: 'div' }, (node: Element) => {
visit(ast, { tagName: 'figure' }, (node: Element) => {
const isRehypePrettyCode =
'data-rehype-pretty-code-fragment' in node.properties
'data-rehype-pretty-code-figure' in node.properties

if (!isRehypePrettyCode) return

Expand Down
36 changes: 8 additions & 28 deletions packages/nextra/src/server/rehype-plugins/rehype.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Element } from 'hast'
import type { Options as RehypePrettyCodeOptions } from 'rehype-pretty-code'
import { bundledLanguages, getHighlighter } from 'shiki'
import type { Plugin } from 'unified'
import { visit } from 'unist-util-visit'

Expand All @@ -24,30 +23,9 @@ export const DEFAULT_REHYPE_PRETTY_CODE_OPTIONS: RehypePrettyCodeOptions = {
delete node.properties['data-line']
},
filterMetaString: meta => meta.replace(CODE_BLOCK_FILENAME_REGEX, ''),
async getHighlighter(_opts) {
const DEFAULT_OPTS = {
themes: {
light: 'github-light',
dark: 'github-dark'
},
defaultColor: false
} as const

const highlighter = await getHighlighter({
themes: Object.values(DEFAULT_OPTS.themes),
langs: Object.keys(bundledLanguages)
})

const originalCodeToHtml = highlighter.codeToHtml

return Object.assign(highlighter, {
codeToHtml(code: string, lang: string) {
return originalCodeToHtml(code, { lang, ...DEFAULT_OPTS })
},
ansiToHtml(code: string) {
return this.codeToHtml(code, 'ansi')
}
})
theme: {
light: 'github-light',
dark: 'github-dark'
}
}

Expand Down Expand Up @@ -81,11 +59,10 @@ export const rehypeParseCodeMeta: Plugin<
}

export const rehypeAttachCodeMeta: Plugin<[], any> = () => ast => {
visit(ast, [{ tagName: 'div' }, { tagName: 'span' }], (node: Element) => {
visit(ast, [{ tagName: 'figure' }, { tagName: 'span' }], (node: Element) => {
const isRehypePrettyCode =
'data-rehype-pretty-code-fragment' in node.properties
'data-rehype-pretty-code-figure' in node.properties
if (!isRehypePrettyCode) return

// remove <div data-rehype-pretty-code-fragment /> element that wraps <pre /> element
// because we'll wrap with our own <div />
const preEl: PreElement = Object.assign(node, node.children[0])
Expand All @@ -108,6 +85,9 @@ export const rehypeAttachCodeMeta: Plugin<[], any> = () => ast => {
}
// @ts-expect-error fixme
if (preEl.type === 'mdxJsxFlowElement') {
if (node.properties.className === undefined)
delete node.properties.className
if (node.properties.style === undefined) delete node.properties.style
// @ts-expect-error fixme
preEl.attributes.push(
...Object.entries(node.properties).map(([name, value]) => ({
Expand Down
Loading

0 comments on commit 9f55bd1

Please sign in to comment.