@@ -483,6 +483,16 @@ function initAnchorClipboard(){
483
483
}
484
484
485
485
function initCodeClipboard ( ) {
486
+ function getCodeText ( node ) {
487
+ var text = node . textContent ;
488
+ // remove a trailing line break, this may most likely
489
+ // come from the browser / Hugo transformation
490
+ text = text . replace ( / \n $ / , '' ) ;
491
+ // removes leading $ signs from text in an assumption
492
+ // that this has to be the unix prompt marker - weird
493
+ return text . replace ( / ^ \$ \s / gm, '' ) ;
494
+ }
495
+
486
496
function fallbackMessage ( action ) {
487
497
var actionMsg = '' ;
488
498
var actionKey = ( action === 'cut' ? 'X' : 'C' ) ;
@@ -498,34 +508,97 @@ function initCodeClipboard(){
498
508
return actionMsg ;
499
509
}
500
510
501
- var codeElements = document . querySelectorAll ( 'code' ) ;
511
+ if ( ! window . disableHighlightWrapFix ) {
512
+ // if the highlight shortcode was used with table lineno mode, the generated DOM
513
+ // is a table, containg exactly one row with two cells, the first cell for all linenos
514
+ // the second with the code;
515
+ // this does not look nice if the code gets wrapped around, so we reformat the table
516
+ // by creating a row for each line, containing the two cells but with only the content of
517
+ // one line
518
+ var codeTables = Array . from ( document . querySelectorAll ( 'code' ) ) . reduce ( function ( a , code ) {
519
+ // collect all tbody's without duplicates that need our treatment
520
+ if ( code . parentNode . tagName . toLowerCase ( ) == 'pre' &&
521
+ code . parentNode . parentNode . tagName . toLowerCase ( ) == 'td' &&
522
+ code . parentNode . parentNode . parentNode . tagName . toLowerCase ( ) == 'tr' &&
523
+ code . parentNode . parentNode . parentNode . parentNode . tagName . toLowerCase ( ) == 'tbody' &&
524
+ code . parentNode . parentNode . parentNode . querySelector ( 'td:first-child > pre > code' ) == code &&
525
+ ( ! a . length || a [ a . length - 1 ] != code . parentNode . parentNode . parentNode . parentNode ) ) {
526
+ var table = code . parentNode . parentNode . parentNode . parentNode ;
527
+ a . push ( table ) ;
528
+ }
529
+ return a ;
530
+ } , [ ] ) ;
531
+ for ( var i = 0 ; i < codeTables . length ; i ++ ) {
532
+ // now treat the table (tbody);
533
+ // first we collect some data, setting up our row template and collect the text
534
+ // representation of the code for later usage with copy-to-clipboard
535
+ var table = codeTables [ i ] ;
536
+ var text = getCodeText ( table . querySelector ( 'td:last-child code' ) ) ;
537
+ var tr = table . querySelector ( 'tr' ) . cloneNode ( ) ;
538
+ tr . appendChild ( table . querySelector ( 'td:first-child' ) . cloneNode ( ) )
539
+ . appendChild ( table . querySelector ( 'td:first-child pre' ) . cloneNode ( ) )
540
+ . appendChild ( table . querySelector ( 'td:first-child code' ) . cloneNode ( ) )
541
+ . classList . add ( 'nocode' ) ;
542
+ tr . appendChild ( table . querySelector ( 'td:last-child' ) . cloneNode ( ) )
543
+ . appendChild ( table . querySelector ( 'td:last-child pre' ) . cloneNode ( ) )
544
+ . appendChild ( table . querySelector ( 'td:last-child code' ) . cloneNode ( ) )
545
+ . classList . add ( 'nocode' ) ;
546
+
547
+ // select lineno and code cell of first line that contains all the content
548
+ var linenums = table . querySelectorAll ( 'td:first-child code > span' ) ;
549
+ var codes = table . querySelectorAll ( 'td:last-child code > span' ) ;
550
+ for ( var j = 0 ; j < linenums . length ; j ++ ) {
551
+ // now create a new table row by cloning our template
552
+ // and transfering the original content
553
+ var clonedTr = tr . cloneNode ( true ) ;
554
+ var code1 = clonedTr . querySelector ( 'td:first-child code' ) ;
555
+ var code2 = clonedTr . querySelector ( 'td:last-child code' ) ;
556
+ code1 . appendChild ( linenums [ j ] ) ;
557
+ code2 . appendChild ( codes [ j ] ) ;
558
+ table . appendChild ( clonedTr ) ;
559
+ }
560
+ // in the end we have an empty first row, that needs to be deleted
561
+ table . querySelector ( 'tr:first-child' ) . remove ( ) ;
562
+ // we delete the reformat marker of the first code cell to allow the
563
+ // copy-to-clipboard functionality
564
+ table . querySelector ( 'tr:first-child td:last-child code' ) . classList . remove ( 'nocode' ) ;
565
+ // put the text representation into a data attribute
566
+ table . querySelector ( 'tr:first-child td:last-child code' ) . dataset [ 'code' ] = text ;
567
+ // finally mark our tbody to apply special CSS styling
568
+ table . parentNode . parentNode . parentNode . classList . add ( 'wrapfix' ) ;
569
+ }
570
+ }
571
+
572
+ var codeElements = document . querySelectorAll ( 'code:not(.nocode)' ) ;
502
573
for ( var i = 0 ; i < codeElements . length ; i ++ ) {
503
574
var code = codeElements [ i ] ;
504
575
var text = code . textContent ;
505
576
var inPre = code . parentNode . tagName . toLowerCase ( ) == 'pre' ;
506
577
// avoid copy-to-clipboard for highlight shortcode in table lineno mode
507
- var isLineCell = inPre &&
578
+ var isFirstLineCell = inPre &&
508
579
code . parentNode . parentNode . tagName . toLowerCase ( ) == 'td' &&
509
- code . parentNode . parentNode . parentNode . querySelector ( 'td:nth -child(1) > pre > code' ) == code ;
580
+ code . parentNode . parentNode . parentNode . querySelector ( 'td:first -child > pre > code' ) == code ;
510
581
511
- if ( ! isLineCell && ( inPre || text . length > 5 ) ) {
582
+ if ( ! isFirstLineCell && ( inPre || text . length > 5 ) ) {
512
583
var clip = new ClipboardJS ( '.copy-to-clipboard-button' , {
513
584
text : function ( trigger ) {
514
585
if ( ! ( trigger . previousElementSibling && trigger . previousElementSibling . matches ( 'code' ) ) ) {
515
586
return '' ;
516
587
}
588
+ // if we already have a text representation, return it
589
+ var code = trigger . previousElementSibling ;
590
+ if ( code . dataset . code ) {
591
+ return code . dataset . code ;
592
+ }
517
593
// if highlight shortcode used in inline lineno mode, remove lineno nodes before generating text
518
- var code = trigger . previousElementSibling . cloneNode ( true ) ;
519
- Array . from ( code . querySelectorAll ( '*:scope > span > span:nth -child(1) :not(:last-child)' ) ) . forEach ( function ( lineno ) {
594
+ code = code . cloneNode ( true ) ;
595
+ Array . from ( code . querySelectorAll ( '*:scope > span > span:first -child:not(:last-child)' ) ) . forEach ( function ( lineno ) {
520
596
lineno . remove ( ) ;
521
597
} ) ;
522
- var text = code . textContent ;
523
- // remove a trailing line break, this may most likely
524
- // come from the browser / Hugo transformation
525
- text = text . replace ( / \n $ / , '' ) ;
526
- // removes leading $ signs from text in an assumption
527
- // that this has to be the unix prompt marker - weird
528
- return text . replace ( / ^ \$ \s / gm, '' ) ;
598
+ // generate and save generated text for repeated usage
599
+ var text = getCodeText ( code ) ;
600
+ trigger . previousElementSibling . dataset [ 'code' ] = text ;
601
+ return text ;
529
602
}
530
603
} ) ;
531
604
0 commit comments