@@ -11,16 +11,37 @@ const emit = defineEmits<{
1111
1212const codeRef = useTemplateRef (' codeRef' )
1313
14- // Generate line numbers array
15- const lineNumbers = computed (() => {
16- return Array .from ({ length: props .lines }, (_ , i ) => i + 1 )
17- })
14+ // Using this so we can track the height of each line, and therefore compute digit sidebar
15+ const lineMultipliers = ref <number []>([])
1816
19- // Used for CSS calculation of line number column width
20- const lineDigits = computed (() => {
21- return String (props .lines ).length
17+ function updateLineMultipliers() {
18+ if (! codeRef .value ) return
19+ const lines = Array .from (codeRef .value .querySelectorAll (' code > .line' ))
20+ lineMultipliers .value = lines
21+ .map (line => Math .round (parseFloat (getComputedStyle (line ).height ) / 24 )) // since each line "row" is 24px high
22+ .filter (m => m > 0 )
23+ }
24+
25+ watch (
26+ () => props .html ,
27+ () => nextTick (updateLineMultipliers ),
28+ { immediate: true },
29+ )
30+ useResizeObserver (codeRef , updateLineMultipliers )
31+
32+ // Line numbers ++ blank rows for the wrapped lines
33+ const displayLines = computed (() => {
34+ const result: (number | null )[] = []
35+ for (let i = 0 ; i < props .lines ; i ++ ) {
36+ result .push (i + 1 )
37+ const extra = (lineMultipliers .value [i ] ?? 1 ) - 1
38+ for (let j = 0 ; j < extra ; j ++ ) result .push (null )
39+ }
40+ return result
2241})
2342
43+ const lineDigits = computed (() => String (props .lines ).length )
44+
2445// Check if a line is selected
2546function isLineSelected(lineNum : number ): boolean {
2647 if (! props .selectedLines ) return false
@@ -93,22 +114,24 @@ watch(
93114 aria-hidden =" true"
94115 >
95116 <!-- This needs to be a native <a> element, because `LinkBase` (or specifically `NuxtLink`) does not seem to work when trying to prevent default behavior (jumping to the anchor) -->
96- <a
97- v-for =" lineNum in lineNumbers"
98- :id =" `L${lineNum}`"
99- :key =" lineNum"
100- :href =" `#L${lineNum}`"
101- tabindex =" -1"
102- class =" line-number block px-3 py-0 font-mono text-sm leading-6 cursor-pointer transition-colors no-underline"
103- :class =" [
104- isLineSelected(lineNum)
105- ? 'bg-yellow-500/20 text-fg'
106- : 'text-fg-subtle hover:text-fg-muted',
107- ]"
108- @click.prevent =" onLineClick(lineNum, $event)"
109- >
110- {{ lineNum }}
111- </a >
117+ <template v-for =" (lineNum , idx ) in displayLines " :key =" idx " >
118+ <a
119+ v-if =" lineNum !== null"
120+ :id =" `L${lineNum}`"
121+ :href =" `#L${lineNum}`"
122+ tabindex =" -1"
123+ class =" line-number block px-3 py-0 font-mono text-sm leading-6 cursor-pointer transition-colors no-underline"
124+ :class =" [
125+ isLineSelected(lineNum)
126+ ? 'bg-yellow-500/20 text-fg'
127+ : 'text-fg-subtle hover:text-fg-muted',
128+ ]"
129+ @click.prevent =" onLineClick(lineNum, $event)"
130+ >
131+ {{ lineNum }}
132+ </a >
133+ <span v-else class =" block px-3 leading-6" >  ; </span >
134+ </template >
112135 </div >
113136
114137 <!-- Code content -->
0 commit comments