mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-16 10:37:20 +02:00
feat(theme-classic): usable CodeBlock outside markdown (#6216)
This commit is contained in:
parent
96dbb8e7ef
commit
c45281a581
5 changed files with 53 additions and 18 deletions
|
@ -114,6 +114,7 @@ declare module '@theme/CodeBlock' {
|
||||||
readonly className?: string;
|
readonly className?: string;
|
||||||
readonly metastring?: string;
|
readonly metastring?: string;
|
||||||
readonly title?: string;
|
readonly title?: string;
|
||||||
|
readonly language?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CodeBlock: (props: Props) => JSX.Element;
|
const CodeBlock: (props: Props) => JSX.Element;
|
||||||
|
|
|
@ -24,9 +24,10 @@ import styles from './styles.module.css';
|
||||||
|
|
||||||
export default function CodeBlock({
|
export default function CodeBlock({
|
||||||
children,
|
children,
|
||||||
className: blockClassName,
|
className: blockClassName = '',
|
||||||
metastring,
|
metastring,
|
||||||
title,
|
title,
|
||||||
|
language: languageProp,
|
||||||
}: Props): JSX.Element {
|
}: Props): JSX.Element {
|
||||||
const {prism} = useThemeConfig();
|
const {prism} = useThemeConfig();
|
||||||
|
|
||||||
|
@ -85,8 +86,7 @@ export default function CodeBlock({
|
||||||
: (children as string);
|
: (children as string);
|
||||||
|
|
||||||
const language =
|
const language =
|
||||||
parseLanguage(blockClassName) ??
|
languageProp ?? parseLanguage(blockClassName) ?? prism.defaultLanguage;
|
||||||
(prism.defaultLanguage as Language | undefined);
|
|
||||||
const {highlightLines, code} = parseLines(content, metastring, language);
|
const {highlightLines, code} = parseLines(content, metastring, language);
|
||||||
|
|
||||||
const handleCopyCode = () => {
|
const handleCopyCode = () => {
|
||||||
|
@ -102,12 +102,16 @@ export default function CodeBlock({
|
||||||
key={String(mounted)}
|
key={String(mounted)}
|
||||||
theme={prismTheme}
|
theme={prismTheme}
|
||||||
code={code}
|
code={code}
|
||||||
language={language ?? ('text' as Language)}>
|
language={(language ?? 'text') as Language}>
|
||||||
{({className, style, tokens, getLineProps, getTokenProps}) => (
|
{({className, style, tokens, getLineProps, getTokenProps}) => (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
styles.codeBlockContainer,
|
styles.codeBlockContainer,
|
||||||
blockClassName,
|
blockClassName,
|
||||||
|
{
|
||||||
|
[`language-${language}`]:
|
||||||
|
language && !blockClassName.includes(`language-${language}`),
|
||||||
|
},
|
||||||
ThemeClassNames.common.codeBlock,
|
ThemeClassNames.common.codeBlock,
|
||||||
)}>
|
)}>
|
||||||
{codeBlockTitle && (
|
{codeBlockTitle && (
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import rangeParser from 'parse-numeric-range';
|
import rangeParser from 'parse-numeric-range';
|
||||||
import type {Language} from 'prism-react-renderer';
|
|
||||||
|
|
||||||
const codeBlockTitleRegex = /title=(["'])(.*?)\1/;
|
const codeBlockTitleRegex = /title=(["'])(.*?)\1/;
|
||||||
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
||||||
|
@ -93,11 +92,11 @@ export function parseCodeBlockTitle(metastring?: string): string {
|
||||||
return metastring?.match(codeBlockTitleRegex)?.[2] ?? '';
|
return metastring?.match(codeBlockTitleRegex)?.[2] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseLanguage(className?: string): Language | undefined {
|
export function parseLanguage(className: string): string | undefined {
|
||||||
const languageClassName = className
|
const languageClassName = className
|
||||||
?.split(' ')
|
.split(' ')
|
||||||
.find((str) => str.startsWith('language-'));
|
.find((str) => str.startsWith('language-'));
|
||||||
return languageClassName?.replace(/language-/, '') as Language | undefined;
|
return languageClassName?.replace(/language-/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +106,7 @@ export function parseLanguage(className?: string): Language | undefined {
|
||||||
export function parseLines(
|
export function parseLines(
|
||||||
content: string,
|
content: string,
|
||||||
metastring?: string,
|
metastring?: string,
|
||||||
language?: Language,
|
language?: string,
|
||||||
): {
|
): {
|
||||||
highlightLines: number[];
|
highlightLines: number[];
|
||||||
code: string;
|
code: string;
|
||||||
|
|
|
@ -6,6 +6,7 @@ slug: /markdown-features/code-blocks
|
||||||
---
|
---
|
||||||
|
|
||||||
import BrowserWindow from '@site/src/components/BrowserWindow';
|
import BrowserWindow from '@site/src/components/BrowserWindow';
|
||||||
|
import CodeBlock from '@theme/CodeBlock';
|
||||||
|
|
||||||
Code blocks within documentation are super-powered 💪.
|
Code blocks within documentation are super-powered 💪.
|
||||||
|
|
||||||
|
@ -391,7 +392,7 @@ function MyPlayground(props) {
|
||||||
|
|
||||||
</BrowserWindow>
|
</BrowserWindow>
|
||||||
|
|
||||||
## Using JSX markup in code blocks
|
## Using JSX markup in code blocks {using-jsx-markup}
|
||||||
|
|
||||||
Code block in Markdown always preserves its content as plain text, meaning you can't do something like:
|
Code block in Markdown always preserves its content as plain text, meaning you can't do something like:
|
||||||
|
|
||||||
|
@ -564,3 +565,39 @@ npm install @docusaurus/remark-plugin-npm2yarn
|
||||||
````
|
````
|
||||||
|
|
||||||
Using the `{sync: true}` option would make all tab choices synced. Because the choice is stored under the same namespace `npm2yarn`, different `npm2yarn` plugin instances would also sync their choices.
|
Using the `{sync: true}` option would make all tab choices synced. Because the choice is stored under the same namespace `npm2yarn`, different `npm2yarn` plugin instances would also sync their choices.
|
||||||
|
|
||||||
|
## Usage in JSX {#usage-in-jsx}
|
||||||
|
|
||||||
|
Outside of Markdown, you can use the `@theme/CodeBlock` component to get the same output.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import CodeBlock from '@theme/CodeBlock';
|
||||||
|
|
||||||
|
export default function MyReactPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* highlight-start */}
|
||||||
|
<CodeBlock language="jsx" title="/src/components/HelloCodeTitle.js">
|
||||||
|
{`function HelloCodeTitle(props) {
|
||||||
|
return <h1>Hello, {props.name}</h1>;
|
||||||
|
}`}
|
||||||
|
</CodeBlock>
|
||||||
|
{/* highlight-end */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<BrowserWindow>
|
||||||
|
<CodeBlock language="jsx" title="/src/components/HelloCodeTitle.js">
|
||||||
|
{`function HelloCodeTitle(props) {
|
||||||
|
return <h1>Hello, {props.name}</h1>;
|
||||||
|
}`}
|
||||||
|
</CodeBlock>
|
||||||
|
</BrowserWindow>
|
||||||
|
|
||||||
|
The props accepted are `language` and `title`, in the same way as you write Markdown code blocks.
|
||||||
|
|
||||||
|
Although discouraged, you can also pass in a `metastring` prop like `metastring='{1-2} title="/src/components/HelloCodeTitle.js"'`, which is how Markdown code blocks are handled under the hood. However, we recommend you [use comments for highlighting lines](#highlighting-with-comments).
|
||||||
|
|
||||||
|
As [previously stated](#using-jsx-markup), syntax highlighting is only applied when the children is a simple string.
|
||||||
|
|
|
@ -116,17 +116,11 @@ import MyComponentSource from '!!raw-loader!@site/src/pages/examples/_myComponen
|
||||||
<br />
|
<br />
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also pass `title` prop to `CodeBlock` component in order for it to appear as header above your code block:
|
See [using code blocks in JSX](./markdown-features-code-blocks.mdx#usage-in-jsx) for more details of the `<CodeBlock>` component.
|
||||||
|
|
||||||
```jsx
|
|
||||||
<CodeBlock className="language-jsx" title="/src/myComponent">
|
|
||||||
{MyComponentSource}
|
|
||||||
</CodeBlock>
|
|
||||||
```
|
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
|
|
||||||
You have to use `<CodeBlock>` rather than the Markdown triple-backtick ` ``` `, because the latter will ship out any of its content as-is, but you want JSX to insert the imported text here.
|
You have to use `<CodeBlock>` rather than the Markdown triple-backtick ` ``` `, because the latter will ship out any of its content as-is, but you want to interpolate the imported text here.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue