docusaurus/packages/docusaurus-theme-classic/src/theme/CodeBlock/Content/String.tsx
Sébastien Lorber 5273a534d3
refactor(theme-classic): split CodeBlock (#7175)
* extract CodeBlockLine

* stable refactor

* stable refactor

* stable refactor

* add CodeBlockContainer

* refactor

* refactor

* do the actual split

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
2022-04-15 17:58:12 +08:00

94 lines
3 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import {
useThemeConfig,
parseCodeBlockTitle,
parseLanguage,
parseLines,
containsLineNumbers,
usePrismTheme,
} from '@docusaurus/theme-common';
import clsx from 'clsx';
import Highlight, {defaultProps, type Language} from 'prism-react-renderer';
import Line from '@theme/CodeBlock/Line';
import CopyButton from '@theme/CodeBlock/CopyButton';
import Container from '@theme/CodeBlock/Container';
import type {Props} from '@theme/CodeBlock/Content/String';
import styles from './styles.module.css';
export default function CodeBlockString({
children,
className: blockClassName = '',
metastring,
title: titleProp,
showLineNumbers: showLineNumbersProp,
language: languageProp,
}: Props): JSX.Element {
const {
prism: {defaultLanguage},
} = useThemeConfig();
const language =
languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage;
const prismTheme = usePrismTheme();
// We still parse the metastring in case we want to support more syntax in the
// future. Note that MDX doesn't strip quotes when parsing metastring:
// "title=\"xyz\"" => title: "\"xyz\""
const title = parseCodeBlockTitle(metastring) || titleProp;
const {highlightLines, code} = parseLines(children, metastring, language);
const showLineNumbers =
showLineNumbersProp || containsLineNumbers(metastring);
return (
<Container
as="div"
className={clsx(
blockClassName,
language &&
!blockClassName.includes(`language-${language}`) &&
`language-${language}`,
)}>
{title && <div className={styles.codeBlockTitle}>{title}</div>}
<div className={styles.codeBlockContent}>
<Highlight
{...defaultProps}
theme={prismTheme}
code={code}
language={(language ?? 'text') as Language}>
{({className, tokens, getLineProps, getTokenProps}) => (
<pre
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
tabIndex={0}
className={clsx(className, styles.codeBlock, 'thin-scrollbar')}>
<code
className={clsx(
styles.codeBlockLines,
showLineNumbers && styles.codeBlockLinesWithNumbering,
)}>
{tokens.map((line, i) => (
<Line
key={i}
line={line}
getLineProps={getLineProps}
getTokenProps={getTokenProps}
highlight={highlightLines.includes(i)}
showLineNumbers={showLineNumbers}
/>
))}
</code>
</pre>
)}
</Highlight>
<CopyButton code={code} />
</div>
</Container>
);
}