feat(theme): code block showLineNumbers=start metastring (#10846)

This commit is contained in:
Sébastien Lorber 2025-01-16 17:28:04 +01:00 committed by GitHub
parent fcc9e5c56a
commit e59355be76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 74 additions and 25 deletions

View file

@ -412,7 +412,7 @@ declare module '@theme/CodeBlock' {
readonly metastring?: string;
readonly title?: string;
readonly language?: string;
readonly showLineNumbers?: boolean;
readonly showLineNumbers?: boolean | number;
}
export default function CodeBlock(props: Props): ReactNode;

View file

@ -12,7 +12,7 @@ import {
parseCodeBlockTitle,
parseLanguage,
parseLines,
containsLineNumbers,
getLineNumbersStart,
useCodeWordWrap,
} from '@docusaurus/theme-common/internal';
import {Highlight, type Language} from 'prism-react-renderer';
@ -59,8 +59,10 @@ export default function CodeBlockString({
language,
magicComments,
});
const showLineNumbers =
showLineNumbersProp ?? containsLineNumbers(metastring);
const lineNumbersStart = getLineNumbersStart({
showLineNumbers: showLineNumbersProp,
metastring,
});
return (
<Container
@ -87,8 +89,14 @@ export default function CodeBlockString({
<code
className={clsx(
styles.codeBlockLines,
showLineNumbers && styles.codeBlockLinesWithNumbering,
)}>
lineNumbersStart !== undefined &&
styles.codeBlockLinesWithNumbering,
)}
style={
lineNumbersStart === undefined
? undefined
: {counterReset: `line-count ${lineNumbersStart - 1}`}
}>
{tokens.map((line, i) => (
<Line
key={i}
@ -96,7 +104,7 @@ export default function CodeBlockString({
getLineProps={getLineProps}
getTokenProps={getTokenProps}
classNames={lineClassNames[i]}
showLineNumbers={showLineNumbers}
showLineNumbers={lineNumbersStart !== undefined}
/>
))}
</code>

View file

@ -37,7 +37,7 @@ export {
parseCodeBlockTitle,
parseLanguage,
parseLines,
containsLineNumbers,
getLineNumbersStart,
} from './utils/codeBlockUtils';
export {DEFAULT_SEARCH_TAG} from './utils/searchUtils';

View file

@ -151,8 +151,37 @@ export function parseCodeBlockTitle(metastring?: string): string {
return metastring?.match(codeBlockTitleRegex)?.groups!.title ?? '';
}
export function containsLineNumbers(metastring?: string): boolean {
return Boolean(metastring?.includes('showLineNumbers'));
function getMetaLineNumbersStart(metastring?: string): number | undefined {
const showLineNumbersMeta = metastring
?.split(' ')
.find((str) => str.startsWith('showLineNumbers'));
if (showLineNumbersMeta) {
if (showLineNumbersMeta.startsWith('showLineNumbers=')) {
const value = showLineNumbersMeta.replace('showLineNumbers=', '');
return parseInt(value, 10);
}
return 1;
}
return undefined;
}
export function getLineNumbersStart({
showLineNumbers,
metastring,
}: {
showLineNumbers: boolean | number | undefined;
metastring: string | undefined;
}): number | undefined {
const defaultStart = 1;
if (typeof showLineNumbers === 'boolean') {
return showLineNumbers ? defaultStart : undefined;
}
if (typeof showLineNumbers === 'number') {
return showLineNumbers;
}
return getMetaLineNumbersStart(metastring);
}
/**

View file

@ -395,18 +395,12 @@ The `Line` component will receive the list of class names, based on which you ca
You can enable line numbering for your code block by using `showLineNumbers` key within the language meta string (don't forget to add space directly before the key).
````md
```jsx {1,4-6,11} showLineNumbers
```jsx showLineNumbers
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
export default function MyComponent(props) {
return <div>Foo</div>;
}
export default MyComponent;
```
````
@ -414,18 +408,36 @@ export default MyComponent;
<BrowserWindow>
```
```jsx {1,4-6,11} showLineNumbers
```jsx showLineNumbers
import React from 'react';
function MyComponent(props) {
if (props.isBar) {
return <div>Bar</div>;
}
export default function MyComponent(props) {
return <div>Foo</div>;
}
```
export default MyComponent;
```mdx-code-block
</BrowserWindow>
```
By default, the counter starts at line number 1. It's possible to pass a custom counter start value to split large code blocks for readability:
````md
```jsx showLineNumbers=3
export default function MyComponent(props) {
return <div>Foo</div>;
}
```
````
```mdx-code-block
<BrowserWindow>
```
```jsx showLineNumbers=3
export default function MyComponent(props) {
return <div>Foo</div>;
}
```
```mdx-code-block