From 20547ce5558cf8618e8a047792bee35ca7710ae3 Mon Sep 17 00:00:00 2001 From: "piotr.suwala" Date: Fri, 17 May 2024 22:12:00 +0200 Subject: [PATCH] Added option for embedding plantuml diagram as an object tag --- client/components/editor/markdown/plantuml.js | 35 +++++++++++++------ .../markdown-plantuml/definition.yml | 7 ++++ .../rendering/markdown-plantuml/renderer.js | 35 +++++++++++++------ 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/client/components/editor/markdown/plantuml.js b/client/components/editor/markdown/plantuml.js index 0e89b218..1a111b6c 100644 --- a/client/components/editor/markdown/plantuml.js +++ b/client/components/editor/markdown/plantuml.js @@ -13,6 +13,7 @@ module.exports = { const closeChar = closeMarker.charCodeAt(0) const imageFormat = opts.imageFormat || 'svg' const server = opts.server || 'https://plantuml.requarks.io' + const renderSvgAsObject = opts.renderSvgAsObject || false md.block.ruler.before('fence', 'uml_diagram', (state, startLine, endLine, silent) => { let nextLine @@ -114,16 +115,27 @@ module.exports = { var zippedCode = encode64(pako.deflate('@startuml\n' + contents + '\n@enduml', { to: 'string' })) - token = state.push('uml_diagram', 'img', 0) - // alt is constructed from children. No point in populating it here. - token.attrs = [ [ 'src', `${server}/${imageFormat}/${zippedCode}` ], [ 'alt', '' ], ['class', 'uml-diagram'] ] - token.block = true - token.children = altToken - token.info = params - token.map = [ startLine, nextLine ] - token.markup = markup - - state.line = nextLine + (autoClosed ? 1 : 0) + if (renderSvgAsObject && imageFormat === 'svg') { + token = state.push('uml_diagram', 'object', 0) + // alt is constructed from children. No point in populating it here. + token.attrs = [['data', `${server}/${imageFormat}/${zippedCode}`], ['alt', ''], ['type', 'image/svg+xml'], ['class', 'uml-diagram']] + token.block = true + token.children = [] + token.info = params + token.map = [startLine, nextLine] + token.markup = markup + state.line = nextLine + (autoClosed ? 1 : 0) + } else { + token = state.push('uml_diagram', 'img', 0) + // alt is constructed from children. No point in populating it here. + token.attrs = [['src', `${server}/${imageFormat}/${zippedCode}`], ['alt', ''], ['class', 'uml-diagram']] + token.block = true + token.children = altToken + token.info = params + token.map = [startLine, nextLine] + token.markup = markup + state.line = nextLine + (autoClosed ? 1 : 0) + } return true }, { @@ -134,7 +146,8 @@ module.exports = { openMarker: conf.openMarker, closeMarker: conf.closeMarker, imageFormat: conf.imageFormat, - server: conf.server + server: conf.server, + renderSvgAsObject: conf.renderSvgAsObject }) } } diff --git a/server/modules/rendering/markdown-plantuml/definition.yml b/server/modules/rendering/markdown-plantuml/definition.yml index e8b156fc..97bf3718 100644 --- a/server/modules/rendering/markdown-plantuml/definition.yml +++ b/server/modules/rendering/markdown-plantuml/definition.yml @@ -39,3 +39,10 @@ props: - ascii order: 4 public: true + renderSvgAsObject: + type: Boolean + default: false + title: Render svg as object tag instead of img tag + hint: Allows for interactive content like links in plantuml graphs - it may have security implications + order: 5 + public: true diff --git a/server/modules/rendering/markdown-plantuml/renderer.js b/server/modules/rendering/markdown-plantuml/renderer.js index 40eedc04..9526c503 100644 --- a/server/modules/rendering/markdown-plantuml/renderer.js +++ b/server/modules/rendering/markdown-plantuml/renderer.js @@ -13,6 +13,7 @@ module.exports = { const closeChar = closeMarker.charCodeAt(0) const imageFormat = opts.imageFormat || 'svg' const server = opts.server || 'https://plantuml.requarks.io' + const renderSvgAsObject = opts.renderSvgAsObject || false md.block.ruler.before('fence', 'uml_diagram', (state, startLine, endLine, silent) => { let nextLine @@ -114,16 +115,27 @@ module.exports = { const zippedCode = encode64(zlib.deflateRawSync('@startuml\n' + contents + '\n@enduml').toString('binary')) - token = state.push('uml_diagram', 'img', 0) - // alt is constructed from children. No point in populating it here. - token.attrs = [ [ 'src', `${server}/${imageFormat}/${zippedCode}` ], [ 'alt', '' ], ['class', 'uml-diagram prefetch-candidate'] ] - token.block = true - token.children = altToken - token.info = params - token.map = [ startLine, nextLine ] - token.markup = markup - - state.line = nextLine + (autoClosed ? 1 : 0) + if (renderSvgAsObject && imageFormat === 'svg') { + token = state.push('uml_diagram', 'object', 0) + // alt is constructed from children. No point in populating it here. + token.attrs = [['data', `${server}/${imageFormat}/${zippedCode}`], ['alt', ''], ['type', 'image/svg+xml'], ['class', 'uml-diagram prefetch-candidate']] + token.block = true + token.children = [] + token.info = params + token.map = [startLine, nextLine] + token.markup = markup + state.line = nextLine + (autoClosed ? 1 : 0) + } else { + token = state.push('uml_diagram', 'img', 0) + // alt is constructed from children. No point in populating it here. + token.attrs = [['src', `${server}/${imageFormat}/${zippedCode}`], ['alt', ''], ['class', 'uml-diagram prefetch-candidate']] + token.block = true + token.children = altToken + token.info = params + token.map = [startLine, nextLine] + token.markup = markup + state.line = nextLine + (autoClosed ? 1 : 0) + } return true }, { @@ -134,7 +146,8 @@ module.exports = { openMarker: conf.openMarker, closeMarker: conf.closeMarker, imageFormat: conf.imageFormat, - server: conf.server + server: conf.server, + renderSvgAsObject: conf.renderSvgAsObject }) } }