Skip to content

Commit a3769cb

Browse files
committed
fix: shiki highlight line
Signed-off-by: Innei <[email protected]>
1 parent 65897b4 commit a3769cb

File tree

5 files changed

+59
-24
lines changed

5 files changed

+59
-24
lines changed

src/components/modules/toc/TocTree.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,12 @@ export const TocTree: Component<
7676
const toc: ITocItem[] = useMemo(() => {
7777
return Array.from($headings).map((el, idx) => {
7878
const depth = +el.tagName.slice(1)
79-
const title = el.textContent || ''
79+
const elClone = el.cloneNode(true) as HTMLElement
80+
elClone.querySelectorAll('del').forEach((del) => {
81+
del.remove()
82+
})
83+
84+
const title = elClone.textContent || ''
8085

8186
const index = idx
8287

src/components/ui/code-highlighter/CodeHighlighter.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { FC } from 'react'
88

99
import { useIsPrintMode } from '~/atoms/css-media'
1010
import { useIsDark } from '~/hooks/common/use-is-dark'
11+
import { stopPropagation } from '~/lib/dom'
1112
import { clsxm } from '~/lib/helper'
1213
import { loadScript, loadStyleSheet } from '~/lib/load-script'
1314
import { toast } from '~/lib/toast'
@@ -36,7 +37,7 @@ export const HighLighterPrismCdn: FC<Props> = (props) => {
3637
const ref = useRef<HTMLElement>(null)
3738
useLoadHighlighter(ref)
3839
return (
39-
<div className={styles['code-wrap']}>
40+
<div className={styles['code-wrap']} onCopy={stopPropagation}>
4041
<span className={styles['language-tip']} aria-hidden>
4142
{language?.toUpperCase()}
4243
</span>
@@ -70,6 +71,7 @@ export const BaseCodeHighlighter: Component<
7071
}, [content, lang])
7172
return (
7273
<pre
74+
onCopy={stopPropagation}
7375
className={clsxm('!bg-transparent', className)}
7476
style={style}
7577
data-start="1"

src/components/ui/code-highlighter/shiki/Shiki.module.css

+7-15
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,22 @@
1111
@apply flex flex-col;
1212
}
1313

14-
code {
15-
counter-reset: step;
16-
counter-increment: step 0;
17-
}
18-
1914
.shiki,
2015
code {
2116
@apply !bg-transparent;
2217
}
2318

2419
.line {
25-
@apply block min-h-[1em] px-4;
20+
@apply block min-h-[1em] px-5;
21+
22+
& > span:last-child {
23+
@apply mr-5;
24+
}
2625
}
2726

2827
.highlighted,
2928
.diff {
3029
@apply relative break-all;
31-
white-space: pre-wrap;
32-
word-wrap: break-word;
33-
overflow: auto;
3430

3531
&::before {
3632
@apply absolute left-0 top-0 h-full w-[2px];
@@ -67,19 +63,15 @@
6763
.highlighted {
6864
@apply bg-accent/20;
6965

70-
white-space: pre-wrap;
71-
word-wrap: break-word;
72-
overflow: auto;
73-
7466
&::before {
7567
@apply bg-accent;
7668
}
7769
}
7870
}
7971

8072
.scroll-container pre::-webkit-scrollbar-track {
81-
margin-left: 3rem;
82-
margin-right: 8rem;
73+
margin-left: 1rem;
74+
margin-right: var(--sr-margin, 0);
8375
}
8476

8577
.scroll-container pre::-webkit-scrollbar {

src/components/ui/code-highlighter/shiki/Shiki.tsx

+42-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { HighlighterCore } from 'shiki'
1414
import { getViewport } from '~/atoms/hooks'
1515
import { AutoResizeHeight } from '~/components/modules/shared/AutoResizeHeight'
1616
import { useMaskScrollArea } from '~/hooks/shared/use-mask-scrollarea'
17+
import { stopPropagation } from '~/lib/dom'
1718
import { clsxm } from '~/lib/helper'
1819

1920
import { MotionButtonBase } from '../../button'
@@ -97,15 +98,38 @@ export const ShikiHighLighter: FC<Props> = (props) => {
9798
}
9899
}, [value, codeBlockRef])
99100

100-
const renderedHtml = useMemo(() => {
101+
const highlightedHtml = useMemo(() => {
101102
if (!highlighter) return ''
102103
return codeHighlighter(highlighter, {
103104
attrs: attrs || '',
105+
// code: `${value.split('\n')[0].repeat(10)} // [!code highlight]\n${value}`,
104106
code: value,
105107
lang: language ? language.toLowerCase() : '',
106108
})
107109
}, [attrs, language, value, highlighter])
108110

111+
const [renderedHtml, setRenderedHtml] = useState(highlightedHtml)
112+
useEffect(() => {
113+
setRenderedHtml(highlightedHtml)
114+
requestAnimationFrame(() => {
115+
if (!highlightedHtml) return
116+
if (!codeBlockRef) return
117+
118+
const $lines = codeBlockRef.querySelectorAll('.line')
119+
const maxLineWidth = Math.max(
120+
...Array.from($lines).map((el) => {
121+
return (el as HTMLElement).scrollWidth
122+
}),
123+
)
124+
$lines.forEach((el) => {
125+
;(el as HTMLElement).style.width = `${maxLineWidth}px`
126+
})
127+
128+
const pre = codeBlockRef.querySelector('pre')
129+
if (pre) setRenderedHtml(pre.outerHTML)
130+
})
131+
}, [codeBlockRef, highlightedHtml])
132+
109133
const filename = useMemo(() => {
110134
return parseFilenameFromAttrs(attrs || '')
111135
}, [attrs])
@@ -114,10 +138,15 @@ export const ShikiHighLighter: FC<Props> = (props) => {
114138
size: 'lg',
115139
})
116140

141+
const hasHeader = !!filename
142+
117143
return (
118-
<div className={clsx(styles['code-card'], 'group')}>
144+
<div
145+
className={clsx(styles['code-card'], 'group')}
146+
onCopy={stopPropagation}
147+
>
119148
{!!filename && (
120-
<div className="z-10 flex w-full items-center justify-between rounded-t-xl bg-accent/20 px-4 py-2 text-sm">
149+
<div className="z-10 flex w-full items-center justify-between rounded-t-xl bg-accent/20 px-5 py-2 text-sm">
121150
<span className="shrink-0 flex-grow truncate">{filename}</span>
122151
<span
123152
className="pointer-events-none flex-shrink-0 flex-grow-0"
@@ -136,7 +165,7 @@ export const ShikiHighLighter: FC<Props> = (props) => {
136165
{language.toUpperCase()}
137166
</div>
138167
)}
139-
<div className="bg-accent/10 py-4">
168+
<div className="bg-accent/5 py-4">
140169
<MotionButtonBase
141170
onClick={handleCopy}
142171
className={clsx(
@@ -156,6 +185,13 @@ export const ShikiHighLighter: FC<Props> = (props) => {
156185
!isCollapsed ? '!max-h-[100%]' : isOverflow ? maskClassName : '',
157186
styles['scroll-container'],
158187
)}
188+
style={
189+
{
190+
'--sr-margin': !hasHeader
191+
? `${(language?.length || 0) + 1}em`
192+
: '1rem',
193+
} as any
194+
}
159195
dangerouslySetInnerHTML={
160196
renderedHtml
161197
? {
@@ -165,8 +201,8 @@ export const ShikiHighLighter: FC<Props> = (props) => {
165201
}
166202
>
167203
{renderedHtml ? undefined : (
168-
<pre className="bg-transparent px-4">
169-
<code className="!px-4">{value}</code>
204+
<pre className="bg-transparent px-5">
205+
<code className="!px-5">{value}</code>
170206
</pre>
171207
)}
172208
</div>

src/components/ui/link/MLink.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const MLink: FC<{
5050
type="tooltip"
5151
TriggerComponent={useCallback(
5252
() => (
53-
<span className="inline items-center">
53+
<span className="inline items-center font-sans">
5454
<Favicon href={href} />
5555
<a
5656
className="shiro-link--underline"

0 commit comments

Comments
 (0)