Reputation: 840
My website is generating some content dynamically, so I have to somehow launch the highlight.js plugin again after loading it.
This code is used to launch the highlighter:
hljs.initHighlightingOnLoad();
I tried to do something like hljs.initHighlighting();
to do this again but it does not work.
Upvotes: 23
Views: 12499
Reputation: 409
My code editor uses highlight.js but should be editable so after each editing it calls hljs.highlightElement(this);
Here`s the code:
<html><head>
<title>Python Editor</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" type="text/javascript"></script>
<script type="text/javascript">hljs.highlightAll();
function replaceTagMarks(str){
//to ensure code is not interpreted as HTML
return str.replaceAll('<', '<').replaceAll('>', '>');
}
function removeHighLight(el){
//innerText contains the plain text without the surounding html made by hljs
el.innerHTML = replaceTagMarks(el.innerText);
//to inform hljs that the element is no longer highlighted
delete el.dataset.highlighted;
}
</script>
</head>
<body>
<pre><code contenteditable = 'true'
class='language-python hljs'
spellcheck = 'false',
onfocusout = 'hljs.highlightElement(this);',
onfocusin = 'removeHighLight(this);')>
print('Hello world')
</code></pre>
<body>
</html>
Upvotes: 0
Reputation: 56905
Calling hljs.highlightAll()
or hljs.highlightElement(e)
multiple times on already-highlighted elements results in an annoying warning:
Element previously highlighted. To highlight again, first unset
dataset.highlighted
.
hljs.highlightAll();
setTimeout(() => hljs.highlightAll(), 0);
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs2015.min.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<pre><code>console.log("hello" + 42);</code></pre>
But unsetting dataset.highlighted
doesn't really seem to work, unless I'm missing something, because it doesn't remove the HTML elements hljs added to facilitate its highlighting:
const highlightAll = () => {
document.querySelectorAll("code").forEach((e) => {
delete e.dataset.highlighted;
hljs.highlightElement(e);
});
// fails too when used instead of highlightElement:
// hljs.highlightAll();
};
highlightAll();
setTimeout(highlightAll, 0);
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs2015.min.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<pre><code>console.log("hello" + 42);</code></pre>
An approach that circumvents this is to skip highlighting anything that's already highlighted:
const highlightAll = () => {
document.querySelectorAll("code").forEach((e) => {
if (!e.dataset.highlighted) {
hljs.highlightElement(e);
}
});
};
highlightAll();
setTimeout(highlightAll, 0);
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs2015.min.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<pre><code>console.log("hello" + 42);</code></pre>
As far as I can tell, if you need to re-highlight rather than skip, you'll need to replace all of the HTML with the original text content before calling hljs.highlightElement(element)
.
Upvotes: 1
Reputation: 151
I get the solution by integrate react-highlight.
You can use innerHtml
to true on the property.
import Highlight from "react-highlight"
import "highlight.js/styles/gradient-dark.css"; // import style on the root file
import JSONViewer from "./JSONViewer"
<Highlight innerHTML className="w-full">
<JSONViewer content={yourContentHere} />
</Highlight>
Set innerHTML=true
to highlight multiple code snippets at a time. This is especially usefull if html with multiple code snippets is generated from preprocesser tools like markdown.
Warning: If innerHTML is set to true, make sure the html generated with code snippets is from trusted source.
Using hljs.registerLanguage("json", json);
or hljs.initHighlightingOnLoad();
will getting a problem by rerendering react. It's not recall when using dependency but useEffect
without dependency like this it works.
useEffect(() => {
hljs.initHighlightingOnLoad(); // it works, but bad for performance because will call every single time re-rendering.
})
useEffect(() => {
hljs.initHighlightingOnLoad(); // it doesn't works
}, [])
Upvotes: 0
Reputation: 67
i hope this could solve your problem.. you have to use
hljs.highlightAll()
since, hljs.initHighlightingOnLoad() is deprecated since version 10.6.
if you're using react, you could apply at componentdidMount..
useEffect(() => {
hljs.highlightAll()
}, []);
or, if another framework, please call that function when page loaded. more: https://highlightjs.readthedocs.io/en/latest/api.html
Upvotes: 0
Reputation: 1508
You must set called to false first:
hljs.initHighlighting.called = false;
hljs.initHighlighting();
Upvotes: 47
Reputation: 222
You can reinitialize all of the codeblocks like this.
$(document).ready(function() {
$('pre code').each(function(i, e) {hljs.highlightBlock(e)});
});
or if you have a div with an ID of myBlock, you can do this.
$(document).ready(function() {
$('#myBlock').each(function(i, e) {hljs.highlightBlock(e)});
});
Upvotes: 6