Skip to content

Commit

Permalink
chore: tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Mister-Hope committed May 20, 2024
1 parent 0b28076 commit a0d124c
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 102 deletions.
17 changes: 7 additions & 10 deletions plugins/plugin-prismjs/src/node/parser/notation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@
* - `// [!code ++:3]`
* - ...more
*/
import { escapeRegExp } from '../utils/index.js'
import type { NodeOpen, Parser } from './parse.js'

const commentEmptyTag = /<span class="token comment">\s*?<\/span>/
const COMMENT_EMPTY_TAG = /<span class="token comment">\s*?<\/span>/

const toArray = <T>(value: T | T[]): T[] =>
Array.isArray(value) ? value : [value]

export interface NotationOption {
classMap: Record<string, string | string[]>
classPre?: string
Expand Down Expand Up @@ -57,7 +62,7 @@ export const notationBase = (parser: Parser, options: NotationOption): void => {
})
if (
replaced &&
!(node.content = node.content.replace(commentEmptyTag, '')).trim()
!(node.content = node.content.replace(COMMENT_EMPTY_TAG, '')).trim()
) {
nodeRemove.push(node)
}
Expand All @@ -66,14 +71,6 @@ export const notationBase = (parser: Parser, options: NotationOption): void => {
parser.lines.splice(parser.lines.indexOf(node), 1)
}

function escapeRegExp(str: string): string {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}

function toArray<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value]
}

/**
* line highlight
*
Expand Down
3 changes: 3 additions & 0 deletions plugins/plugin-prismjs/src/node/parser/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ export interface Parser {
const splitLines = (code: string): string[] => {
const parts = code.split(SPLIT_RE)
const lines: string[] = []

for (let i = 0; i < parts.length; i += 2) {
lines.push(parts[i])
}

return lines
}

Expand All @@ -54,6 +56,7 @@ const createNodeOpen = (
classes: string[] = [],
): NodeOpen => {
const match = html.match(CLASS_RE)

if (!match) {
const hashHtml = html.length > 1
return {
Expand Down
2 changes: 2 additions & 0 deletions plugins/plugin-prismjs/src/node/utils/escapeRegExp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const escapeRegExp = (str: string): string =>
str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
1 change: 1 addition & 0 deletions plugins/plugin-prismjs/src/node/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './escapeRegExp.js'
export * from './languages.js'
export * from './resolveLanguage.js'
export * from './resolveAttr.js'
Expand Down
114 changes: 22 additions & 92 deletions plugins/plugin-shiki/src/node/resolveHighlight.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
import {
transformerCompactLineOptions,
transformerNotationDiff,
transformerNotationErrorLevel,
transformerNotationFocus,
transformerNotationHighlight,
} from '@shikijs/transformers'
import type { ShikiTransformer } from 'shiki'
import { transformerCompactLineOptions } from '@shikijs/transformers'
import {
bundledLanguages,
getHighlighter,
isPlainLang,
isSpecialLang,
} from 'shiki'
import { colors, logger } from 'vuepress/utils'
import { getTransformers } from './transformers/getTransformers.js'
import type { ShikiPluginOptions } from './types.js'
import { attrsToLines, nanoid, resolveLanguage } from './utils.js'

const DEFAULT_LANGS = Object.keys(bundledLanguages)

const RE_ESCAPE = /\[\\!code/g
const mustacheRE = /\{\{.*?\}\}/g
const MUSTACHE_REG = /\{\{[\s\S]*?\}\}/g

export const resolveHighlight = async ({
langs = DEFAULT_LANGS,
Expand All @@ -38,50 +31,7 @@ export const resolveHighlight = async ({

await options.shikiSetup?.(highlighter)

const transformers: ShikiTransformer[] = []

if (options.notationDiff) {
transformers.push(transformerNotationDiff())
}

if (options.notationFocus) {
transformers.push(
transformerNotationFocus({
classActiveLine: 'has-focus',
classActivePre: 'has-focused-lines',
}),
)
}

if (options.notationHighlight) {
transformers.push(transformerNotationHighlight())
}

if (options.notationErrorLevel) {
transformers.push(transformerNotationErrorLevel())
}

transformers.push(
...([
{
name: 'vuepress:add-class',
pre(node) {
this.addClassToHast(node, 'vp-code')
},
},
{
name: 'vuepress:clean-up',
pre(node) {
delete node.properties.tabindex
delete node.properties.style
},
},
{
name: 'vuepress:remove-escape',
postprocess: (code) => code.replace(RE_ESCAPE, '[!code'),
},
] as ShikiTransformer[]),
)
const transformers = getTransformers(options)

return (str, language, attrs) => {
let lang = resolveLanguage(language)
Expand All @@ -98,60 +48,40 @@ export const resolveHighlight = async ({
}
}

const codeTransformers: ShikiTransformer[] = [
{
name: 'vuepress:empty-line',
code(hast) {
hast.children.forEach((span) => {
if (
span.type === 'element' &&
span.tagName === 'span' &&
Array.isArray(span.properties.class) &&
span.properties.class.includes('line') &&
span.children.length === 0
) {
span.children.push({
type: 'element',
tagName: 'wbr',
properties: {},
children: [],
})
}
})
},
},
]

if (options.highlightLines ?? true) {
codeTransformers.push(transformerCompactLineOptions(attrsToLines(attrs)))
}
const codeMustaches = new Map<string, string>()

const mustaches = new Map<string, string>()
const removeMustache = (str: string): string =>
str.replace(MUSTACHE_REG, (match) => {
let marker = codeMustaches.get(match)

const removeMustache = (s: string): string => {
return s.replace(mustacheRE, (match) => {
let marker = mustaches.get(match)
if (!marker) {
marker = nanoid()
mustaches.set(match, marker)
codeMustaches.set(match, marker)
}

return marker
})
}

const restoreMustache = (s: string): string => {
mustaches.forEach((marker, match) => {
s = s.replaceAll(marker, match)
const restoreMustache = (str: string): string => {
codeMustaches.forEach((marker, match) => {
str = str.replaceAll(marker, match)
})
return s

return str
}

str = removeMustache(str).trimEnd()

const highlighted = highlighter.codeToHtml(str, {
lang,
meta: { __raw: attrs },
transformers: [...transformers, ...codeTransformers, ...userTransformers],
transformers: [
...transformers,
...(options.highlightLines ?? true
? [transformerCompactLineOptions(attrsToLines(attrs))]
: []),
...userTransformers,
],
...(themes ? { themes, defaultColor: options.defaultColor } : { theme }),
})

Expand Down
50 changes: 50 additions & 0 deletions plugins/plugin-shiki/src/node/transformers/getTransformers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
transformerNotationDiff,
transformerNotationErrorLevel,
transformerNotationFocus,
transformerNotationHighlight,
} from '@shikijs/transformers'
import type { ShikiTransformer } from 'shiki'
import type { ShikiPluginOptions } from '../types.js'
import {
addClassTransformer,
cleanUpTransformer,
emptyLineTransformer,
removeEscapeTransformer,
} from './vuepressTransformers.js'

export const getTransformers = (
options: ShikiPluginOptions,
): ShikiTransformer[] => {
const transformers: ShikiTransformer[] = []

if (options.notationDiff) {
transformers.push(transformerNotationDiff())
}

if (options.notationFocus) {
transformers.push(
transformerNotationFocus({
classActiveLine: 'has-focus',
classActivePre: 'has-focused-lines',
}),
)
}

if (options.notationHighlight) {
transformers.push(transformerNotationHighlight())
}

if (options.notationErrorLevel) {
transformers.push(transformerNotationErrorLevel())
}

transformers.push(
addClassTransformer,
cleanUpTransformer,
removeEscapeTransformer,
emptyLineTransformer,
)

return transformers
}
2 changes: 2 additions & 0 deletions plugins/plugin-shiki/src/node/transformers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './getTransformers.js'
export * from './vuepressTransformers.js'
47 changes: 47 additions & 0 deletions plugins/plugin-shiki/src/node/transformers/vuepressTransformers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { ShikiTransformer } from 'shiki'

const ESCAPE_RE = /\[\\!code/g

export const addClassTransformer: ShikiTransformer = {
name: 'vuepress:add-class',
pre(node) {
this.addClassToHast(node, 'vp-code')
},
}

export const cleanUpTransformer: ShikiTransformer = {
name: 'vuepress:clean-up',
pre(node) {
delete node.properties.tabindex
delete node.properties.style
},
}

export const removeEscapeTransformer: ShikiTransformer = {
name: 'vuepress:remove-escape',
postprocess(code) {
return code.replace(ESCAPE_RE, '[!code')
},
}

export const emptyLineTransformer: ShikiTransformer = {
name: 'vuepress:empty-line',
code(hast) {
hast.children.forEach((span) => {
if (
span.type === 'element' &&
span.tagName === 'span' &&
Array.isArray(span.properties.class) &&
span.properties.class.includes('line') &&
span.children.length === 0
) {
span.children.push({
type: 'element',
tagName: 'wbr',
properties: {},
children: [],
})
}
})
},
}

0 comments on commit a0d124c

Please sign in to comment.