Skip to content

Commit 90db482

Browse files
committed
highlight: simplify js implementation matcornic#169
1 parent 95f7b01 commit 90db482

File tree

5 files changed

+50
-97
lines changed

5 files changed

+50
-97
lines changed

exampleSite/content/tests/code/_index.en.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Some preformatted stuff in HTML elements
7575
#### %% %%
7676

7777
{{% tab title="json" %}}
78-
{{% highlight html "linenos=table,hl_lines=1 2,anchorlinenos=true" %}}
78+
{{% highlight html "hl_lines=1 2,anchorlinenos=true" %}}
7979
{
8080
"Hello": "World" "Hello": "World" "Hello": "World"
8181
}
@@ -85,7 +85,7 @@ Some preformatted stuff in HTML elements
8585
#### %% <>
8686

8787
{{% tab title="json" %}}
88-
{{< highlight html "linenos=table,hl_lines=1 2,anchorlinenos=true" >}}
88+
{{< highlight html "hl_lines=1 2,anchorlinenos=true" >}}
8989
{
9090
"Hello": "World" "Hello": "World" "Hello": "World"
9191
}

static/css/ie.css

+3
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
border-bottom-right-radius: 2px;
127127
border-bottom-left-radius: 0;
128128
}
129+
div.highlight > div table + .copy-to-clipboard-button,
129130
pre > .copy-to-clipboard-button {
130131
right: 4px;
131132
}
@@ -522,11 +523,13 @@
522523
color: rgba( 255, 250, 233, 1 ); /* var(--CODE-INLINE-BG-color) */
523524
}
524525

526+
div.highlight > div table + .copy-to-clipboard-button,
525527
pre .copy-to-clipboard-button {
526528
border-color: rgba( 216, 216, 216, 1 ); /* var(--CODE-BLOCK-BORDER-color) */
527529
color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
528530
}
529531

532+
div.highlight > div table + .copy-to-clipboard-button:hover,
530533
pre .copy-to-clipboard-button:hover {
531534
background-color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
532535
border-color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */

static/css/theme.css

+12-1
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ pre code {
670670
div.highlight > div{
671671
border-style: solid;
672672
border-width: 1px;
673+
position: relative;
673674
}
674675
/* remove default style for usual markdown tables */
675676
div.highlight > div table{
@@ -679,7 +680,6 @@ div.highlight > div table{
679680
}
680681
div.highlight > div td{
681682
border-width: 0;
682-
!padding: 0;
683683
}
684684
#body div.highlight > div a {
685685
line-height: inherit;
@@ -695,6 +695,14 @@ div.highlight > div td:first-child:not(:last-child){
695695
div.highlight > div td:not(:first-child):last-child{
696696
width: 100%;
697697
}
698+
/* add scrollbars if highlight shortcode was used in table lineno mode */
699+
div.highlight > div table{
700+
display: block;
701+
overflow: auto;
702+
}
703+
div.highlight > div td:not(:first-child):last-child pre code{
704+
white-space: pre;
705+
}
698706
/* remove border from row cells if highlight shortcode was used in table lineno mode */
699707
div.highlight > div td > pre {
700708
border-radius: 0;
@@ -1077,6 +1085,7 @@ html[dir="rtl"] #body #breadcrumbs {
10771085
border-width: 1px;
10781086
cursor: pointer;
10791087
font-size: .934375rem;
1088+
line-height: 1.15;
10801089
}
10811090

10821091
span > .copy-to-clipboard-button {
@@ -1091,11 +1100,13 @@ span > .copy-to-clipboard-button {
10911100
font-weight: 500;
10921101
}
10931102

1103+
div.highlight > div table + .copy-to-clipboard-button > i,
10941104
.copy-to-clipboard-code + .copy-to-clipboard-button > i {
10951105
padding-left: 5px;
10961106
padding-right: 5px;
10971107
}
10981108

1109+
div.highlight > div table + .copy-to-clipboard-button,
10991110
pre > .copy-to-clipboard-button {
11001111
background-color: rgba( 160, 160, 160, .2 );
11011112
border-radius: 2px;

static/css/variant.css

+2
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,13 @@ table {
272272
color: var(--INTERNAL-CODE-INLINE-BG-color);
273273
}
274274

275+
div.highlight > div table + .copy-to-clipboard-button,
275276
pre .copy-to-clipboard-button {
276277
border-color: var(--INTERNAL-CODE-BLOCK-BORDER-color);
277278
color: var(--INTERNAL-MAIN-LINK-color);
278279
}
279280

281+
div.highlight > div table + .copy-to-clipboard-button:hover,
280282
pre .copy-to-clipboard-button:hover {
281283
background-color: var(--INTERNAL-MAIN-LINK-color);
282284
border-color: var(--INTERNAL-MAIN-LINK-color);

static/js/theme.js

+31-94
Original file line numberDiff line numberDiff line change
@@ -484,13 +484,16 @@ function initAnchorClipboard(){
484484

485485
function initCodeClipboard(){
486486
function getCodeText( node ){
487-
var text = node.textContent;
487+
// if highlight shortcode is used in inline lineno mode, remove lineno nodes before generating text, otherwise it doesn't hurt
488+
var code = node.cloneNode( true );
489+
Array.from( code.querySelectorAll( '*:scope > span > span:first-child:not(:last-child)' ) ).forEach( function( lineno ){
490+
lineno.remove();
491+
});
492+
var text = code.textContent;
488493
// remove a trailing line break, this may most likely
489494
// come from the browser / Hugo transformation
490495
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, '' );
496+
return text;
494497
}
495498

496499
function fallbackMessage( action ){
@@ -508,114 +511,41 @@ function initCodeClipboard(){
508511
return actionMsg;
509512
}
510513

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)' );
514+
var codeElements = document.querySelectorAll( 'code' );
573515
for( var i = 0; i < codeElements.length; i++ ){
574516
var code = codeElements[i];
575-
var text = code.textContent;
517+
var text = getCodeText( code );
576518
var inPre = code.parentNode.tagName.toLowerCase() == 'pre';
519+
var inTable = inPre &&
520+
code.parentNode.parentNode.tagName.toLowerCase() == 'td';
577521
// avoid copy-to-clipboard for highlight shortcode in table lineno mode
578-
var isFirstLineCell = inPre &&
579-
code.parentNode.parentNode.tagName.toLowerCase() == 'td' &&
522+
var isFirstLineCell = inTable &&
580523
code.parentNode.parentNode.parentNode.querySelector( 'td:first-child > pre > code' ) == code;
581524

582525
if( !isFirstLineCell && ( inPre || text.length > 5 ) ){
583526
var clip = new ClipboardJS( '.copy-to-clipboard-button', {
584527
text: function( trigger ){
585-
if( !( trigger.previousElementSibling && trigger.previousElementSibling.matches( 'code' ) ) ){
528+
if( !trigger.previousElementSibling ){
586529
return '';
587530
}
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-
}
593-
// if highlight shortcode used in inline lineno mode, remove lineno nodes before generating text
594-
code = code.cloneNode( true );
595-
Array.from( code.querySelectorAll( '*:scope > span > span:first-child:not(:last-child)' ) ).forEach( function( lineno ){
596-
lineno.remove();
597-
});
598-
// generate and save generated text for repeated usage
599-
var text = getCodeText( code );
600-
trigger.previousElementSibling.dataset[ 'code' ] = text;
601-
return text;
531+
return trigger.previousElementSibling.dataset.code || '';
602532
}
603533
});
604534

605535
clip.on( 'success', function( e ){
606536
e.clearSelection();
607-
var inPre = e.trigger.parentNode.tagName.toLowerCase() == 'pre';
537+
var doBeside = e.trigger.parentNode.tagName.toLowerCase() == 'pre' || (e.trigger.previousElementSibling && e.trigger.previousElementSibling.tagName.toLowerCase() == 'table' );
608538
e.trigger.setAttribute( 'aria-label', window.T_Copied_to_clipboard );
609-
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (inPre ? 'w' : 's'+(isRtl?'e':'w')) );
539+
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (doBeside ? 'w' : 's'+(isRtl?'e':'w')) );
610540
});
611541

612542
clip.on( 'error', function( e ){
613-
var inPre = e.trigger.parentNode.tagName.toLowerCase() == 'pre';
543+
var doBeside = e.trigger.parentNode.tagName.toLowerCase() == 'pre' || (e.trigger.previousElementSibling && e.trigger.previousElementSibling.tagName.toLowerCase() == 'table' );
614544
e.trigger.setAttribute( 'aria-label', fallbackMessage(e.action) );
615-
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (inPre ? 'w' : 's'+(isRtl?'e':'w')) );
545+
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (doBeside ? 'w' : 's'+(isRtl?'e':'w')) );
616546
var f = function(){
617547
e.trigger.setAttribute( 'aria-label', window.T_Copied_to_clipboard );
618-
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (inPre ? 'w' : 's'+(isRtl?'e':'w')) );
548+
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (doBeside ? 'w' : 's'+(isRtl?'e':'w')) );
619549
document.removeEventListener( 'copy', f );
620550
};
621551
document.addEventListener( 'copy', f );
@@ -627,12 +557,11 @@ function initCodeClipboard(){
627557
code.parentNode.classList.add( 'pre-code' );
628558
}
629559
else{
630-
var clone = code.cloneNode( true );
560+
var parent = code.parentNode;
631561
var span = document.createElement( 'span' );
632562
span.classList.add( 'copy-to-clipboard' );
633-
span.appendChild( clone );
634-
code.parentNode.replaceChild( span, code );
635-
code = clone;
563+
span.appendChild( code );
564+
parent.appendChild( span );
636565
}
637566
var button = document.createElement( 'span' );
638567
button.classList.add( 'copy-to-clipboard-button' );
@@ -642,7 +571,15 @@ function initCodeClipboard(){
642571
this.removeAttribute( 'aria-label' );
643572
this.classList.remove( 'tooltipped', 'tooltipped-w', 'tooltipped-se', 'tooltipped-sw' );
644573
});
645-
code.parentNode.insertBefore( button, code.nextSibling );
574+
if( inTable ){
575+
var table = code.parentNode.parentNode.parentNode.parentNode.parentNode;
576+
table.dataset[ 'code' ] = text;
577+
table.parentNode.insertBefore( button, table.nextSibling );
578+
}
579+
else{
580+
code.dataset[ 'code' ] = text;
581+
code.parentNode.insertBefore( button, code.nextSibling );
582+
}
646583
}
647584
}
648585
}

0 commit comments

Comments
 (0)