diff --git a/app/components/Code/Viewer.vue b/app/components/Code/Viewer.vue index 90bcf0c22..2b1338db1 100644 --- a/app/components/Code/Viewer.vue +++ b/app/components/Code/Viewer.vue @@ -11,16 +11,38 @@ const emit = defineEmits<{ const codeRef = useTemplateRef('codeRef') -// Generate line numbers array -const lineNumbers = computed(() => { - return Array.from({ length: props.lines }, (_, i) => i + 1) -}) +// Using this so we can track the height of each line, and therefore compute digit sidebar +const lineMultipliers = ref([]) +const LINE_HEIGHT_PX = 24 // also used in css + +function updateLineMultipliers() { + if (!codeRef.value) return + const lines = Array.from(codeRef.value.querySelectorAll('code > .line')) + lineMultipliers.value = lines.map(line => + Math.max(1, Math.round(parseFloat(getComputedStyle(line).height) / LINE_HEIGHT_PX)), + ) +} -// Used for CSS calculation of line number column width -const lineDigits = computed(() => { - return String(props.lines).length +watch( + () => props.html, + () => nextTick(updateLineMultipliers), + { immediate: true }, +) +useResizeObserver(codeRef, updateLineMultipliers) + +// Line numbers ++ blank rows for the wrapped lines +const displayLines = computed(() => { + const result: (number | null)[] = [] + for (let i = 0; i < props.lines; i++) { + result.push(i + 1) + const extra = (lineMultipliers.value[i] ?? 1) - 1 + for (let j = 0; j < extra; j++) result.push(null) + } + return result }) +const lineDigits = computed(() => String(props.lines).length) + // Check if a line is selected function isLineSelected(lineNum: number): boolean { if (!props.selectedLines) return false @@ -86,36 +108,37 @@ watch(