@@ -3,13 +3,15 @@ const props = defineProps<{
33 html: string
44 lines: number
55 selectedLines: { start: number ; end: number } | null
6+ wordWrap? : boolean
67}>()
78
89const emit = defineEmits <{
910 lineClick: [lineNum : number , event : MouseEvent ]
1011}>()
1112
1213const codeRef = useTemplateRef (' codeRef' )
14+ const lineNumbersRef = useTemplateRef (' lineNumbersRef' )
1315
1416// Generate line numbers array
1517const lineNumbers = computed (() => {
@@ -32,6 +34,30 @@ function onLineClick(lineNum: number, event: MouseEvent) {
3234 emit (' lineClick' , lineNum , event )
3335}
3436
37+ // Synchronize line number heights with code line heights (needed for word wrap)
38+ function syncLineHeights() {
39+ if (! props .wordWrap || ! codeRef .value || ! lineNumbersRef .value ) {
40+ // Reset heights if word wrap is disabled
41+ if (lineNumbersRef .value ) {
42+ const nums = lineNumbersRef .value .querySelectorAll <HTMLElement >(' .line-number' )
43+ nums .forEach (num => (num .style .height = ' ' ))
44+ }
45+ return
46+ }
47+
48+ const lines = codeRef .value .querySelectorAll <HTMLElement >(' code > .line' )
49+ const nums = lineNumbersRef .value .querySelectorAll <HTMLElement >(' .line-number' )
50+
51+ lines .forEach ((line , index ) => {
52+ const num = nums [index ]
53+ if (num ) {
54+ // Use getBoundingClientRect for more precision if needed, but offsetHeight is usually enough
55+ const height = line .offsetHeight
56+ num .style .height = ` ${height }px `
57+ }
58+ })
59+ }
60+
3561// Apply highlighting to code lines when selection changes
3662function updateLineHighlighting() {
3763 if (! codeRef .value ) return
@@ -53,11 +79,27 @@ function updateLineHighlighting() {
5379watch (
5480 () => [props .selectedLines , props .html ] as const ,
5581 () => {
56- nextTick (updateLineHighlighting )
82+ nextTick (() => {
83+ updateLineHighlighting ()
84+ syncLineHeights ()
85+ })
5786 },
5887 { immediate: true },
5988)
6089
90+ // Also watch wordWrap specifically
91+ watch (
92+ () => props .wordWrap ,
93+ () => {
94+ nextTick (syncLineHeights )
95+ },
96+ )
97+
98+ // Sync on resize
99+ if (import .meta .client ) {
100+ useEventListener (window , ' resize' , syncLineHeights )
101+ }
102+
61103// Use Nuxt's `navigateTo` for the rendered import links
62104function handleImportLinkNavigate() {
63105 if (! codeRef .value ) return
@@ -86,9 +128,10 @@ watch(
86128 </script >
87129
88130<template >
89- <div class =" code-viewer flex min-h-full max-w-full" >
131+ <div class =" code-viewer flex min-h-full max-w-full" :class = " { 'is-wrapped': wordWrap } " >
90132 <!-- Line numbers column -->
91133 <div
134+ ref =" lineNumbersRef"
92135 class =" line-numbers shrink-0 bg-bg-subtle border-ie border-solid border-border text-end select-none relative"
93136 :style =" { '--line-digits': lineDigits }"
94137 aria-hidden =" true"
@@ -155,6 +198,12 @@ watch(
155198 transition : background-color 0.1s ;
156199}
157200
201+ .is-wrapped .code-content :deep(.line ) {
202+ white-space : pre-wrap ;
203+ word-break : break-all ;
204+ max-height : none ;
205+ }
206+
158207/* Highlighted lines in code content - extend full width with negative margin */
159208.code-content :deep(.line.highlighted ) {
160209 @apply bg-yellow- 500/20;
0 commit comments