@nteract/outputs
Version:
components for rendering outputs
70 lines (69 loc) • 2.6 kB
JavaScript
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const React = __importStar(require("react"));
const styled_components_1 = __importDefault(require("styled-components"));
const outputStyle_1 = __importDefault(require("../outputStyle"));
// Note: createRange and Range must be polyfilled on older browsers with
// https://github.com/timdown/rangy
function createFragment(html) {
/**
* createFragment takes in an HTML string and outputs a DOM element that is
* treated as if it originated on the page "like normal".
* @type {Node} - https://developer.mozilla.org/en-US/docs/Web/API/Node
*/
// Create a range to ensure that scripts are invoked from within the HTML
const range = document.createRange();
const fragment = range.createContextualFragment(html);
return fragment;
}
const StyledDiv = styled_components_1.default.div `
${outputStyle_1.default}
`;
class HTML extends React.PureComponent {
componentDidMount() {
// clear out all DOM element children
// This matters on server side render otherwise we'll get both the `innerHTML`ed
// version + the fragment version right after each other
// In the desktop app (and successive loads with tools like commuter) this
// will be a no-op
if (!this.el) {
return;
}
while (this.el.firstChild) {
this.el.removeChild(this.el.firstChild);
}
// DOM element appended with a real DOM Node fragment
this.el.appendChild(createFragment(this.props.data));
}
componentDidUpdate() {
if (!this.el) {
return;
}
// clear out all DOM element children
while (this.el.firstChild) {
this.el.removeChild(this.el.firstChild);
}
this.el.appendChild(createFragment(this.props.data));
}
render() {
return (React.createElement(StyledDiv, { dangerouslySetInnerHTML: { __html: this.props.data }, ref: el => {
this.el = el;
} }));
}
}
exports.HTML = HTML;
HTML.defaultProps = {
data: "",
mediaType: "text/html"
};
exports.default = HTML;