@@ -179,7 +179,7 @@ export const CodeBlockHighlight: ExtensionAuto<CodeBlockHighlightOptions> = (bui
179179 let prevLineCount = 0 ;
180180
181181 if ( opts . lineNumbers ?. enabled ) {
182- const result = initializeLineNumbers ( node , code ) ;
182+ const result = manageLineNumbers ( node , code ) ;
183183 lineNumbersContainer = result . container ;
184184 prevLineCount = result . lineCount ;
185185 }
@@ -210,7 +210,7 @@ export const CodeBlockHighlight: ExtensionAuto<CodeBlockHighlightOptions> = (bui
210210 ) ;
211211
212212 if ( opts . lineNumbers ?. enabled ) {
213- const result = updateLineNumbers (
213+ const result = manageLineNumbers (
214214 newNode ,
215215 code ,
216216 lineNumbersContainer ,
@@ -296,102 +296,62 @@ function updateDomAttribute(elem: Element, attr: string, value: string | null |
296296 elem . removeAttribute ( attr ) ;
297297 }
298298}
299- function initializeLineNumbers (
300- node : Node ,
301- code : HTMLElement ,
302- ) : { container ?: HTMLDivElement ; lineCount : number } {
303- const showLineNumbers = node . attrs [ CodeBlockNodeAttr . ShowLineNumbers ] ;
304-
305- if ( ! showLineNumbers ) {
306- return { container : undefined , lineCount : 0 } ;
307- }
308-
309- const lineNumbersContainer = document . createElement ( 'div' ) ;
310- lineNumbersContainer . className = 'yfm-line-numbers' ;
311- lineNumbersContainer . contentEditable = 'false' ;
312-
313- const lines = node . textContent ? node . textContent . split ( '\n' ) : [ '' ] ;
314- const lineCount = lines . length ;
315299
316- appendLineNumbers ( lineNumbersContainer , 1 , lineCount ) ;
317-
318- code . prepend ( lineNumbersContainer ) ;
319- code . classList . add ( 'show-line-numbers' ) ;
320-
321- return { container : lineNumbersContainer , lineCount} ;
322- }
323-
324- function updateLineNumbers (
300+ function manageLineNumbers (
325301 node : Node ,
326302 code : HTMLElement ,
327- prevLineNumbersContainer ?: HTMLDivElement ,
303+ prevContainer ?: HTMLDivElement ,
328304 prevLineCount = 0 ,
329305) : { container ?: HTMLDivElement ; lineCount : number } {
330- const showLineNumbers = node . attrs [ CodeBlockNodeAttr . ShowLineNumbers ] ;
306+ const showLineNumbers = node . attrs [ CodeBlockNodeAttr . ShowLineNumbers ] === 'true' ;
331307
332- if ( ! prevLineNumbersContainer && showLineNumbers !== 'true' ) {
333- return { container : undefined , lineCount : 0 } ;
334- } else if ( ! prevLineNumbersContainer && showLineNumbers === 'true' ) {
335- return initializeLineNumbers ( node , code ) ;
336- } else if ( prevLineNumbersContainer && showLineNumbers !== 'true' ) {
337- code . removeChild ( prevLineNumbersContainer ) ;
338- code . classList . remove ( 'show-line-numbers' ) ;
308+ if ( ! showLineNumbers ) {
309+ if ( prevContainer ) {
310+ code . removeChild ( prevContainer ) ;
311+ code . classList . remove ( 'show-line-numbers' ) ;
312+ }
339313 return { container : undefined , lineCount : 0 } ;
340314 }
341315
342- if ( ! prevLineNumbersContainer ) {
343- return { container : prevLineNumbersContainer , lineCount : prevLineCount } ;
344- }
345-
346316 const lines = node . textContent ? node . textContent . split ( '\n' ) : [ '' ] ;
347317 const currentLineCount = lines . length ;
348318
349- code . classList . add ( 'show-line-numbers' ) ;
350-
351- if ( currentLineCount === prevLineCount ) {
352- return { container : prevLineNumbersContainer , lineCount : prevLineCount } ;
353- }
354-
355- if ( currentLineCount > prevLineCount ) {
356- appendLineNumbers ( prevLineNumbersContainer , prevLineCount + 1 , currentLineCount ) ;
357- } else if ( currentLineCount < prevLineCount ) {
358- removeExcessLineNumbers ( prevLineNumbersContainer , currentLineCount , prevLineCount ) ;
319+ let container = prevContainer ;
320+ if ( ! container ) {
321+ container = document . createElement ( 'div' ) ;
322+ container . className = 'yfm-line-numbers' ;
323+ container . contentEditable = 'false' ;
324+ code . prepend ( container ) ;
359325 }
360326
361- return { container : prevLineNumbersContainer , lineCount : currentLineCount } ;
362- }
363-
364- function appendLineNumbers ( container : HTMLDivElement , startLine : number , endLine : number ) {
365- const maxDigits = String ( endLine ) . length ;
327+ code . classList . add ( 'show-line-numbers' ) ;
366328
367- for ( let i = startLine ; i <= endLine ; i ++ ) {
368- const lineNumberElement = document . createElement ( 'div' ) ;
369- lineNumberElement . className = 'yfm-line-number' ;
370- lineNumberElement . textContent = String ( i ) . padStart ( maxDigits , ' ' ) ;
371- container . appendChild ( lineNumberElement ) ;
372- }
329+ if ( currentLineCount !== prevLineCount ) {
330+ const maxDigits = String ( currentLineCount ) . length ;
331+ const prevMaxDigits = String ( prevLineCount ) . length ;
373332
374- // Update padding on all line numbers if digit count changed
375- if ( startLine === 1 ) {
376- updateLineNumberPadding ( container , maxDigits ) ;
377- }
378- }
333+ if ( currentLineCount > prevLineCount ) {
334+ for ( let i = prevLineCount + 1 ; i <= currentLineCount ; i ++ ) {
335+ const lineNumberElement = document . createElement ( 'div' ) ;
336+ lineNumberElement . className = 'yfm-line-number' ;
337+ lineNumberElement . textContent = String ( i ) . padStart ( maxDigits , ' ' ) ;
338+ container . appendChild ( lineNumberElement ) ;
339+ }
340+ } else if ( currentLineCount < prevLineCount ) {
341+ for ( let i = prevLineCount ; i > currentLineCount ; i -- ) {
342+ if ( container . lastChild ) {
343+ container . removeChild ( container . lastChild ) ;
344+ }
345+ }
346+ }
379347
380- function removeExcessLineNumbers ( container : HTMLDivElement , keepCount : number , prevCount : number ) {
381- for ( let i = prevCount ; i > keepCount ; i -- ) {
382- if ( container . lastChild ) {
383- container . removeChild ( container . lastChild ) ;
348+ if ( maxDigits !== prevMaxDigits ) {
349+ Array . from ( container . children ) . forEach ( ( lineNumber , index ) => {
350+ const lineNum = index + 1 ;
351+ lineNumber . textContent = String ( lineNum ) . padStart ( maxDigits , ' ' ) ;
352+ } ) ;
384353 }
385354 }
386355
387- // Update padding on remaining line numbers if digit count changed
388- const maxDigits = String ( keepCount ) . length ;
389- updateLineNumberPadding ( container , maxDigits ) ;
390- }
391-
392- function updateLineNumberPadding ( container : HTMLDivElement , maxDigits : number ) {
393- Array . from ( container . children ) . forEach ( ( lineNumber , index ) => {
394- const lineNum = index + 1 ;
395- lineNumber . textContent = String ( lineNum ) . padStart ( maxDigits , ' ' ) ;
396- } ) ;
356+ return { container, lineCount : currentLineCount } ;
397357}
0 commit comments