import React, { PureComponent } from 'react' import * as hljs from 'highlight.js' import Spinner from 'react-spinner' import ResizeObserver from 'resize-observer-polyfill' import debounce from 'lodash.debounce' import ms from 'ms' import WindowControls from '../components/WindowControls' import Watermark from '../components/svg/Watermark' import CodeMirror from '../lib/react-codemirror' import { COLORS, LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, DEFAULT_SETTINGS } from '../lib/constants' class Carbon extends PureComponent { constructor(props) { super(props) this.state = { loading: true, language: props.config.language } this.handleLanguageChange = this.handleLanguageChange.bind(this) this.handleTitleBarChange = this.handleTitleBarChange.bind(this) this.codeUpdated = this.codeUpdated.bind(this) } componentDidMount() { this.setState({ loading: false }) this.handleLanguageChange(this.props.children) const ro = new ResizeObserver(entries => { const cr = entries[0].contentRect this.props.onAspectRatioChange(cr.width / cr.height) }) ro.observe(this.exportContainerNode) } componentWillReceiveProps(newProps) { this.handleLanguageChange(newProps.children, { customProps: newProps }) } codeUpdated(newCode) { this.handleLanguageChange(newCode) this.props.updateCode(newCode) } handleTitleBarChange(newTitle) { this.props.updateTitleBar(newTitle) } handleLanguageChange = debounce( (newCode, config) => { const props = (config && config.customProps) || this.props if (props.config.language === 'auto') { // try to set the language const detectedLanguage = hljs.highlightAuto(newCode).language const languageMode = LANGUAGE_MODE_HASH[detectedLanguage] || LANGUAGE_NAME_HASH[detectedLanguage] if (languageMode) { this.setState({ language: languageMode.mime || languageMode.mode }) } } else { this.setState({ language: props.config.language }) } }, ms('300ms'), { trailing: true } ) render() { const config = { ...DEFAULT_SETTINGS, ...this.props.config } const options = { lineNumbers: config.lineNumbers, mode: this.state.language || 'plaintext', theme: config.theme, scrollBarStyle: null, viewportMargin: Infinity, lineWrapping: true, extraKeys: { 'Shift-Tab': 'indentLess' } } const backgroundImage = (this.props.config.backgroundImage && this.props.config.backgroundImageSelection) || this.props.config.backgroundImage // set content to spinner if loading, else editor let content = (