Skip to content

Commit

Permalink
feat(theme): code block showLineNumbers=start metastring (#10846)
Browse files Browse the repository at this point in the history
  • Loading branch information
slorber committed Jan 17, 2025
1 parent 605107e commit 678c6cd
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 24 deletions.
2 changes: 1 addition & 1 deletion packages/docusaurus-theme-classic/src/theme-classic.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
parseCodeBlockTitle,
parseLanguage,
parseLines,
containsLineNumbers,
getLineNumbersStart,
useCodeWordWrap,
} from '@docusaurus/theme-common/internal';
import {Highlight, type Language} from 'prism-react-renderer';
Expand Down Expand Up @@ -59,8 +59,10 @@ export default function CodeBlockString({
language,
magicComments,
});
const showLineNumbers =
showLineNumbersProp ?? containsLineNumbers(metastring);
const lineNumbersStart = getLineNumbersStart({
showLineNumbers: showLineNumbersProp,
metastring,
});

return (
<Container
Expand All @@ -87,16 +89,22 @@ 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}
line={line}
getLineProps={getLineProps}
getTokenProps={getTokenProps}
classNames={lineClassNames[i]}
showLineNumbers={showLineNumbers}
showLineNumbers={lineNumbersStart !== undefined}
/>
))}
</code>
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus-theme-common/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export {
parseCodeBlockTitle,
parseLanguage,
parseLines,
containsLineNumbers,
getLineNumbersStart,
} from './utils/codeBlockUtils';

export {DEFAULT_SEARCH_TAG} from './utils/searchUtils';
Expand Down
33 changes: 31 additions & 2 deletions packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,37 +395,49 @@ 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;
```
````

```mdx-code-block
<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>;
}
```

```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>;
}
```
````

export default MyComponent;
```mdx-code-block
<BrowserWindow>
```

```jsx showLineNumbers=3
export default function MyComponent(props) {
return <div>Foo</div>;
}
```

```mdx-code-block
Expand Down

0 comments on commit 678c6cd

Please sign in to comment.