1 | import React, {PureComponent} from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import classNames from 'classnames';
|
4 |
|
5 | import normalizeIndent from '../global/normalize-indent';
|
6 | import trivialTemplateTag from '../global/trivial-template-tag';
|
7 |
|
8 | import highlight from './highlight';
|
9 | import styles from './code.css';
|
10 |
|
11 | function noop() {}
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | export default class Code extends PureComponent {
|
18 | static propTypes = {
|
19 | className: PropTypes.string,
|
20 | code: PropTypes.string.isRequired,
|
21 | inline: PropTypes.bool,
|
22 | softWrap: PropTypes.bool,
|
23 | language: PropTypes.string,
|
24 | replacer: PropTypes.func,
|
25 | codeRef: PropTypes.oneOfType([
|
26 | PropTypes.shape({current: PropTypes.instanceOf(Element)}),
|
27 | PropTypes.func
|
28 | ])
|
29 | };
|
30 |
|
31 | static defaultProps = {
|
32 | inline: false,
|
33 | softWrap: false,
|
34 | replacer: noop
|
35 | };
|
36 |
|
37 | componentDidMount() {
|
38 | this.highlight();
|
39 | }
|
40 |
|
41 | componentDidUpdate() {
|
42 | this.highlight();
|
43 | }
|
44 |
|
45 | highlight() {
|
46 | if (!this.props.inline) {
|
47 | highlight.highlightBlock(this.codeRef);
|
48 | }
|
49 | this.props.replacer(this.codeRef);
|
50 | }
|
51 |
|
52 | get codeRef() {
|
53 | const {codeRef} = this.props;
|
54 | return !codeRef || this.isFunctionCodeRef ? this.code : codeRef.current;
|
55 | }
|
56 |
|
57 | get isFunctionCodeRef() {
|
58 | return typeof (this.props.codeRef) === 'function';
|
59 | }
|
60 |
|
61 | get initCodeRef() {
|
62 | const {codeRef} = this.props;
|
63 | if (codeRef && !this.isFunctionCodeRef) {
|
64 | return codeRef;
|
65 | }
|
66 | return ref => {
|
67 | this.code = ref;
|
68 | if (this.isFunctionCodeRef) {
|
69 | codeRef(this.code);
|
70 | }
|
71 | };
|
72 | }
|
73 |
|
74 | render() {
|
75 | const {code, className, inline, softWrap, language} = this.props;
|
76 |
|
77 | const Tag = inline ? 'span' : 'pre';
|
78 | const classes = classNames(styles.code, className, language, {
|
79 | [styles.inline]: inline,
|
80 | [styles.softWrap]: softWrap
|
81 | });
|
82 |
|
83 | return (
|
84 | <Tag className={classes}>
|
85 | <code ref={this.initCodeRef}>{normalizeIndent(code)}</code>
|
86 | </Tag>
|
87 | );
|
88 | }
|
89 | }
|
90 |
|
91 | const code = trivialTemplateTag(source => <Code code={source}/>);
|
92 |
|
93 | export {code, highlight};
|
94 |
|
\ | No newline at end of file |