diff --git a/action/action.php b/action/action.php index 39e808c..5e91d54 100644 --- a/action/action.php +++ b/action/action.php @@ -40,6 +40,7 @@ public function addJsinfo(Doku_Event $event) $JSINFO['sectok'] = getSecurityToken(); $JSINFO['plugins']['diagrams'] = [ 'service_url' => $this->getConf('service_url'), + 'theme' => $this->getConf('theme'), 'mode' => $this->getConf('mode'), ]; } diff --git a/action/embed.php b/action/embed.php index 2c05c56..a3b13a0 100644 --- a/action/embed.php +++ b/action/embed.php @@ -118,6 +118,5 @@ public function handleSave(Doku_Event $event) unlock($id); echo 'OK'; } - } diff --git a/conf/default.php b/conf/default.php index 3f88c01..f548dc0 100644 --- a/conf/default.php +++ b/conf/default.php @@ -3,5 +3,6 @@ * Diagrams plugin, default configuration settings */ $conf['service_url'] = 'https://embed.diagrams.net/?embed=1&proto=json&spin=1&svg-warning=0'; +$conf['theme'] = 'light'; $conf['mode'] = 1; $conf['pngcache'] = 0; diff --git a/conf/metadata.php b/conf/metadata.php index 997c5f2..b1c2494 100644 --- a/conf/metadata.php +++ b/conf/metadata.php @@ -3,5 +3,6 @@ * Diagrams plugin, configuration metadata */ $meta['service_url'] = array('string'); +$meta['theme'] = array('multichoice', '_choices' => array('light', 'dark')); $meta['mode'] = array('multichoice', '_choices' => array(1, 2, 3)); $meta['pngcache'] = array('onoff'); diff --git a/lang/en/settings.php b/lang/en/settings.php index 3884723..092a82d 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -6,9 +6,13 @@ */ $lang['service_url'] = 'Defines which diagrams.net editor url is used.'; +$lang['theme'] = 'Which theme should diagrams use?'; $lang['mode'] = 'How should diagrams be stored?'; $lang['pngcache'] = 'Should diagrams also be cached as PNG? (recommended when using the dw2pdf plugin)'; +$lang['theme_o_light'] = 'Light'; +$lang['theme_o_dark'] = 'Dark'; + $lang['mode_o_1'] = 'Media Files'; $lang['mode_o_2'] = 'Embedded in the page'; $lang['mode_o_3'] = 'Allow both'; diff --git a/script/DiagramsEditor.js b/script/DiagramsEditor.js index 8f44776..e6f9767 100644 --- a/script/DiagramsEditor.js +++ b/script/DiagramsEditor.js @@ -126,7 +126,7 @@ class DiagramsEditor { const response = await fetch(uploadUrl, { method: 'POST', cache: 'no-cache', - body: svg, + body: DiagramsEditor.svgThemeProcessing(svg), }); return response.ok; @@ -151,7 +151,7 @@ class DiagramsEditor { '§ok=' + JSINFO['sectok']; const body = new FormData(); - body.set('svg', svg); + body.set('svg', DiagramsEditor.svgThemeProcessing(svg)); const response = await fetch(uploadUrl, { method: 'POST', @@ -174,7 +174,7 @@ class DiagramsEditor { '§ok=' + JSINFO['sectok']; const body = new FormData(); - body.set('svg', svg); + body.set('svg', DiagramsEditor.svgThemeProcessing(svg)); body.set('png', png); const response = await fetch(uploadUrl, { @@ -192,7 +192,7 @@ class DiagramsEditor { #createEditor() { this.#diagramsEditor = document.createElement('iframe'); this.#diagramsEditor.id = 'plugin__diagrams-editor'; - this.#diagramsEditor.src = JSINFO['plugins']['diagrams']['service_url']; + this.#diagramsEditor.src = JSINFO['plugins']['diagrams']['service_url'] + '&ui=' + JSINFO['plugins']['diagrams']['theme']; document.body.appendChild(this.#diagramsEditor); this.#listener = this.#handleMessage.bind(this); @@ -227,6 +227,31 @@ class DiagramsEditor { ); } + /** + * Add additional theme properties to svg data + * + * @param {string} svg The raw SVG data + * @return {string} + */ + static svgThemeProcessing(svg) + { + if (JSINFO['plugins']['diagrams']['theme'] !== 'dark') return svg; + + const parser = new DOMParser(); + const xml = parser.parseFromString(svg, "image/svg+xml"); + + xml.documentElement.setAttribute('class', 'ge-export-svg-dark'); + + const darkStyle = xml.createElementNS(xml.documentElement.namespaceURI, 'style'); + darkStyle.setAttribute('type', 'text/css'); + darkStyle.textContent = 'svg.ge-export-svg-dark { filter: invert(100%) hue-rotate(180deg); } svg.ge-export-svg-dark foreignObject img, svg.ge-export-svg-dark image:not(svg.ge-export-svg-dark switch image), svg.ge-export-svg-dark svg { filter: invert(100%) hue-rotate(180deg) }'; + + const defs = xml.getElementsByTagName('defs')[0]; + defs.replaceChildren(darkStyle); + + return new XMLSerializer().serializeToString(xml); + } + /** * Handle messages from diagramming service * @@ -256,6 +281,7 @@ class DiagramsEditor { case 'export': if (msg.format === 'svg') { this.#svg = this.#decodeDataUri(msg.data); + this.#svg = DiagramsEditor.svgThemeProcessing(this.#svg); // export again as PNG this.#diagramsEditor.contentWindow.postMessage( diff --git a/script/embed-editbutton.js b/script/embed-editbutton.js index 9e61443..019fc9c 100644 --- a/script/embed-editbutton.js +++ b/script/embed-editbutton.js @@ -18,7 +18,8 @@ document.addEventListener('DOMContentLoaded', () => { event.preventDefault(); const diagramsEditor = new DiagramsEditor(() => { // replace instead of reload to avoid accidentally re-submitting forms - window.location.replace(window.location.href); + // hash breaks replace, must be ignored + window.location.replace(window.location.pathname + window.location.search); }); diagramsEditor.editEmbed( JSINFO.id, diff --git a/script/embed-toolbar.js b/script/embed-toolbar.js index 8e62965..5443106 100644 --- a/script/embed-toolbar.js +++ b/script/embed-toolbar.js @@ -52,6 +52,8 @@ if (typeof window.toolbar !== 'undefined') { const origSvg = area.value.substring(selection.start, selection.end); diagramsEditor.editMemory(origSvg, svg => { + svg = DiagramsEditor.svgThemeProcessing(svg); + if (!origSvg) { // if this is a new diagram, wrap it in a tag svg = '' + svg + ''; diff --git a/syntax/mediafile.php b/syntax/mediafile.php index 474ea5e..a836b49 100644 --- a/syntax/mediafile.php +++ b/syntax/mediafile.php @@ -125,7 +125,7 @@ public function render($format, Doku_Renderer $renderer, $data) $wrapperAttributes['class'] = 'media diagrams-svg-wrapper media' . $data['align']; $imageAttributes = []; - $imageAttributes['class'] = 'diagrams-svg'; + $imageAttributes['class'] = "diagrams-svg"; $imageAttributes['data'] = $data['url']; $imageAttributes['data-id'] = cleanID($data['src'] ?? ''); $imageAttributes['type'] = 'image/svg+xml';