Skip to content

Commit f62fefe

Browse files
committed
fix: track line digits as well
1 parent a6e9ca5 commit f62fefe

File tree

1 file changed

+46
-23
lines changed

1 file changed

+46
-23
lines changed

app/components/Code/Viewer.vue

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,37 @@ const emit = defineEmits<{
1111
1212
const 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
2546
function 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">&nbsp;</span>
134+
</template>
112135
</div>
113136

114137
<!-- Code content -->

0 commit comments

Comments
 (0)