Skip to content

Commit

Permalink
fix: improve transformers
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Nov 22, 2023
1 parent 543c2b7 commit 182dc80
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 82 deletions.
39 changes: 16 additions & 23 deletions packages/shikiji-transformers/src/transformers/notation-diff.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import type { ShikijiTransformer } from 'shikiji'
import { addClassToHast } from 'shikiji'
import { createCommentNotationTransformer } from '../utils'
import { transformerNotationMap } from './notation-map'

export interface TransformerNotationDiffOptions {
/**
* Class for added lines
*/
classAdded?: string
classLineAdd?: string
/**
* Class for removed lines
*/
classRemoved?: string
classLineRemove?: string
/**
* Class added to the root element when the current code has diff
* Class added to the <pre> element when the current code has diff
*/
classRootActive?: string
classActivePre?: string
}

/**
Expand All @@ -24,27 +25,19 @@ export function transformerNotationDiff(
options: TransformerNotationDiffOptions = {},
): ShikijiTransformer {
const {
classAdded = 'diff add',
classRemoved = 'diff remove',
classRootActive = 'has-diff',
classLineAdd = 'diff add',
classLineRemove = 'diff remove',
classActivePre = 'has-diff',
} = options

return createCommentNotationTransformer(
'shikiji-transformers:notation-diff',
/\[!code (\-\-|\+\+)(:\d+)?\]/,
function ([_, match, range = ':1'], _line, _comment, lines, index) {
const className = match === '--'
? classRemoved
: classAdded
const lineNum = Number.parseInt(range.slice(1), 10)
lines
.slice(index, index + lineNum)
.forEach((line) => {
addClassToHast(line, className)
})
if (classRootActive)
addClassToHast(this.pre, classRootActive)
return true
return transformerNotationMap(
{
classMap: {
'++': classLineAdd,
'--': classLineRemove,
},
classActivePre,
},
'shikiji-transformers:notation-diff',
)
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import type { ShikijiTransformer } from 'shikiji'
import { addClassToHast } from 'shikiji'
import { createCommentNotationTransformer } from '../utils'
import { transformerNotationMap } from './notation-map'

export interface TransformerNotationErrorLevelOptions {
classMap?: Record<string, string | string[]>
/**
* Class added to the <pre> element when the current code has diff
*/
classActivePre?: string
}

/**
Expand All @@ -17,19 +22,14 @@ export function transformerNotationErrorLevel(
error: ['highlighted', 'error'],
warning: ['highlighted', 'warning'],
},
classActivePre = 'has-highlighted',
} = options

return createCommentNotationTransformer(
'shikiji-transformers:notation-error-level',
new RegExp(`\\[!code (${Object.keys(classMap).join('|')})(:\\d+)?\\]`),
([_, match, range = ':1'], _line, _comment, lines, index) => {
const lineNum = Number.parseInt(range.slice(1), 10)
lines
.slice(index, index + lineNum)
.forEach((line) => {
addClassToHast(line, classMap[match])
})
return true
return transformerNotationMap(
{
classMap,
classActivePre,
},
'shikiji-transformers:notation-error-level',
)
}
29 changes: 12 additions & 17 deletions packages/shikiji-transformers/src/transformers/notation-focus.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import type { ShikijiTransformer } from 'shikiji'
import { addClassToHast } from 'shikiji'
import { createCommentNotationTransformer } from '../utils'
import { transformerNotationMap } from './notation-map'

export interface TransformerNotationFocusOptions {
/**
* Class for focused lines
*/
classFocused?: string
classActiveLine?: string
/**
* Class added to the root element when the code has focused lines
*/
classRootActive?: string
classActivePre?: string
}

/**
Expand All @@ -20,23 +21,17 @@ export function transformerNotationFocus(
options: TransformerNotationFocusOptions = {},
): ShikijiTransformer {
const {
classFocused = 'focused',
classRootActive = 'has-focused',
classActiveLine = 'focused',
classActivePre = 'has-focused',
} = options

return createCommentNotationTransformer(
'shikiji-transformers:notation-focus',
/\[!code focus(:\d+)?\]/,
function ([_, range = ':1'], _line, _comment, lines, index) {
const lineNum = Number.parseInt(range.slice(1), 10)
lines
.slice(index, index + lineNum)
.forEach((line) => {
addClassToHast(line, classFocused)
})
if (classRootActive)
addClassToHast(this.pre, classRootActive)
return true
return transformerNotationMap(
{
classMap: {
focus: classActiveLine,
},
classActivePre,
},
'shikiji-transformers:notation-focus',
)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import type { ShikijiTransformer } from 'shikiji'
import { addClassToHast } from 'shikiji'
import { createCommentNotationTransformer } from '../utils'
import { transformerNotationMap } from './notation-map'

export interface TransformerNotationHighlightOptions {
/**
* Class for highlighted lines
*/
classHighlight?: string
classActiveLine?: string
/**
* Class added to the root element when the code has highlighted lines
*/
classRootActive?: string
classActivePre?: string
}

/**
Expand All @@ -20,23 +21,18 @@ export function transformerNotationHighlight(
options: TransformerNotationHighlightOptions = {},
): ShikijiTransformer {
const {
classHighlight = 'highlighted',
classRootActive = 'has-highlighted',
classActiveLine = 'highlighted',
classActivePre = 'has-highlighted',
} = options

return createCommentNotationTransformer(
'shikiji-transformers:notation-highlight',
/\[!code (?:hl|highlight)(:\d+)?\]/,
function ([_, range = ':1'], _line, _comment, lines, index) {
const lineNum = Number.parseInt(range.slice(1), 10)
lines
.slice(index, index + lineNum)
.forEach((line) => {
addClassToHast(line, classHighlight)
})
if (classRootActive)
addClassToHast(this.pre, classRootActive)
return true
return transformerNotationMap(
{
classMap: {
highlight: classActiveLine,
hl: classActiveLine,
},
classActivePre,
},
'shikiji-transformers:notation-highlight',
)
}
41 changes: 41 additions & 0 deletions packages/shikiji-transformers/src/transformers/notation-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ShikijiTransformer } from 'shikiji'
import { addClassToHast } from 'shikiji'
import { createCommentNotationTransformer } from '../utils'

export interface TransformerNotationMapOptions {
classMap?: Record<string, string | string[]>
/**
* Class added to the <pre> element when the current code has diff
*/
classActivePre?: string
}

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

export function transformerNotationMap(
options: TransformerNotationMapOptions = {},
name = 'shikiji-transformers:notation-map',
): ShikijiTransformer {
const {
classMap = {},
classActivePre = undefined,
} = options

return createCommentNotationTransformer(
name,
new RegExp(`\\s*(?://|/\\*|<!--|#)\\s+\\[!code (${Object.keys(classMap).map(escapeRegExp).join('|')})(:\\d+)?\\]\\s*(?:\\*/|-->)?`),
function ([_, match, range = ':1'], _line, _comment, lines, index) {
const lineNum = Number.parseInt(range.slice(1), 10)
lines
.slice(index, index + lineNum)
.forEach((line) => {
addClassToHast(line, classMap[match])
})
if (classActivePre)
addClassToHast(this.pre, classActivePre)
return true
},
)
}
17 changes: 8 additions & 9 deletions packages/shikiji-transformers/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function createCommentNotationTransformer(
regex: RegExp,
onMatch: (
this: ShikijiTransformerContext,
match: RegExpMatchArray,
match: string[],
line: Element,
commentNode: Element,
lines: Element[],
Expand All @@ -39,18 +39,17 @@ export function createCommentNotationTransformer(
for (const child of line.children) {
if (child.type !== 'element')
continue
if (!isCommentLike(child, line))
continue
const text = child.children[0]
if (text.type !== 'text')
continue
const match = text.value.match(regex)
if (!match)
continue
if (onMatch.call(this, match, line, child, lines, idx)) {

text.value = text.value.replace(regex, (...match) => {
if (onMatch.call(this, match, line, child, lines, idx))
return ''
return match[0]
})
if (!text.value.trim())
nodeToRemove = child
break
}
}
if (nodeToRemove)
line.children.splice(line.children.indexOf(nodeToRemove), 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<pre class="shiki github-dark" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> foo</span><span style="color:#E1E4E8">() {</span></span><span class="line highlighted error"><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'error'</span><span style="color:#E1E4E8">) </span></span><span class="line highlighted warning"><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'warn'</span><span style="color:#E1E4E8">) </span></span><span class="line"><span style="color:#E1E4E8">}</span></span><span class="line"></span></code></pre>
<pre class="shiki github-dark has-highlighted" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> foo</span><span style="color:#E1E4E8">() {</span></span><span class="line highlighted error"><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'error'</span><span style="color:#E1E4E8">) </span></span><span class="line highlighted warning"><span style="color:#E1E4E8"> console.</span><span style="color:#B392F0">log</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'warn'</span><span style="color:#E1E4E8">) </span></span><span class="line"><span style="color:#E1E4E8">}</span></span><span class="line"></span></code></pre>
<style>
body { margin: 0; }
.shiki { padding: 1em; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export function transformerNotationFocus(
) {
const {
classFocused = 'focused',
classRootActive = 'has-focused',
classActivePre = 'has-focused',
} = options
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<pre class="shiki github-dark has-focused" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> transformerNotationFocus</span><span style="color:#E1E4E8">(</span></span><span class="line focused"><span style="color:#FFAB70"> options</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {}, </span></span><span class="line focused"><span style="color:#E1E4E8">) {</span></span><span class="line focused"><span style="color:#F97583"> const</span><span style="color:#E1E4E8"> {</span></span><span class="line focused"><span style="color:#79B8FF"> classFocused</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#79B8FF"> classRootActive</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'has-focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> options</span></span><span class="line"><span style="color:#E1E4E8">}</span></span><span class="line"></span></code></pre>
<pre class="shiki github-dark has-focused" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> transformerNotationFocus</span><span style="color:#E1E4E8">(</span></span><span class="line focused"><span style="color:#FFAB70"> options</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {}, </span></span><span class="line focused"><span style="color:#E1E4E8">) {</span></span><span class="line focused"><span style="color:#F97583"> const</span><span style="color:#E1E4E8"> {</span></span><span class="line focused"><span style="color:#79B8FF"> classFocused</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#79B8FF"> classActivePre</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'has-focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> options</span></span><span class="line"><span style="color:#E1E4E8">}</span></span><span class="line"></span></code></pre>
<style>
body { margin: 0; }
.shiki { padding: 1em; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export function transformerNotationFocus(
) {
const {
classFocused = 'focused',
classRootActive = 'has-focused',
classActivePre = 'has-focused',
} = options
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<pre class="shiki github-dark has-highlighted" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> transformerNotationFocus</span><span style="color:#E1E4E8">(</span></span><span class="line highlighted"><span style="color:#FFAB70"> options</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {}, </span></span><span class="line highlighted"><span style="color:#E1E4E8">) {</span></span><span class="line highlighted"><span style="color:#F97583"> const</span><span style="color:#E1E4E8"> {</span></span><span class="line highlighted"><span style="color:#79B8FF"> classFocused</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#79B8FF"> classRootActive</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'has-focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> options</span></span><span class="line"><span style="color:#E1E4E8">}</span></span><span class="line"></span></code></pre>
<pre class="shiki github-dark has-highlighted" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> function</span><span style="color:#B392F0"> transformerNotationFocus</span><span style="color:#E1E4E8">(</span></span><span class="line highlighted"><span style="color:#FFAB70"> options</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {}, </span></span><span class="line highlighted"><span style="color:#E1E4E8">) {</span></span><span class="line highlighted"><span style="color:#F97583"> const</span><span style="color:#E1E4E8"> {</span></span><span class="line highlighted"><span style="color:#79B8FF"> classFocused</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#79B8FF"> classActivePre</span><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> 'has-focused'</span><span style="color:#E1E4E8">,</span></span><span class="line"><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> options</span></span><span class="line"><span style="color:#E1E4E8">}</span></span><span class="line"></span></code></pre>
<style>
body { margin: 0; }
.shiki { padding: 1em; }
Expand Down

0 comments on commit 182dc80

Please sign in to comment.