mirror of
https://github.com/McShelby/hugo-theme-relearn.git
synced 2024-11-27 01:33:04 +00:00
highlight: simplify js implementation #169
This commit is contained in:
parent
95f7b0107e
commit
90db4823dc
5 changed files with 50 additions and 97 deletions
|
@ -75,7 +75,7 @@ Some preformatted stuff in HTML elements
|
||||||
#### %% %%
|
#### %% %%
|
||||||
|
|
||||||
{{% tab title="json" %}}
|
{{% tab title="json" %}}
|
||||||
{{% highlight html "linenos=table,hl_lines=1 2,anchorlinenos=true" %}}
|
{{% highlight html "hl_lines=1 2,anchorlinenos=true" %}}
|
||||||
{
|
{
|
||||||
"Hello": "World" "Hello": "World" "Hello": "World"
|
"Hello": "World" "Hello": "World" "Hello": "World"
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ Some preformatted stuff in HTML elements
|
||||||
#### %% <>
|
#### %% <>
|
||||||
|
|
||||||
{{% tab title="json" %}}
|
{{% tab title="json" %}}
|
||||||
{{< highlight html "linenos=table,hl_lines=1 2,anchorlinenos=true" >}}
|
{{< highlight html "hl_lines=1 2,anchorlinenos=true" >}}
|
||||||
{
|
{
|
||||||
"Hello": "World" "Hello": "World" "Hello": "World"
|
"Hello": "World" "Hello": "World" "Hello": "World"
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
border-bottom-right-radius: 2px;
|
border-bottom-right-radius: 2px;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
}
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button,
|
||||||
pre > .copy-to-clipboard-button {
|
pre > .copy-to-clipboard-button {
|
||||||
right: 4px;
|
right: 4px;
|
||||||
}
|
}
|
||||||
|
@ -522,11 +523,13 @@
|
||||||
color: rgba( 255, 250, 233, 1 ); /* var(--CODE-INLINE-BG-color) */
|
color: rgba( 255, 250, 233, 1 ); /* var(--CODE-INLINE-BG-color) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button,
|
||||||
pre .copy-to-clipboard-button {
|
pre .copy-to-clipboard-button {
|
||||||
border-color: rgba( 216, 216, 216, 1 ); /* var(--CODE-BLOCK-BORDER-color) */
|
border-color: rgba( 216, 216, 216, 1 ); /* var(--CODE-BLOCK-BORDER-color) */
|
||||||
color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
|
color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button:hover,
|
||||||
pre .copy-to-clipboard-button:hover {
|
pre .copy-to-clipboard-button:hover {
|
||||||
background-color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
|
background-color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
|
||||||
border-color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
|
border-color: rgba( 72, 106, 201, 1 ); /* var(--MAIN-LINK-color) */
|
||||||
|
|
|
@ -670,6 +670,7 @@ pre code {
|
||||||
div.highlight > div{
|
div.highlight > div{
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
/* remove default style for usual markdown tables */
|
/* remove default style for usual markdown tables */
|
||||||
div.highlight > div table{
|
div.highlight > div table{
|
||||||
|
@ -679,7 +680,6 @@ div.highlight > div table{
|
||||||
}
|
}
|
||||||
div.highlight > div td{
|
div.highlight > div td{
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
!padding: 0;
|
|
||||||
}
|
}
|
||||||
#body div.highlight > div a {
|
#body div.highlight > div a {
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
|
@ -695,6 +695,14 @@ div.highlight > div td:first-child:not(:last-child){
|
||||||
div.highlight > div td:not(:first-child):last-child{
|
div.highlight > div td:not(:first-child):last-child{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
/* add scrollbars if highlight shortcode was used in table lineno mode */
|
||||||
|
div.highlight > div table{
|
||||||
|
display: block;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
div.highlight > div td:not(:first-child):last-child pre code{
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
/* remove border from row cells if highlight shortcode was used in table lineno mode */
|
/* remove border from row cells if highlight shortcode was used in table lineno mode */
|
||||||
div.highlight > div td > pre {
|
div.highlight > div td > pre {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
@ -1077,6 +1085,7 @@ html[dir="rtl"] #body #breadcrumbs {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: .934375rem;
|
font-size: .934375rem;
|
||||||
|
line-height: 1.15;
|
||||||
}
|
}
|
||||||
|
|
||||||
span > .copy-to-clipboard-button {
|
span > .copy-to-clipboard-button {
|
||||||
|
@ -1091,11 +1100,13 @@ span > .copy-to-clipboard-button {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button > i,
|
||||||
.copy-to-clipboard-code + .copy-to-clipboard-button > i {
|
.copy-to-clipboard-code + .copy-to-clipboard-button > i {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button,
|
||||||
pre > .copy-to-clipboard-button {
|
pre > .copy-to-clipboard-button {
|
||||||
background-color: rgba( 160, 160, 160, .2 );
|
background-color: rgba( 160, 160, 160, .2 );
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
|
@ -272,11 +272,13 @@ table {
|
||||||
color: var(--INTERNAL-CODE-INLINE-BG-color);
|
color: var(--INTERNAL-CODE-INLINE-BG-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button,
|
||||||
pre .copy-to-clipboard-button {
|
pre .copy-to-clipboard-button {
|
||||||
border-color: var(--INTERNAL-CODE-BLOCK-BORDER-color);
|
border-color: var(--INTERNAL-CODE-BLOCK-BORDER-color);
|
||||||
color: var(--INTERNAL-MAIN-LINK-color);
|
color: var(--INTERNAL-MAIN-LINK-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.highlight > div table + .copy-to-clipboard-button:hover,
|
||||||
pre .copy-to-clipboard-button:hover {
|
pre .copy-to-clipboard-button:hover {
|
||||||
background-color: var(--INTERNAL-MAIN-LINK-color);
|
background-color: var(--INTERNAL-MAIN-LINK-color);
|
||||||
border-color: var(--INTERNAL-MAIN-LINK-color);
|
border-color: var(--INTERNAL-MAIN-LINK-color);
|
||||||
|
|
|
@ -484,13 +484,16 @@ function initAnchorClipboard(){
|
||||||
|
|
||||||
function initCodeClipboard(){
|
function initCodeClipboard(){
|
||||||
function getCodeText( node ){
|
function getCodeText( node ){
|
||||||
var text = node.textContent;
|
// if highlight shortcode is used in inline lineno mode, remove lineno nodes before generating text, otherwise it doesn't hurt
|
||||||
|
var code = node.cloneNode( true );
|
||||||
|
Array.from( code.querySelectorAll( '*:scope > span > span:first-child:not(:last-child)' ) ).forEach( function( lineno ){
|
||||||
|
lineno.remove();
|
||||||
|
});
|
||||||
|
var text = code.textContent;
|
||||||
// remove a trailing line break, this may most likely
|
// remove a trailing line break, this may most likely
|
||||||
// come from the browser / Hugo transformation
|
// come from the browser / Hugo transformation
|
||||||
text = text.replace( /\n$/, '' );
|
text = text.replace( /\n$/, '' );
|
||||||
// removes leading $ signs from text in an assumption
|
return text;
|
||||||
// that this has to be the unix prompt marker - weird
|
|
||||||
return text.replace( /^\$\s/gm, '' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fallbackMessage( action ){
|
function fallbackMessage( action ){
|
||||||
|
@ -508,114 +511,41 @@ function initCodeClipboard(){
|
||||||
return actionMsg;
|
return actionMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !window.disableHighlightWrapFix ){
|
var codeElements = document.querySelectorAll( 'code' );
|
||||||
// if the highlight shortcode was used with table lineno mode, the generated DOM
|
|
||||||
// is a table, containg exactly one row with two cells, the first cell for all linenos
|
|
||||||
// the second with the code;
|
|
||||||
// this does not look nice if the code gets wrapped around, so we reformat the table
|
|
||||||
// by creating a row for each line, containing the two cells but with only the content of
|
|
||||||
// one line
|
|
||||||
var codeTables = Array.from( document.querySelectorAll( 'code' ) ).reduce( function(a, code){
|
|
||||||
// collect all tbody's without duplicates that need our treatment
|
|
||||||
if( code.parentNode.tagName.toLowerCase() == 'pre' &&
|
|
||||||
code.parentNode.parentNode.tagName.toLowerCase() == 'td' &&
|
|
||||||
code.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'tr' &&
|
|
||||||
code.parentNode.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'tbody' &&
|
|
||||||
code.parentNode.parentNode.parentNode.querySelector( 'td:first-child > pre > code' ) == code &&
|
|
||||||
( !a.length || a[a.length-1] != code.parentNode.parentNode.parentNode.parentNode ) ){
|
|
||||||
var table = code.parentNode.parentNode.parentNode.parentNode;
|
|
||||||
a.push( table );
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}, [] );
|
|
||||||
for( var i = 0; i < codeTables.length; i++ ){
|
|
||||||
// now treat the table (tbody);
|
|
||||||
// first we collect some data, setting up our row template and collect the text
|
|
||||||
// representation of the code for later usage with copy-to-clipboard
|
|
||||||
var table = codeTables[i];
|
|
||||||
var text = getCodeText( table.querySelector( 'td:last-child code' ) );
|
|
||||||
var tr = table.querySelector( 'tr' ).cloneNode();
|
|
||||||
tr.appendChild( table.querySelector( 'td:first-child' ).cloneNode() )
|
|
||||||
.appendChild( table.querySelector( 'td:first-child pre' ).cloneNode() )
|
|
||||||
.appendChild( table.querySelector( 'td:first-child code' ).cloneNode() )
|
|
||||||
.classList.add( 'nocode' );
|
|
||||||
tr.appendChild( table.querySelector( 'td:last-child' ).cloneNode() )
|
|
||||||
.appendChild( table.querySelector( 'td:last-child pre' ).cloneNode() )
|
|
||||||
.appendChild( table.querySelector( 'td:last-child code' ).cloneNode() )
|
|
||||||
.classList.add( 'nocode' );
|
|
||||||
|
|
||||||
// select lineno and code cell of first line that contains all the content
|
|
||||||
var linenums = table.querySelectorAll( 'td:first-child code > span' );
|
|
||||||
var codes = table.querySelectorAll( 'td:last-child code > span' );
|
|
||||||
for( var j = 0; j < linenums.length; j++ ){
|
|
||||||
// now create a new table row by cloning our template
|
|
||||||
// and transfering the original content
|
|
||||||
var clonedTr = tr.cloneNode(true);
|
|
||||||
var code1 = clonedTr.querySelector( 'td:first-child code' );
|
|
||||||
var code2 = clonedTr.querySelector( 'td:last-child code' );
|
|
||||||
code1.appendChild( linenums[j] );
|
|
||||||
code2.appendChild( codes[j] );
|
|
||||||
table.appendChild( clonedTr );
|
|
||||||
}
|
|
||||||
// in the end we have an empty first row, that needs to be deleted
|
|
||||||
table.querySelector( 'tr:first-child' ).remove();
|
|
||||||
// we delete the reformat marker of the first code cell to allow the
|
|
||||||
// copy-to-clipboard functionality
|
|
||||||
table.querySelector( 'tr:first-child td:last-child code' ).classList.remove( 'nocode' );
|
|
||||||
// put the text representation into a data attribute
|
|
||||||
table.querySelector( 'tr:first-child td:last-child code' ).dataset[ 'code' ] = text;
|
|
||||||
// finally mark our tbody to apply special CSS styling
|
|
||||||
table.parentNode.parentNode.parentNode.classList.add( 'wrapfix' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var codeElements = document.querySelectorAll( 'code:not(.nocode)' );
|
|
||||||
for( var i = 0; i < codeElements.length; i++ ){
|
for( var i = 0; i < codeElements.length; i++ ){
|
||||||
var code = codeElements[i];
|
var code = codeElements[i];
|
||||||
var text = code.textContent;
|
var text = getCodeText( code );
|
||||||
var inPre = code.parentNode.tagName.toLowerCase() == 'pre';
|
var inPre = code.parentNode.tagName.toLowerCase() == 'pre';
|
||||||
|
var inTable = inPre &&
|
||||||
|
code.parentNode.parentNode.tagName.toLowerCase() == 'td';
|
||||||
// avoid copy-to-clipboard for highlight shortcode in table lineno mode
|
// avoid copy-to-clipboard for highlight shortcode in table lineno mode
|
||||||
var isFirstLineCell = inPre &&
|
var isFirstLineCell = inTable &&
|
||||||
code.parentNode.parentNode.tagName.toLowerCase() == 'td' &&
|
|
||||||
code.parentNode.parentNode.parentNode.querySelector( 'td:first-child > pre > code' ) == code;
|
code.parentNode.parentNode.parentNode.querySelector( 'td:first-child > pre > code' ) == code;
|
||||||
|
|
||||||
if( !isFirstLineCell && ( inPre || text.length > 5 ) ){
|
if( !isFirstLineCell && ( inPre || text.length > 5 ) ){
|
||||||
var clip = new ClipboardJS( '.copy-to-clipboard-button', {
|
var clip = new ClipboardJS( '.copy-to-clipboard-button', {
|
||||||
text: function( trigger ){
|
text: function( trigger ){
|
||||||
if( !( trigger.previousElementSibling && trigger.previousElementSibling.matches( 'code' ) ) ){
|
if( !trigger.previousElementSibling ){
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
// if we already have a text representation, return it
|
return trigger.previousElementSibling.dataset.code || '';
|
||||||
var code = trigger.previousElementSibling;
|
|
||||||
if( code.dataset.code ){
|
|
||||||
return code.dataset.code;
|
|
||||||
}
|
|
||||||
// if highlight shortcode used in inline lineno mode, remove lineno nodes before generating text
|
|
||||||
code = code.cloneNode( true );
|
|
||||||
Array.from( code.querySelectorAll( '*:scope > span > span:first-child:not(:last-child)' ) ).forEach( function( lineno ){
|
|
||||||
lineno.remove();
|
|
||||||
});
|
|
||||||
// generate and save generated text for repeated usage
|
|
||||||
var text = getCodeText( code );
|
|
||||||
trigger.previousElementSibling.dataset[ 'code' ] = text;
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
clip.on( 'success', function( e ){
|
clip.on( 'success', function( e ){
|
||||||
e.clearSelection();
|
e.clearSelection();
|
||||||
var inPre = e.trigger.parentNode.tagName.toLowerCase() == 'pre';
|
var doBeside = e.trigger.parentNode.tagName.toLowerCase() == 'pre' || (e.trigger.previousElementSibling && e.trigger.previousElementSibling.tagName.toLowerCase() == 'table' );
|
||||||
e.trigger.setAttribute( 'aria-label', window.T_Copied_to_clipboard );
|
e.trigger.setAttribute( 'aria-label', window.T_Copied_to_clipboard );
|
||||||
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (inPre ? 'w' : 's'+(isRtl?'e':'w')) );
|
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (doBeside ? 'w' : 's'+(isRtl?'e':'w')) );
|
||||||
});
|
});
|
||||||
|
|
||||||
clip.on( 'error', function( e ){
|
clip.on( 'error', function( e ){
|
||||||
var inPre = e.trigger.parentNode.tagName.toLowerCase() == 'pre';
|
var doBeside = e.trigger.parentNode.tagName.toLowerCase() == 'pre' || (e.trigger.previousElementSibling && e.trigger.previousElementSibling.tagName.toLowerCase() == 'table' );
|
||||||
e.trigger.setAttribute( 'aria-label', fallbackMessage(e.action) );
|
e.trigger.setAttribute( 'aria-label', fallbackMessage(e.action) );
|
||||||
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (inPre ? 'w' : 's'+(isRtl?'e':'w')) );
|
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (doBeside ? 'w' : 's'+(isRtl?'e':'w')) );
|
||||||
var f = function(){
|
var f = function(){
|
||||||
e.trigger.setAttribute( 'aria-label', window.T_Copied_to_clipboard );
|
e.trigger.setAttribute( 'aria-label', window.T_Copied_to_clipboard );
|
||||||
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (inPre ? 'w' : 's'+(isRtl?'e':'w')) );
|
e.trigger.classList.add( 'tooltipped', 'tooltipped-' + (doBeside ? 'w' : 's'+(isRtl?'e':'w')) );
|
||||||
document.removeEventListener( 'copy', f );
|
document.removeEventListener( 'copy', f );
|
||||||
};
|
};
|
||||||
document.addEventListener( 'copy', f );
|
document.addEventListener( 'copy', f );
|
||||||
|
@ -627,12 +557,11 @@ function initCodeClipboard(){
|
||||||
code.parentNode.classList.add( 'pre-code' );
|
code.parentNode.classList.add( 'pre-code' );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
var clone = code.cloneNode( true );
|
var parent = code.parentNode;
|
||||||
var span = document.createElement( 'span' );
|
var span = document.createElement( 'span' );
|
||||||
span.classList.add( 'copy-to-clipboard' );
|
span.classList.add( 'copy-to-clipboard' );
|
||||||
span.appendChild( clone );
|
span.appendChild( code );
|
||||||
code.parentNode.replaceChild( span, code );
|
parent.appendChild( span );
|
||||||
code = clone;
|
|
||||||
}
|
}
|
||||||
var button = document.createElement( 'span' );
|
var button = document.createElement( 'span' );
|
||||||
button.classList.add( 'copy-to-clipboard-button' );
|
button.classList.add( 'copy-to-clipboard-button' );
|
||||||
|
@ -642,7 +571,15 @@ function initCodeClipboard(){
|
||||||
this.removeAttribute( 'aria-label' );
|
this.removeAttribute( 'aria-label' );
|
||||||
this.classList.remove( 'tooltipped', 'tooltipped-w', 'tooltipped-se', 'tooltipped-sw' );
|
this.classList.remove( 'tooltipped', 'tooltipped-w', 'tooltipped-se', 'tooltipped-sw' );
|
||||||
});
|
});
|
||||||
code.parentNode.insertBefore( button, code.nextSibling );
|
if( inTable ){
|
||||||
|
var table = code.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
|
table.dataset[ 'code' ] = text;
|
||||||
|
table.parentNode.insertBefore( button, table.nextSibling );
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
code.dataset[ 'code' ] = text;
|
||||||
|
code.parentNode.insertBefore( button, code.nextSibling );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue