Path: blob/master/src/packages/jupyter/util/iframe.ts
1447 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6Efficient backend processing of iframe srcdoc and general text/html messages.78MOTIVATION: Sage 3d graphics.9*/1011import { decode } from "he";1213// use iframe for anything at all large (reduce strain on )14const MAX_HTML_SIZE = 10000;1516// We use iframes to render html in a number of cases:17// - if it starts with iframe18// - if it has a whole page doctype19// - if it has a <script> tag anywhere -- since those are ignored by safe HTML20// rendering; using an iframe is the only way. This e.g., makes mpld3 work uses -- <script>! https://github.com/sagemathinc/cocalc/issues/193421// and altair -- https://github.com/sagemathinc/cocalc/issues/4468 -- uses <script type="text/javascript"/>22// - do NOT just render all html in an iframe, e.g., this would break bokeh, since one output creates the target elt,23// and a different output uses javascript to render it, and this doesn't work with an iframe, of course.24export function shouldUseIframe(content: string): boolean {25if (!content) {26return false;27}28content = content.toLowerCase();29if (30content.includes("https://bokeh.org") &&31content.includes("bk-notebook-logo")32) {33// Do NOT use an iframe for bokeh no matter what, since this won't work properly.34// Hopefully the above heuristic is sufficiently robust to detect but not overdetect.35return false;36}37if (content.includes("<!doctype html>") || content.includes("<html>")) {38// plotly wraps its output in <html>, which strongly suggests it wants to39// be in an iframe. It's not valid to put <html> as a child of a div, so really40// the only valid way to render an <html> string is as an iframe.41return true;42}43if (content.length >= MAX_HTML_SIZE) {44// it'll just break anyways if we don't use an iframe -- if we do, there is hope.45return true;46}47return content.startsWith("<iframe");48}4950export function processIframeContent(content: string): string {51const decodedContent = decode(content);52const contentLower = decodedContent.toLowerCase();53const i = contentLower.indexOf("<html>");54const j = contentLower.lastIndexOf("</html>");55// trim content to the part inside the html tags – keep it otherwise56// this is necessary for wrapping inline html code like for57// https://github.com/sagemathinc/cocalc/issues/446858let src = "";59if (i != -1 && j != -1) {60src = decodedContent.slice(i, j + "</html>".length);61} else {62src = `<html>${decodedContent}</html>`;63}64return src;65}666768