├── README.md ├── drawio.svg ├── preview1.gif └── trilium-drawio.js /README.md: -------------------------------------------------------------------------------- 1 | # trilium-drawio 2 | ## version: 0.4 for trilium > 0.62.4 3 | ## update 4 | 1. Fixed the bug where large files can only be displayed after refreshing when they are closed 5 | 2. Use light theme by default 6 | ## Draw.io is a JavaScript, client-side editor for general diagramming and whiteboarding. **This widget allows you to use drawio drawing in trilium.** 7 | ## Installation 8 | 1. Create a code note of type JS Frontend with the contents of `trilium-drawio.js` and the label `#widget` 9 | 2. Import `drawio.svg` into Notes and add `#template` tag to it 10 | 3. Reload frontend 11 | ## Tips 12 | 1. The saved format is svg 13 | 2. Click on the svg image to enter the editing state 14 | 3. Will call the drawio website 15 | ## Preview 16 | ![](./preview1.gif) 17 | -------------------------------------------------------------------------------- /drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /preview1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiriusXT/trilium-drawio/43f55ffd24e5f094a480ef7fbc887abbde10b409/preview1.gif -------------------------------------------------------------------------------- /trilium-drawio.js: -------------------------------------------------------------------------------- 1 | /* 2 | trilium-drawio 3 | https://github.com/SiriusXT/trilium-drawio 4 | version:0.4 5 | */ 6 | 7 | var defaultTheme = "0" //0:light;1:dark;,2:Follow software theme styles 8 | 9 | var currentNoteId; 10 | var themeStyle = getComputedStyle(document.documentElement).getPropertyValue('--theme-style'); 11 | var $last_image_wrapper;//Used to detect tab switching 12 | var last_noteId;//For detection and switching of new tab pages 13 | var editor = 'https://embed.diagrams.net/?embed=1&ui=min&spin=1&proto=json&configure=1&libraries=1&noSaveBtn=1&math=1'; 14 | var id_svg_dict = {} 15 | var noteId = '' 16 | 17 | function edit(noteId) { 18 | $('div.component.note-split:not(.hidden-ext) div.component.scrolling-container div.note-detail.component div.note-detail-image-wrapper').off("click"); 19 | 20 | var svg = id_svg_dict[noteId]; 21 | $("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper .note-detail-image-view").css("display", "none"); 22 | var div_iframe = document.createElement('div'); 23 | div_iframe.classList.add("iframe-drawio"); 24 | var iframe = document.createElement('iframe'); 25 | iframe.setAttribute('frameborder', '0'); 26 | iframe.setAttribute('allow', 'clipboard-write'); 27 | if (themeStyle.indexOf('dark') >= 0 && defaultTheme != 0) { div_iframe.classList.add("dark"); } 28 | iframe.setAttribute('src', editor); 29 | document.querySelector('div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper').appendChild(div_iframe); 30 | 31 | div_iframe.appendChild(iframe); 32 | $('div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio').prepend(`
34 |
35 |
36 |
37 |
`); 38 | $('div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio .drawio-switch-theme.bx').click(function (event) {//Drawio Switch Theme 39 | event.stopPropagation(); 40 | var $iframe_tmp = $("div.component.note-split:not(.hidden-ext) div.note-detail-image-wrapper div.iframe-drawio"); 41 | if ($iframe_tmp.length > 0) { 42 | if ($iframe_tmp.hasClass("dark")) { 43 | $iframe_tmp.removeClass("dark"); 44 | } 45 | else { 46 | $iframe_tmp.addClass("dark"); 47 | } 48 | } 49 | else { 50 | const $iframe_tmp = $("body > div.iframe-drawio"); 51 | if ($iframe_tmp.hasClass("dark")) { 52 | $iframe_tmp.removeClass("dark"); 53 | } 54 | else { 55 | $iframe_tmp.addClass("dark"); 56 | } 57 | } 58 | }); 59 | $('div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio .drawio-switch-full-screen.bx').click(function (event) {//Drawio full screen 60 | event.stopPropagation(); 61 | const $iframe_tmp = $("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio"); 62 | if ($iframe_tmp.length > 0) { 63 | $iframe_tmp.appendTo($(parent.document).find("body")); 64 | $iframe_tmp.css("position", "fixed"); 65 | $(".tab-row-filler").css("-webkit-app-region", "none"); 66 | } 67 | else { 68 | const $iframe_tmp = $("body > div.iframe-drawio"); 69 | $iframe_tmp.appendTo($("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper")); 70 | $iframe_tmp.css("position", ""); 71 | $(".tab-row-filler").css("-webkit-app-region", "drag"); 72 | } 73 | 74 | }); 75 | //Close and exit button 76 | $('div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio .drawio-save-and-close.bx').click(function (event) { 77 | event.stopPropagation(); 78 | close(); 79 | }) 80 | 81 | 82 | var close = function () { 83 | id_svg_dict[noteId] = svg; 84 | window.removeEventListener('message', receive); 85 | if ($("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio").length > 0) { 86 | $("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio").remove(); 87 | } 88 | else { 89 | $("body > div.iframe-drawio").remove(); 90 | $(".tab-row-filler").css("-webkit-app-region", "drag"); 91 | } 92 | $("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper img.note-detail-image-view").css("display", "block"); 93 | var img = $("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper img.note-detail-image-view"); 94 | img.attr("src", img.attr("src")); 95 | /////////////////////////////////// 96 | $('div.component.note-split:not(.hidden-ext) div.component.scrolling-container div.note-detail.component div.note-detail-image-wrapper').click(noteId, function () { 97 | edit(noteId); 98 | }); 99 | }; 100 | 101 | var receive = function (evt) { 102 | if (noteId != currentNoteId || div_iframe == undefined || iframe.contentWindow == null) { return; } 103 | if (evt.data.length > 0) { 104 | var msg = JSON.parse(evt.data); 105 | 106 | // If configure=1 URL parameter is used the application 107 | // waits for this message. For configuration options see 108 | // https://desk.draw.io/support/solutions/articles/16000058316 109 | if (msg.event == 'configure') { 110 | iframe.contentWindow.postMessage(JSON.stringify({ 111 | action: 'configure', 112 | config: { defaultFonts: ["Helvetica", "Verdana", "Times New Roman", "SimSun"], css: " body.geEditor > div.mxWindow:nth-of-type(3) { right: 10px !important; top:63px !important; left: unset !important;} body.geEditor > div.mxWindow:nth-of-type(2) { left: 10px !important; top:63px !important; " }, 113 | mathEnabled: true 114 | }), '*'); 115 | } 116 | else if (msg.event == 'init') { 117 | iframe.contentWindow.postMessage(JSON.stringify({ action: 'load', autosave: 1, xml: svg, saveAndExit: '0', noExitBtn: '1', saveAndExit: '0' }), '*'); //noExitBtn:'1',saveAndExit: '1', 118 | } 119 | else if (msg.event == 'export') { 120 | // Extracts SVG DOM from data URI to enable links 121 | //svg = atob(msg.data.substring(msg.data.indexOf(',') + 1)); 122 | var base64String = msg.data.substring(msg.data.indexOf(',') + 1); 123 | const bytes = new Uint8Array(atob(base64String).split('').map(c => c.charCodeAt(0))); 124 | const decoder = new TextDecoder('utf-8'); 125 | const decodedString = decoder.decode(bytes); 126 | svg = decodedString; 127 | id_svg_dict[noteId] = svg; 128 | api.runAsyncOnBackendWithManualTransactionHandling(async (noteId, svg) => { 129 | const note = await api.getNote(noteId); 130 | note.setContent(svg); 131 | }, [noteId, svg]); 132 | } 133 | else if (msg.event == 'autosave') { 134 | iframe.contentWindow.postMessage(JSON.stringify({ 135 | action: 'export', 136 | format: 'xmlsvg', spin: 'Updating page', 137 | }), '*'); 138 | 139 | } 140 | else if (msg.event == 'save') { 141 | iframe.contentWindow.postMessage(JSON.stringify({ 142 | action: 'export', 143 | format: 'xmlsvg', spin: 'Updating page' 144 | }), '*'); 145 | } 146 | else if (msg.event == 'exit') { 147 | close(); 148 | } 149 | } 150 | }; 151 | 152 | window.addEventListener('message', receive); 153 | }; 154 | 155 | 156 | function addClick(noteId, autoEdit) { 157 | var $img = $('div.component.note-split:not(.hidden-ext) div.component.scrolling-container div.note-detail.component img.note-detail-image-view'); 158 | if (!$img.hasClass('dark') && !$img.hasClass('light')) { 159 | $('div.component.note-split:not(.hidden-ext) div.component.scrolling-container div.note-detail.component div.note-detail-image-wrapper').off("click"); 160 | $('div.component.note-split:not(.hidden-ext) div.component.scrolling-container div.note-detail.component div.note-detail-image-wrapper').click(noteId, function () { 161 | edit(noteId); 162 | }); 163 | } 164 | if (themeStyle.indexOf('dark') >= 0) { $img.addClass('dark'); } 165 | else if (themeStyle.indexOf('light') >= 0) { $img.addClass('light'); } 166 | if (autoEdit) { 167 | edit(noteId); 168 | } 169 | } 170 | 171 | class DrawiIo extends api.NoteContextAwareWidget { 172 | get position() { 173 | return 100; 174 | } 175 | get parentWidget() { 176 | return 'center-pane'; 177 | } 178 | 179 | doRender() { 180 | this.$widget = $(``); 226 | return this.$widget; 227 | } 228 | 229 | async refreshWithNote(note) { 230 | var noteId = note.noteId; 231 | currentNoteId = noteId; 232 | var autoEdit = false; 233 | id_svg_dict[noteId] = (await note.getNoteComplement()).content; 234 | if (note.hasLabel("originalFileName") && note.getLabel("originalFileName").value == "drawio.svg" && (await note.getNoteComplement()).content == undefined) { 235 | id_svg_dict[noteId] = ``; 236 | note.mime = "image/svg+xml"; 237 | autoEdit = true; 238 | api.runAsyncOnBackendWithManualTransactionHandling(async (NoteId, svg) => { 239 | const Note = await api.getNote(NoteId); 240 | Note.setContent(svg); 241 | Note.mime = "image/svg+xml"; 242 | Note.title = Note.title + ".drawio.svg" 243 | Note.save(); 244 | }, [noteId, id_svg_dict[noteId]]); 245 | } 246 | 247 | $(document).ready(function () { 248 | var ischangeTab = false; 249 | if ($last_image_wrapper != undefined && $last_image_wrapper.length > 0) { 250 | window.last_image_wrapper = $last_image_wrapper; 251 | $.each($last_image_wrapper.parents(), function (index, value) { 252 | var truecount = 0; 253 | $.each(value.classList, function (index1, classL) { 254 | if (classL == "note-split") { truecount += 1; } 255 | else if (classL == "hidden-ext") { truecount += 1; } 256 | }); 257 | if (truecount == 2) { 258 | ischangeTab = true; 259 | } 260 | 261 | }); 262 | } 263 | if (last_noteId != undefined && last_noteId == noteId) { 264 | ischangeTab = true; 265 | } 266 | $last_image_wrapper = $("div.component.note-split:not(.hidden-ext) div.scrolling-container.component"); 267 | last_noteId = noteId; 268 | if (!ischangeTab) { 269 | if ($("div.component.note-split:not(.hidden-ext) div.note-detail-image-wrapper div.iframe-drawio").length > 0) { $("div.component.note-split:not(.hidden-ext) div.note-detail-image-wrapper div.iframe-drawio").remove(); } 270 | if ($("div.component.note-split:not(.hidden-ext) .note-detail-printable.component div.note-detail-image-wrapper img.note-detail-image-view").length > 0) { $("div.component.note-split:not(.hidden-ext) .note-detail-printable.component div.note-detail-image-wrapper img.note-detail-image-view").css("display", "block"); } 271 | $('div.component.note-split:not(.hidden-ext) .note-detail-printable.component .note-detail-image-wrapper').off("click"); 272 | var $img = $('div.component.note-split:not(.hidden-ext) .note-detail-printable.component img.note-detail-image-view'); 273 | if ($img.length > 0) { 274 | if ($img.hasClass('dark')) { $img.removeClass('dark') } 275 | if ($img.hasClass('light')) { $img.removeClass('light') } 276 | } 277 | } 278 | if (note.mime != "image/svg+xml" || id_svg_dict[noteId].indexOf("mxfile") < 0) { return; } 279 | setTimeout(function () { 280 | if ($("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio").length > 0) { return; };//When switching tabs, if the iframe is already loaded, return 281 | addClick(noteId, autoEdit); 282 | }, 10); 283 | $("div.ribbon-tab-title.active").click(); 284 | 285 | }); 286 | 287 | } 288 | async entitiesReloadedEvent({ loadResults }) { 289 | if (loadResults.isNoteContentReloaded(this.noteId)) { 290 | this.refresh(); 291 | } 292 | } 293 | } 294 | 295 | module.exports = new DrawiIo(); 296 | 297 | window.onbeforeunload = function () { 298 | if ($("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio").length > 0) { 299 | $("div.component.note-split:not(.hidden-ext) .note-detail-image-wrapper div.iframe-drawio").remove(); 300 | } 301 | else { 302 | $("body > div.iframe-drawio").remove(); 303 | $(".tab-row-filler").css("-webkit-app-region", "drag"); 304 | } 305 | }; 306 | --------------------------------------------------------------------------------