├── 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 | 
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(`
`);
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 |
--------------------------------------------------------------------------------