I am trying to configure highlightjs in a reactjs application to detect and highlight json. But it doesn't work, any workaround ? I need it on the browser side btw.
To suggest any "workaround" we need to know what was the problem :-) Can you provide any example that does not work?
@Sannis thanks for the quick response, my bad.
In my index.html
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
In my react component
var Pretty = React.createClass({
render: function() {
return <pre className="custom-json-body"><code className="json">{JSON.stringify(this.props.json, null, 2)}</code></pre>;
}
});
But it isn't highlighting.
I tried with class and className as well. No luck.
hljs.initHighlightingOnLoad(); higlights code on page once after page is loaded.
If you need highlight dinamically loaded content - this is your responsability. We provide hljs.highlight() method for that, so you can include it to React.js render callback. I also think that React.js should provide some post-render events that you can listen and highlight rendered block there.
hljs.initHighlightingOnLoad(); higlights code on page once after page is loaded.
@Sannis thanks a lot. Its solved now. In fact I called hljs.initHighlightingOnLoad(); when the page has been loaded but I did not wait for that particular component to load.
I also think that React.js should provide some post-render events that you can listen and highlight rendered block there.
React provides this, just for future reference
var Pretty = React.createClass({
componentDidMount: function(){
hljs.initHighlightingOnLoad();
var current = React.findDOMNode(this);
hljs.highlightBlock(current);
},
render: function() {
return <pre className="custom-json-body"><code className="json">{JSON.stringify(this.props.json, null, 2)}</code></pre>;
}
});
Let me know if there is a better way to do this. Thanks a lot.
Great! Unfortunately, I'm not familiar with react to suggest something better. But it looks like you do double work in componentDidMount.
Ohh okay I just realised that for some reason hljs.initHighlightingOnLoad(); doesn't do anything at all. So finally its
componentDidMount: function(){
var current = React.findDOMNode(this);
hljs.highlightBlock(current);
}
Ohh okay I just realised that for some reason hljs.initHighlightingOnLoad(); doesn't do anything at all.
What it does is binds itself to the onload event of the browser which by that moment has probably already been fired. highlightBlock() is the main method anyway.
For anyone (like me) who finds this issue: https://github.com/akiran/react-highlight
:-)
import React from 'react'
import hljs from 'highlight.js'
import javascript from 'highlight.js/lib/languages/javascript'
import '../../node_modules/highlight.js/styles/darcula.css'
hljs.registerLanguage('javascript', javascript)
export class Highlighter extends React.PureComponent {
componentDidMount(){
hljs.highlightBlock(this.node)
}
render() {
let { children } = this.props
return (
<pre
ref={(node) => this.node = node}
>
<code className="javascript">
{children}
</code>
</pre>
)
}
}
export default Highlighter
<Highlighter>
{'function(){let test = [\'test\', \'test 2\']}'}
</Highlighter>
You can customize this component with various props like language
For anyone (like me) who finds this issue: https://github.com/akiran/react-highlight
:-)
this library has a lot of side effects.
For anyone (like me) who finds this issue: https://github.com/akiran/react-highlight
:-)this library has a lot of side effects.
@Farhad33 Like what? I'm very interested to know, being that I just incorporated this package into my project.
For anyone (like me) who finds this issue: https://github.com/akiran/react-highlight
:-)this library has a lot of side effects.
@Farhad33 Like what? I'm very interested to know, being that I just incorporated this package into my project.
I have already experienced unstable DOMExceptions with this library and seen these errors posted as issues but unanswered...
For everyone who didn't find any working answer above and have no success with initHighlightingOnLoad and others builtin functions.
React: 16.8.2 working example:
import hljs from "highlight.js";
import "./dracula.css";
class Preview extends Component {
componentDidMount() {
this.updateCodeSyntaxHighlighting();
}
componentDidUpdate() {
this.updateCodeSyntaxHighlighting();
}
updateCodeSyntaxHighlighting = () => {
document.querySelectorAll("pre code").forEach(block => {
hljs.highlightBlock(block);
});
};
render() {
return (
<div
className="content"
dangerouslySetInnerHTML={{ __html: this.props.parsedText }}
/>
);
}
}
Note that updateCodeSyntaxHighlighting should be in componentDidMount and componentDidUpdate methods in every component which use <pre><code>... tags.
I have a slightly different solution that registers only the language you actually need by importing them once.
React 16.8.2:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import hljs from 'highlight.js/lib/highlight'; // import hljs library
import 'highlight.js/styles/hopscotch.css'; // import your preferred style
const registeredLanguages = {}; // keep a record of registered languages
export class CodeHighlight extends Component {
constructor(props) {
super(props);
// do not show anything until language is loaded
this.state = { loaded: false };
// create a ref to highlight only the rendered node and not fetch all the DOM
this.codeNode = React.createRef();
}
componentDidMount() {
const { language } = this.props;
if (language && !registeredLanguages[language]) {
try {
const newLanguage = require(`highlight.js/lib/languages/${language}`);
hljs.registerLanguage(language, newLanguage);
registeredLanguages[language] = true;
this.setState(
() => { return { loaded: true }; },
() => { this.highlight(); }
);
} catch (e) {
console.error(e);
throw Error(`Cannot register and higlight language ${language}`);
// We can alternatively set loaded to true and show an error message in the
// code block instead of children, or just show the children without highlight.
// This would be an improvement or an optional behavior given a special prop.
}
} else {
this.setState({ loaded: true });
}
}
componentDidUpdate() {
this.highlight();
}
highlight = () => {
this.codeNode && this.codeNode.current && hljs.highlightBlock(this.codeNode.current);
}
render() {
const { language, children } = this.props;
const { loaded } = this.state;
if (!loaded) return ''; // or show a loader
return <pre>
<code ref={this.codeNode} className={language}>{children}</code>
</pre>;
}
}
CodeHighlight.propTypes = {
children: PropTypes.node.isRequired,
language: PropTypes.string,
};
// optionally set the language you think will use most as a default value
// if you don't set this, I would encourage to make language prop required,
// or at least improve the "else" statement in "componentDidMount"
CodeHighlight.defaultProps = {
language: 'javascript',
};
Usage:
// Use the default language, if set
<CodeHighlight>
{JSON.stringify(myObject, null, 4)}
</CodeHighlight>
// Specify a language
<CodeHighlight language="python">
{JSON.stringify(myObject, null, 4)}
</CodeHighlight>
Witaj @twistezo and ciao @vittoriozamboni
Do your codes support third-party languages like https://github.com/highlightjs/highlightjs-cypher?
Sure. Just import and register the 3rd party grammar after you import the main library.
WItaj @twistezo, ciao @vittoriozamboni and hello @yyyc514 !
Thank you, I have just updated the repo's README, adding React instruction.
Most helpful comment
For everyone who didn't find any working answer above and have no success with
initHighlightingOnLoadand others builtin functions.React: 16.8.2 working example:
Note that
updateCodeSyntaxHighlightingshould be incomponentDidMountandcomponentDidUpdatemethods in every component which use<pre><code>...tags.