From bcb8cbf3c839dc17c1eaee7e39edb3ecca236a27 Mon Sep 17 00:00:00 2001 From: Alexey Iskhakov Date: Tue, 14 Feb 2023 22:28:47 +0400 Subject: [PATCH] fix: custom titles of code snippets inside code groups (#1834) Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> --- docs/guide/markdown.md | 28 ++++++++++++++++++++++++ src/node/markdown/plugins/lineNumbers.ts | 9 ++++++-- src/node/markdown/plugins/preWrapper.ts | 12 ++++++---- src/node/markdown/plugins/snippet.ts | 20 ++++++++++++----- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/docs/guide/markdown.md b/docs/guide/markdown.md index 7520d7226896..1d59336e526a 100644 --- a/docs/guide/markdown.md +++ b/docs/guide/markdown.md @@ -651,6 +651,34 @@ export default config ::: +You can also [import snippets](#import-code-snippets) in code groups: + +**Input** + +```md +::: code-group + + + +<<< @/snippets/snippet.js + + + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: +``` + +**Output** + +::: code-group + +<<< @/snippets/snippet.js + +<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] + +::: + ## Markdown File Inclusion You can include a markdown file in another markdown file like this: diff --git a/src/node/markdown/plugins/lineNumbers.ts b/src/node/markdown/plugins/lineNumbers.ts index a1830b8fdbfc..73efa944a61f 100644 --- a/src/node/markdown/plugins/lineNumbers.ts +++ b/src/node/markdown/plugins/lineNumbers.ts @@ -24,8 +24,13 @@ export const lineNumberPlugin = (md: MarkdownIt, enable = false) => { ) const lines = code.split('\n') - const lineNumbersCode = [...Array(lines.length - 1)] - .map((line, index) => `${index + 1}
`) + + const lineNumbersCode = [ + ...Array( + lines.length - (lines.at(-1) === `` ? 1 : 0) + ) + ] + .map((_, index) => `${index + 1}
`) .join('') const lineNumbersWrapperCode = `` diff --git a/src/node/markdown/plugins/preWrapper.ts b/src/node/markdown/plugins/preWrapper.ts index 10f57d2d3cfd..623204778a7d 100644 --- a/src/node/markdown/plugins/preWrapper.ts +++ b/src/node/markdown/plugins/preWrapper.ts @@ -3,11 +3,15 @@ import type MarkdownIt from 'markdown-it' export function preWrapperPlugin(md: MarkdownIt) { const fence = md.renderer.rules.fence! md.renderer.rules.fence = (...args) => { - const { info } = args[0][args[1]] - const lang = extractLang(info) + const [tokens, idx] = args + const token = tokens[idx] + // remove title from info + token.info = token.info.replace(/\[.*\]/, '') + + const lang = extractLang(token.info) const rawCode = fence(...args) return `
${lang}${rawCode}
` } } @@ -19,7 +23,7 @@ export function extractTitle(info: string) { const extractLang = (info: string) => { return info .trim() - .replace(/:(no-)?line-numbers$/, '') + .replace(/:(no-)?line-numbers({| |$).*/, '') .replace(/(-vue|{| ).*$/, '') .replace(/^vue-html$/, 'template') } diff --git a/src/node/markdown/plugins/snippet.ts b/src/node/markdown/plugins/snippet.ts index 7d82296933a1..f0b0bf5214e0 100644 --- a/src/node/markdown/plugins/snippet.ts +++ b/src/node/markdown/plugins/snippet.ts @@ -95,10 +95,10 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => { * where #region and {meta} are optional * and meta can be like '1,2,4-6 lang', 'lang' or '1,2,4-6' * - * captures: ['/path/to/file.extension', 'extension', '#region', '{meta}'] + * captures: ['/path/to/file.extension', 'extension', '#region', '{meta}', '[title]'] */ const rawPathRegexp = - /^(.+(?:\.([a-z0-9]+)))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))?$/ + /^(.+(?:\.([a-z0-9]+)))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))? ?(?:\[(.+)\])?$/ const rawPath = state.src .slice(start, end) @@ -106,13 +106,23 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => { .replace(/^@/, srcDir) .trim() - const [filename = '', extension = '', region = '', lines = '', lang = ''] = - (rawPathRegexp.exec(rawPath) || []).slice(1) + const [ + filename = '', + extension = '', + region = '', + lines = '', + lang = '', + rawTitle = '' + ] = (rawPathRegexp.exec(rawPath) || []).slice(1) + + const title = rawTitle || filename.split('/').at(-1) || '' state.line = startLine + 1 const token = state.push('fence', 'code', 0) - token.info = `${lang || extension}${lines ? `{${lines}}` : ''}` + token.info = `${lang || extension}${lines ? `{${lines}}` : ''}${ + title ? `[${title}]` : '' + }` // @ts-ignore token.src = path.resolve(filename) + region