Skip to content

Commit

Permalink
refactor(build): replace the line highlighting logic with Shiki lineO…
Browse files Browse the repository at this point in the history
…ptions (#1152)
  • Loading branch information
Jinjiang committed Aug 9, 2022
1 parent 93fe820 commit e8cb73e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 54 deletions.
23 changes: 7 additions & 16 deletions src/client/theme-default/styles/components/vp-doc.css
Original file line number Diff line number Diff line change
Expand Up @@ -310,30 +310,21 @@
}

.vp-doc [class*='language-'] code {
display: block;
padding: 0 24px;
width: fit-content;
display: flex;
width: max-content;
min-width: 100%;
flex-direction: column;
line-height: var(--vp-code-line-height);
font-size: var(--vp-code-font-size);
color: var(--vp-code-block-color);
transition: color 0.5s;
}

.vp-doc .highlight-lines {
position: absolute;
top: 0;
bottom: 0;
left: 0;
padding-top: 16px;
width: 100%;
line-height: var(--vp-code-line-height);
font-family: var(--vp-font-family-mono);
font-size: var(--vp-code-font-size);
user-select: none;
overflow: hidden;
.vp-doc [class*='language-'] code .line {
padding: 0 24px;
}

.vp-doc .highlight-lines .highlighted {
.vp-doc [class*='language-'] code .highlighted {
background-color: var(--vp-code-line-highlight-color);
transition: background-color 0.5s;
}
Expand Down
47 changes: 41 additions & 6 deletions src/node/markdown/plugins/highlight.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,40 @@
import { IThemeRegistration, getHighlighter } from 'shiki'
import { IThemeRegistration, getHighlighter, HtmlRendererOptions } from 'shiki'
import type { ThemeOptions } from '../markdown'

export async function highlight(theme: ThemeOptions = 'material-palenight') {
/**
* 2 steps:
*
* 1. convert attrs into line numbers:
* {4,7-13,16,23-27,40} -> [4,7,8,9,10,11,12,13,16,23,24,25,26,27,40]
* 2. convert line numbers into line options:
* [{ line: number, classes: string[] }]
*/
const attrsToLines = (attrs: string): HtmlRendererOptions['lineOptions'] => {
const result: number[] = []
if (!attrs.trim()) {
return []
}
attrs
.split(',')
.map((v) => v.split('-').map((v) => parseInt(v, 10)))
.forEach(([start, end]) => {
if (start && end) {
result.push(
...Array.from({ length: end - start + 1 }, (_, i) => start + i)
)
} else {
result.push(start)
}
})
return result.map((v) => ({
line: v,
classes: ['highlighted']
}))
}

export async function highlight(
theme: ThemeOptions = 'material-palenight'
): Promise<(str: string, lang: string, attrs: string) => string> {
const hasSingleTheme = typeof theme === 'string' || 'name' in theme
const getThemeName = (themeValue: IThemeRegistration) =>
typeof themeValue === 'string' ? themeValue : themeValue.name
Expand All @@ -12,22 +45,24 @@ export async function highlight(theme: ThemeOptions = 'material-palenight') {
const preRE = /^<pre.*?>/
const vueRE = /-vue$/

return (str: string, lang: string) => {
return (str: string, lang: string, attrs: string) => {
const vPre = vueRE.test(lang) ? '' : 'v-pre'
lang = lang.replace(vueRE, '').toLowerCase()

const lineOptions = attrsToLines(attrs)

if (hasSingleTheme) {
return highlighter
.codeToHtml(str, { lang, theme: getThemeName(theme) })
.codeToHtml(str, { lang, lineOptions, theme: getThemeName(theme) })
.replace(preRE, `<pre ${vPre}>`)
}

const dark = highlighter
.codeToHtml(str, { lang, theme: getThemeName(theme.dark) })
.codeToHtml(str, { lang, lineOptions, theme: getThemeName(theme.dark) })
.replace(preRE, `<pre ${vPre} class="vp-code-dark">`)

const light = highlighter
.codeToHtml(str, { lang, theme: getThemeName(theme.light) })
.codeToHtml(str, { lang, lineOptions, theme: getThemeName(theme.light) })
.replace(preRE, `<pre ${vPre} class="vp-code-light">`)

return dark + light
Expand Down
38 changes: 6 additions & 32 deletions src/node/markdown/plugins/highlightLines.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Modified from https://github.com/egoist/markdown-it-highlight-lines
// Now this plugin is only used to normalize line attrs.
// The else part of line highlights logic is in './highlight.ts'.

import MarkdownIt from 'markdown-it'

const RE = /{([\d,-]+)}/
const wrapperRE = /^<pre .*?><code>/

export const highlightLinePlugin = (md: MarkdownIt) => {
const fence = md.renderer.rules.fence!
md.renderer.rules.fence = (...args) => {
const [tokens, idx, options] = args
const [tokens, idx] = args
const token = tokens[idx]

// due to use of markdown-it-attrs, the {0} syntax would have been
Expand Down Expand Up @@ -40,35 +42,7 @@ export const highlightLinePlugin = (md: MarkdownIt) => {
}
}

const lineNumbers = lines
.split(',')
.map((v) => v.split('-').map((v) => parseInt(v, 10)))

const code = options.highlight
? options.highlight(token.content, token.info, '')
: token.content

const rawCode = code.replace(wrapperRE, '')

const highlightLinesCode = rawCode
.split('\n')
.map((split, index) => {
const lineNumber = index + 1
const inRange = lineNumbers.some(([start, end]) => {
if (start && end) {
return lineNumber >= start && lineNumber <= end
}
return lineNumber === start
})
if (inRange) {
return `<div class="highlighted">&nbsp;</div>`
}
return '<br>'
})
.join('')

const highlightLinesWrapperCode = `<div class="highlight-lines">${highlightLinesCode}</div>`

return highlightLinesWrapperCode + code
token.info += ' ' + lines
return fence(...args)
}
}

0 comments on commit e8cb73e

Please sign in to comment.