Skip to content

feat: support for customizing the starting line number in a code block #2917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion docs/guide/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ Please see [`markdown` options](../reference/site-config#markdown) for more deta

You can add `:line-numbers` / `:no-line-numbers` mark in your fenced code blocks to override the value set in config.

You can also customize the starting line number by adding `=` after `:line-numbers`. For example, `:line-numbers=2` means the line numbers in code blocks will start from `2`.

**Input**

````md
Expand All @@ -524,6 +526,12 @@ const line3 = 'This is line 3'
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```

```ts:line-numbers=2 {1}
// line-numbers is enabled and start from 2
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```
````

**Output**
Expand All @@ -540,6 +548,12 @@ const line2 = 'This is line 2'
const line3 = 'This is line 3'
```

```ts:line-numbers=2 {1}
// line-numbers is enabled and start from 2
const line3 = 'This is line 3'
const line4 = 'This is line 4'
````

## Import Code Snippets

You can import code snippets from existing files via following syntax:
Expand All @@ -566,7 +580,7 @@ It also supports [line highlighting](#line-highlighting-in-code-blocks):

**Output**

<<< @/snippets/snippet.js{2}
<<< @/snippets/snippet.js

::: tip
The value of `@` corresponds to the source root. By default it's the VitePress project root, unless `srcDir` is configured. Alternatively, you can also import from relative paths:
Expand Down
2 changes: 1 addition & 1 deletion src/node/markdown/plugins/highlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export async function highlight(
const styleRE = /<pre[^>]*(style=".*?")/
const preRE = /^<pre(.*?)>/
const vueRE = /-vue$/
const lineNoRE = /:(no-)?line-numbers$/
const lineNoRE = /:(no-)?line-numbers(=\d*)?$/
const mustacheRE = /\{\{.*?\}\}/g

return (str: string, lang: string, attrs: string) => {
Expand Down
13 changes: 11 additions & 2 deletions src/node/markdown/plugins/lineNumbers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ export const lineNumberPlugin = (md: MarkdownIt, enable = false) => {
const info = tokens[idx].info

if (
(!enable && !/:line-numbers($| )/.test(info)) ||
(!enable && !/:line-numbers($| |=)/.test(info)) ||
(enable && /:no-line-numbers($| )/.test(info))
) {
return rawCode
}

let startLineNumber = 1
const matchStartLineNumber = info.match(/:line-numbers=(\d*)/)
if (matchStartLineNumber && matchStartLineNumber[1]) {
startLineNumber = parseInt(matchStartLineNumber[1])
}

const code = rawCode.slice(
rawCode.indexOf('<code>'),
rawCode.indexOf('</code>')
Expand All @@ -26,7 +32,10 @@ export const lineNumberPlugin = (md: MarkdownIt, enable = false) => {
const lines = code.split('\n')

const lineNumbersCode = [...Array(lines.length)]
.map((_, index) => `<span class="line-number">${index + 1}</span><br>`)
.map(
(_, index) =>
`<span class="line-number">${index + startLineNumber}</span><br>`
)
.join('')

const lineNumbersWrapperCode = `<div class="line-numbers-wrapper" aria-hidden="true">${lineNumbersCode}</div>`
Expand Down
2 changes: 1 addition & 1 deletion src/node/markdown/plugins/preWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function extractTitle(info: string, html = false) {
function extractLang(info: string) {
return info
.trim()
.replace(/:(no-)?line-numbers({| |$).*/, '')
.replace(/:(no-)?line-numbers({| |$|=\d*).*/, '')
.replace(/(-vue|{| ).*$/, '')
.replace(/^vue-html$/, 'template')
.replace(/^ansi$/, '')
Expand Down