diff options
Diffstat (limited to 'app/assets/javascripts/behaviors')
-rw-r--r-- | app/assets/javascripts/behaviors/components/sandboxed_mermaid.vue | 77 | ||||
-rw-r--r-- | app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js | 7 |
2 files changed, 81 insertions, 3 deletions
diff --git a/app/assets/javascripts/behaviors/components/sandboxed_mermaid.vue b/app/assets/javascripts/behaviors/components/sandboxed_mermaid.vue new file mode 100644 index 00000000000..6b4110cff02 --- /dev/null +++ b/app/assets/javascripts/behaviors/components/sandboxed_mermaid.vue @@ -0,0 +1,77 @@ +<script> +import { + getSandboxFrameSrc, + BUFFER_IFRAME_HEIGHT, + SANDBOX_ATTRIBUTES, +} from '../markdown/render_sandboxed_mermaid'; + +export default { + name: 'SandboxedMermaid', + + props: { + source: { + type: String, + required: true, + }, + }, + + data() { + return { + iframeHeight: BUFFER_IFRAME_HEIGHT, + sandboxFrameSrc: getSandboxFrameSrc(), + }; + }, + + watch: { + source() { + this.updateDiagram(); + }, + }, + + mounted() { + window.addEventListener('message', this.onPostMessage, false); + }, + + destroyed() { + window.removeEventListener('message', this.onPostMessage); + }, + + methods: { + getSandboxFrameSrc, + + onPostMessage(event) { + const container = this.$refs.diagramContainer; + + if (event.source === container?.contentWindow) { + this.iframeHeight = Number(event.data.h) + BUFFER_IFRAME_HEIGHT; + } + }, + + updateDiagram() { + const container = this.$refs.diagramContainer; + + // Potential risk associated with '*' discussed in below thread + // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74414#note_735183398 + container.contentWindow?.postMessage(this.source, '*'); + container.addEventListener('load', () => { + container.contentWindow?.postMessage(this.source, '*'); + }); + }, + }, + + sandboxFrameSrc: getSandboxFrameSrc(), + sandboxAttributes: SANDBOX_ATTRIBUTES, +}; +</script> +<template> + <iframe + ref="diagramContainer" + :src="$options.sandboxFrameSrc" + :sandbox="$options.sandboxAttributes" + frameborder="0" + scrolling="no" + width="100%" + :height="iframeHeight" + > + </iframe> +</template> diff --git a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js index 543e676e85e..077e96b2fee 100644 --- a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js @@ -32,7 +32,8 @@ const MAX_CHAR_LIMIT = 2000; const MAX_MERMAID_BLOCK_LIMIT = 50; // Max # of `&` allowed in Chaining of links syntax const MAX_CHAINING_OF_LINKS_LIMIT = 30; -const BUFFER_IFRAME_HEIGHT = 10; +export const BUFFER_IFRAME_HEIGHT = 10; +export const SANDBOX_ATTRIBUTES = 'allow-scripts allow-popups'; // Keep a map of mermaid blocks we've already rendered. const elsProcessingMap = new WeakMap(); let renderedMermaidBlocks = 0; @@ -56,7 +57,7 @@ function fixElementSource(el) { return { source }; } -function getSandboxFrameSrc() { +export function getSandboxFrameSrc() { const path = joinPaths(gon.relative_url_root || '', SANDBOX_FRAME_PATH); if (!darkModeEnabled()) { return path; @@ -69,7 +70,7 @@ function renderMermaidEl(el, source) { const iframeEl = document.createElement('iframe'); setAttributes(iframeEl, { src: getSandboxFrameSrc(), - sandbox: 'allow-scripts allow-popups', + sandbox: SANDBOX_ATTRIBUTES, frameBorder: 0, scrolling: 'no', width: '100%', |