summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-plugin-highlight/src/CodeBlock.js
blob: 9e3b70d1ed217f915d076f3a8c45f70d1fe7c77b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const hljs = require('highlight.js');
const GitBook = require('gitbook-core');
const { React } = GitBook;

const getLanguage = require('./getLanguage');

/**
 * Get children as text
 * @param {React.Children} children
 * @return {String}
 */
function getChildrenToText(children) {
    return React.Children.map(children, (child) => {
        if (typeof child === 'string') {
            return child;
        } else {
            return child.props.children ?
                getChildrenToText(child.props.children) : '';
        }
    }).join('');
}

/**
 * Code block wrapper to highlight the code inside.
 * @type {ReactClass}
 */
const CodeBlock = React.createClass({
    propTypes: {
        children:  React.PropTypes.node,
        theme:     React.PropTypes.string.isRequired,
        className: React.PropTypes.string
    },

    render() {
        const { children, className, theme } = this.props;
        const content = getChildrenToText(children);
        const lang = getLanguage(className || '');

        const includeCSS = <GitBook.ImportCSS href={`gitbook/highlight/${theme}.css`} />;

        try {
            const html = hljs.highlight(lang, content).value;
            return (
                <code>
                    {includeCSS}
                    <span dangerouslySetInnerHTML={{__html: html}} />
                </code>
            );
        } catch (e) {
            return (
                <code>
                    {includeCSS}
                    {content}
                </code>
            );
        }
    }
});

module.exports = GitBook.connect(CodeBlock, ({ config }) => ({
    theme: config.getForPlugin('highlight').get('theme')
}));