import React from 'react' import * as hljs from 'highlight.js' import ResizeObserver from 'resize-observer-polyfill' import debounce from 'lodash.debounce' import ms from 'ms' import { Controlled as CodeMirror } from 'react-codemirror2' import WindowControls from '../components/WindowControls' import Watermark from '../components/svg/Watermark' import { COLORS, LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, THEMES_HASH, DEFAULT_SETTINGS } from '../lib/constants' class Carbon extends React.PureComponent { static defaultProps = { onAspectRatioChange: () => {}, updateCode: () => {}, innerRef: () => {} } componentDidMount() { const ro = new ResizeObserver(entries => { const cr = entries[0].contentRect this.props.onAspectRatioChange(cr.width / cr.height) }) ro.observe(this.exportContainerNode) } handleLanguageChange = debounce( (newCode, language) => { if (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) { return languageMode.mime || languageMode.mode } } return language }, ms('300ms'), { leading: true, trailing: true } ) onBeforeChange = (editor, meta, code) => { if (!this.props.readOnly) { this.props.updateCode(code) } } getRef = ele => { this.exportContainerNode = ele this.props.innerRef(ele) } render() { const config = { ...DEFAULT_SETTINGS, ...this.props.config } const languageMode = this.handleLanguageChange(this.props.children, config.language) const options = { lineNumbers: config.lineNumbers, mode: languageMode || 'plaintext', theme: config.theme, scrollBarStyle: null, viewportMargin: Infinity, lineWrapping: true, extraKeys: { 'Shift-Tab': 'indentLess' }, // negative values removes the cursor, undefined means default (530) cursorBlinkRate: this.props.readOnly ? -1 : undefined, // needs to be able to refresh every 16ms to hit 60 frames / second pollInterval: 16 } const backgroundImage = (this.props.config.backgroundImage && this.props.config.backgroundImageSelection) || this.props.config.backgroundImage const content = (