'use strict'; import './public-path'; import React, {Component} from 'react'; import ReactDOM from 'react-dom'; import {I18nextProvider} from 'react-i18next'; import i18n, {withTranslation} from './i18n'; import { parentRPC, UntrustedContentRoot } from './untrusted'; import PropTypes from "prop-types"; import styles from "./sandboxed-codeeditor.scss"; import { getPublicUrl, getSandboxUrl, getTrustedUrl } from "./urls"; import { base, unbase } from "../../../shared/templates"; import ACEEditorRaw from 'react-ace'; import 'brace/theme/github'; import 'brace/ext/searchbox'; import 'brace/mode/html'; import {CodeEditorSourceType} from "./sandboxed-codeeditor-shared"; import mjml2html from "mjml4-in-browser"; import juice from "juice"; const refreshTimeout = 1000; @withTranslation() class CodeEditorSandbox extends Component { constructor(props) { super(props); let defaultSource; if (props.sourceType === CodeEditorSourceType.MJML) { defaultSource = '\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ''; } else if (props.sourceType === CodeEditorSourceType.HTML) { defaultSource = '\n' + '\n' + '\n' + ' \n' + ' Title of the document\n' + '\n' + '\n' + ' Content of the document......\n' + '\n' + ''; } const trustedUrlBase = getTrustedUrl(); const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); const source = this.props.initialSource ? base(this.props.initialSource, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultSource; this.state = { source, preview: props.initialPreview, wrapEnabled: props.initialWrap }; this.state.previewContents = this.getHtml(); this.onCodeChangedHandler = ::this.onCodeChanged; this.refreshHandler = ::this.refresh; this.refreshTimeoutId = null; this.onMessageFromPreviewHandler = ::this.onMessageFromPreview; this.previewScroll = {x: 0, y: 0}; } static propTypes = { entityTypeId: PropTypes.string, entityId: PropTypes.number, initialSource: PropTypes.string, sourceType: PropTypes.string, initialPreview: PropTypes.bool, initialWrap: PropTypes.bool } async exportState(method, params) { const trustedUrlBase = getTrustedUrl(); const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); return { html: unbase(this.getHtml(), trustedUrlBase, sandboxUrlBase, publicUrlBase, true), source: unbase(this.state.source, trustedUrlBase, sandboxUrlBase, publicUrlBase, true) }; } async setPreview(method, preview) { this.setState({ preview }); } async setWrap(method, wrap) { this.setState({ wrapEnabled: wrap }); } componentDidMount() { parentRPC.setMethodHandler('exportState', ::this.exportState); parentRPC.setMethodHandler('setPreview', ::this.setPreview); parentRPC.setMethodHandler('setWrap', ::this.setWrap); window.addEventListener('message', this.onMessageFromPreviewHandler, false); } componentWillUnmount() { clearTimeout(this.refreshTimeoutId); } getHtml() { let previewContents; if (this.props.sourceType === CodeEditorSourceType.MJML) { const res = mjml2html(this.state.source); previewContents = res.html; } else if (this.props.sourceType === CodeEditorSourceType.HTML) { previewContents = juice(this.state.source); } return previewContents; } onCodeChanged(data) { this.setState({ source: data }); if (!this.refreshTimeoutId) { this.refreshTimeoutId = setTimeout(() => this.refresh(), refreshTimeout); } } onMessageFromPreview(evt) { if (evt.data.type === 'scroll') { this.previewScroll = evt.data.data; } } refresh() { this.refreshTimeoutId = null; this.setState({ previewContents: this.getHtml() }); } render() { const previewScript = '(function() {\n' + ' function reportScroll() { window.parent.postMessage({type: \'scroll\', data: {x: window.scrollX, y: window.scrollY}}, \'*\'); }\n' + ' reportScroll();\n' + ' window.addEventListener(\'scroll\', reportScroll);\n' + ' window.addEventListener(\'load\', function(evt) { window.scrollTo(' + this.previewScroll.x + ',' + this.previewScroll.y +'); });\n' + '})();\n'; const previewContents = this.state.previewContents.replace(/<\s*head\s*>/i, ``); return (
{ this.state.preview &&
}
); } } export default function() { parentRPC.init(); ReactDOM.render( } /> , document.getElementById('root') ); };