Änderungen von Dokument DiagramSheet

Zuletzt geändert von Daniel Herrmann am 2026/02/04 20:25

Von Version Icon 2.1
bearbeitet von Daniel Herrmann
am 2026/02/04 20:25
Änderungskommentar: Install extension [com.xwiki.diagram:application-diagram/1.22.11]
Auf Version 1.1 Icon
bearbeitet von Mike Schneider
am 2025/12/30 10:37
Änderungskommentar: Install extension [org.xwiki.contrib:application-diagram/1.3]

Zusammenfassung

Details

Icon Seiteneigenschaften
Dokument-Autor
... ... @@ -1,1 +1,1 @@
1 -XWiki.dherrman
1 +XWiki.mschneide
Inhalt
... ... @@ -1,15 +1,5 @@
1 1  {{velocity}}
2 -#set ($diagramObj = $doc.getObject('Diagram.DiagramClass'))
3 -#if ($diagramObj)
4 - #set ($temporaryUploadSupported = ("$!services.temporaryAttachments" != ''))
5 - #set ($diagramConfig = {
6 - "debug": $services.debug.minify.equals(false),
7 - "locale": $xcontext.locale,
8 - "drawIOBasePath": $services.webjars.url('org.xwiki.contrib:draw.io', ''),
9 - "pdfImageExportZoom": $diagramObj.getValue('pdfImageExportZoom'),
10 - "disableExternalServices": $xwiki.getDocument('Diagram.DiagramConfig').getValue('disableExternalServices'),
11 - "isTemporaryUploadSupported": $temporaryUploadSupported
12 - })
2 +#if ($doc.getObject('Diagram.DiagramClass'))
13 13   #if ($xcontext.action == 'edit')
14 14   {{include reference="Diagram.DiagramEditSheet" /}}
15 15   #else
Icon XWiki.JavaScriptExtension[1]
Pufferstrategie
... ... @@ -1,1 +1,0 @@
1 -long
Code
... ... @@ -1,715 +1,0 @@
1 -/**
2 - * Generic helper methods.
3 - */
4 -define('xwiki-utils', ['jquery', 'xwiki-meta'], function($, xm) {
5 - var getAttachmentURL = function(attachment, action, queryString) {
6 - var docRef = xm.documentReference;
7 - if (typeof attachment !== 'string') {
8 - docRef = attachment.parent;
9 - attachment = attachment.name;
10 - }
11 - if (typeof queryString === 'object') {
12 - queryString = $.param(queryString);
13 - }
14 - var attachmentURL = new XWiki.Document(docRef).getURL(action || 'download') +
15 - (docRef.name == 'WebHome' ? docRef.name : '') + '/' + attachment +
16 - (queryString ? '?' + queryString : '');
17 - return attachmentURL;
18 - };
19 -
20 - var temporaryUploadAttachment = function (blob, attachment) {
21 - var documentReference = xm.documentReference;
22 - if (typeof attachment !== 'string') {
23 - documentReference = attachment.parent;
24 - attachment = attachment.name;
25 - }
26 - var doc = new XWiki.Document(documentReference);
27 - var formData = new FormData();
28 - formData.append('upload', blob);
29 - const params = {
30 - 'form_token': xm.form_token,
31 - 'sheet': 'CKEditor.FileUploader',
32 - 'outputSyntax': 'plain',
33 - 'filename': attachment
34 - };
35 - var form = $('form#inline');
36 - return $.ajax({
37 - url : doc.getURL('get', new URLSearchParams(params).toString()),
38 - data : formData,
39 - method: 'POST',
40 - processData : false,
41 - contentType : false, // Sets the 'multipart/form-data' automatically
42 - headers: {
43 - 'X-XWiki-Temporary-Attachment-Support': true
44 - }
45 - }).then(function (response) {
46 - form.append($('<input>')
47 - .prop('type', 'hidden')
48 - .prop('name', 'uploadedFiles')
49 - .prop('value', response.fileName))
50 - }, null);
51 - };
52 -
53 - var uploadAttachment = function(blob, attachment) {
54 - var documentReference = xm.documentReference;
55 - if (typeof attachment !== 'string') {
56 - documentReference = attachment.parent;
57 - attachment = attachment.name;
58 - }
59 - var doc = new XWiki.Document(documentReference);
60 - var url = doc.getURL('upload');
61 - var formData = new FormData();
62 - formData.append('filepath', blob);
63 - formData.append('filename', attachment);
64 - formData.append('form_token', xm.form_token);
65 - // The default redirect adds more time for the upload and we don't need to render those pages.
66 - formData.append('xredirect', doc.getURL('get', 'outputSyntax=plain'));
67 - return $.post({
68 - url : url,
69 - data : formData,
70 - processData : false,
71 - contentType : false
72 - });
73 - };
74 -
75 - var deleteAttachment = function(attachmentName) {
76 - var attachmentURL = getAttachmentURL(attachmentName, 'delattachment', {
77 - 'form_token': xm.form_token,
78 - 'xredirect': XWiki.currentDocument.getURL('get', 'outputSyntax=plain')
79 - });
80 - return $.post(attachmentURL);
81 - };
82 -
83 - return {
84 - getAttachmentURL: getAttachmentURL,
85 - uploadAttachment: uploadAttachment,
86 - deleteAttachment: deleteAttachment,
87 - temporaryUploadAttachment: temporaryUploadAttachment
88 - };
89 -});
90 -
91 -/**
92 - * Diagram application configuration received from the server side.
93 - */
94 -define('diagram-config', ['jquery'], function($) {
95 - return $('[data-diagram-config]').data('diagramConfig');
96 -});
97 -
98 -/**
99 - * Diagram application setup.
100 - */
101 -define('diagram-setup', ['diagram-config'], function(diagramConfig) {
102 - window.mxIsElectron = false;
103 - var drawIOBasePath = diagramConfig.drawIOBasePath;
104 - // mxGraph client setup
105 - window.mxBasePath = drawIOBasePath + 'mxgraph';
106 - window.mxImageBasePath = drawIOBasePath + 'mxgraph/images';
107 - window.mxLanguage = diagramConfig.locale;
108 -
109 - // draw.io setup
110 - window.DRAWIO_SERVER_URL = "https://app.diagrams.net/";
111 - window.RESOURCES_PATH = drawIOBasePath + 'resources';
112 - window.RESOURCE_BASE = RESOURCES_PATH + '/dia';
113 - window.STENCIL_PATH = drawIOBasePath + 'stencils';
114 - window.IMAGE_PATH = drawIOBasePath + 'images';
115 - window.STYLE_PATH = window.CSS_PATH = drawIOBasePath + 'styles';
116 - window.SHAPES_PATH = drawIOBasePath + 'shapes';
117 - window.GRAPH_IMAGE_PATH = drawIOBasePath + 'img';
118 - window.TEMPLATE_PATH = drawIOBasePath + 'templates';
119 - // This is used by File > Open Library from > Browser...
120 - window.OPEN_FORM = drawIOBasePath + 'open.html';
121 - window.OPEN_URL = new XWiki.Document('DiagramImporter', 'Diagram').getURL('get', 'outputSyntax=plain');
122 - window.EXPORT_URL = ' ';
123 - window.PROXY_URL = new XWiki.Document('DiagramProxy', 'Diagram').getURL('get');
124 - window.isLocalStorage = true;
125 - // mxClient is not considering the basePath of the stylesheet files, so we load them after.
126 - window.mxLoadStylesheets = false;
127 -
128 - window.urlParams = (function(params) {
129 - var pairs = window.location.search.substr(1).split('&');
130 - pairs.forEach(function(pair) {
131 - var parts = pair.split('=', 2);
132 - if (parts.length === 2) {
133 - params[parts[0]] = decodeURIComponent(parts[1].replace(/\+/g, " "));
134 - }
135 - });
136 - return params;
137 - })({
138 - // Don't show the splash screen.
139 - 'splash': '0',
140 - // Disable the GitHub integration.
141 - 'gh': '0',
142 - // Disable the GitLab integration.
143 - 'gl': '0',
144 - // Explicitly enable the tabbed UI.
145 - 'pages': '1',
146 - // Disable the Dropbox integration.
147 - 'db': '0',
148 - // Disable the Google Drive integration.
149 - 'gapi': '0',
150 - // Disable Google Analytics.
151 - 'analytics': '0',
152 - // Disable the One Drive integration.
153 - 'od': '0',
154 - // Disable the Trello integration.
155 - 'tr': '0',
156 - // Disable realtime collaboration.
157 - 'sync': 'none'
158 - });
159 -
160 - // Disabling the integration with these external services is not enough because the draw.io code has hard-coded
161 - // references.
162 - window.DriveFile = window.DropboxFile = window.GitHubFile = window.OneDriveFile = window.TrelloFile = false;
163 - window.DriveLibrary = window.DropboxLibrary = window.GitHubLibrary = window.OneDriveLibrary = window.TrelloLibrary
164 - = false;
165 -
166 - require.config({
167 - paths: {
168 - 'base64': drawIOBasePath + 'js/deflate/base64.min',
169 - 'jscolor': drawIOBasePath + 'js/jscolor/jscolor.min',
170 - 'pako': drawIOBasePath + 'js/deflate/pako.min',
171 - 'sanitizer': drawIOBasePath + 'js/sanitizer/purify.min',
172 - 'spin': drawIOBasePath + 'js/spin/spin.min',
173 - 'jszip': drawIOBasePath + 'js/jszip/jszip.min',
174 - 'mermaid': drawIOBasePath + 'js/mermaid/mermaid.min',
175 - 'freehand': drawIOBasePath + 'js/freehand/perfect-freehand',
176 - 'rough': drawIOBasePath + 'js/rough/rough.min',
177 - 'mxgraph-init': drawIOBasePath + 'js/draw.io.init.min',
178 - 'mxgraph-client': drawIOBasePath + 'mxgraph/mxClient',
179 - 'mxgraph-editor': drawIOBasePath + 'js/draw.io.grapheditor.min',
180 - 'mxgraph-viewer': drawIOBasePath + 'js/draw.io.graphviewer.min',
181 - 'draw.io': drawIOBasePath + 'js/draw.io.min',
182 - 'draw.io.viewer': drawIOBasePath + 'js/draw.io.viewer.min',
183 - 'resourceSelector': new XWiki.Document('WebHome', 'Diagram.ResourceSelector').getURL('jsx', 'minify=' + !diagramConfig.debug)
184 - },
185 - shim: {
186 - 'mxgraph-client': ['mxgraph-init'],
187 - 'mxgraph-editor': ['noDocWrite!mxgraph-client', 'jscolor', 'sanitizer-global'],
188 - 'mxgraph-viewer': ['noDocWrite!mxgraph-client', 'sanitizer-global'],
189 - 'draw.io': ['mxgraph-editor', 'base64', 'pako-global', 'spin-global', 'jszip-global', 'mermaid-global', 'freehand', 'rough'],
190 - 'draw.io.viewer': ['mxgraph-viewer', 'pako-global', 'spin-global', 'rough']
191 - }
192 - });
193 -
194 - define('pako-global', ['pako'], function(pako) {
195 - // draw.io expects a global variable.
196 - window.pako = pako;
197 - });
198 -
199 - define('spin-global', ['spin'], function(spin) {
200 - // draw.io expects a global variable.
201 - window.Spinner = spin;
202 - });
203 -
204 - define('jszip-global', ['jszip'], function(JSZip) {
205 - // draw.io expects a global variable.
206 - window.JSZip = JSZip;
207 - });
208 -
209 - define('sanitizer-global', ['sanitizer'], function(sanitizer) {
210 - // draw.io expects a global variable.
211 - window.DOMPurify = sanitizer;
212 - });
213 -
214 - define('mermaid-global', ['mermaid'], function(mermaid) {
215 - // draw.io expects a global variable.
216 - window.mermaid = mermaid;
217 - });
218 -
219 - // Disable document.write() while loading modules that call this API in order to prevent warning messages in the
220 - // JavaScript console.
221 - define('noDocWrite', {
222 - load: function (name, req, onload, config) {
223 - var originalDocWrite = document.write;
224 - document.write = function() {};
225 - req([name], function (value) {
226 - document.write = originalDocWrite;
227 - onload(value);
228 - });
229 - }
230 - });
231 -});
232 -
233 -/**
234 - * Handles links to wiki pages (this is used by both the diagram viewer and the diagram editor).
235 - */
236 -define('diagram-link-handler', ['xwiki-utils', 'draw.io.common'], function(xutils) {
237 - // See https://about.draw.io/interactive-diagrams-with-custom-links-and-actions/
238 - // See https://desk.draw.io/support/solutions/articles/16000080137
239 - // See https://jgraph.github.io/drawio-tools/tools/link.html
240 - var xwikiCustomLinkPrefix = 'data:xwiki/reference,';
241 - var isXWikiCustomLink = function(href) {
242 - return typeof href === 'string' && href.substring(0, xwikiCustomLinkPrefix.length) === xwikiCustomLinkPrefix;
243 - };
244 -
245 - var getResourceReferenceFromCustomLink = function(href) {
246 - if (isXWikiCustomLink(href)) {
247 - var resourceReference = href.substring(xwikiCustomLinkPrefix.length);
248 - var typeSeparatorIndex = resourceReference.indexOf(':');
249 - if (typeSeparatorIndex >= 0) {
250 - return {
251 - type: resourceReference.substring(0, typeSeparatorIndex),
252 - reference: resourceReference.substring(typeSeparatorIndex + 1)
253 - }
254 - }
255 - }
256 - if (href) {
257 - return {
258 - type: 'url',
259 - reference: href
260 - };
261 - }
262 - };
263 -
264 - var getCustomLinkFromResourceReference = function(resourceReference) {
265 - if (resourceReference.type === 'url') {
266 - return resourceReference.reference || '';
267 - } else if (resourceReference.type) {
268 - return xwikiCustomLinkPrefix + resourceReference.type + ':' + (resourceReference.reference || '');
269 - } else {
270 - // An empty link usually means that the link should be removed.
271 - return '';
272 - }
273 - };
274 -
275 - var getURLFromResourceReference = function(resourceReference, diagramReference) {
276 - switch (resourceReference.type) {
277 - case 'doc':
278 - let documentReference = XWiki.Model.resolve(resourceReference.reference, XWiki.EntityType.DOCUMENT,
279 - XWiki.currentDocument.documentReference);
280 - return new XWiki.Document(documentReference).getURL();
281 - case 'attach':
282 - // The diagram reference is used for the attachment reference only if is specified. This is needed when the
283 - // diagram is displayed on another page. See https://github.com/xwikisas/application-diagram/issues/121
284 - let attachmentReference = XWiki.Model.resolve(resourceReference.reference, XWiki.EntityType.ATTACHMENT,
285 - diagramReference || XWiki.currentDocument.documentReference);
286 - return xutils.getAttachmentURL(attachmentReference);
287 - default:
288 - return resourceReference.reference;
289 - }
290 - };
291 -
292 - var getURLFromCustomLink = function(href, diagramReference) {
293 - let resourceReference = getResourceReferenceFromCustomLink(href);
294 - return getURLFromResourceReference(resourceReference, diagramReference);
295 - };
296 -
297 - var originalHandleCustomLink = Graph.prototype.handleCustomLink;
298 - Graph.prototype.handleCustomLink = function(href) {
299 - let actualHref = href;
300 - if (isXWikiCustomLink(href)) {
301 - actualHref = 'data:action/json,' + JSON.stringify({'actions': [{'open': getURLFromCustomLink(href)}]});
302 - }
303 - return originalHandleCustomLink.call(this, actualHref);
304 - };
305 -
306 - var originalGetLinkTitle = EditorUi.prototype.getLinkTitle;
307 - EditorUi.prototype.getLinkTitle = function(href) {
308 - if (isXWikiCustomLink(href)) {
309 - let resourceReference = getResourceReferenceFromCustomLink(href);
310 - return resourceReference.type + ':' + resourceReference.reference;
311 - } else {
312 - return originalGetLinkTitle.apply(this, arguments);
313 - }
314 - };
315 -
316 - var getFragmentIdentifierFromURL = function(url) {
317 - if (typeof url === 'string' && url.substring(0, 5) !== 'data:') {
318 - fragmentIdentifierPosition = url.indexOf('#');
319 - if (fragmentIdentifierPosition >= 0) {
320 - var fragmentIdentifier = url.substring(fragmentIdentifierPosition + 1);
321 - try {
322 - return decodeURIComponent(fragmentIdentifier);
323 - } catch (e) {
324 - // Malformed URI sequence. Return the fragment identifier as is.
325 - return fragmentIdentifier;
326 - }
327 - }
328 - }
329 - };
330 -
331 - var getCustomLinkFromURL = function(url) {
332 - if (isXWikiCustomLink(url)) {
333 - return url;
334 - } else {
335 - var fragmentIdentifier = getFragmentIdentifierFromURL(url);
336 - if (isXWikiCustomLink(fragmentIdentifier)) {
337 - return fragmentIdentifier;
338 - }
339 - }
340 - };
341 -
342 - return {
343 - isXWikiCustomLink: isXWikiCustomLink,
344 - getResourceReferenceFromCustomLink: getResourceReferenceFromCustomLink,
345 - getCustomLinkFromResourceReference: getCustomLinkFromResourceReference,
346 - getCustomLinkFromURL: getCustomLinkFromURL,
347 - getURLFromCustomLink: getURLFromCustomLink,
348 - getURLFromResourceReference: getURLFromResourceReference
349 - };
350 -});
351 -
352 -/**
353 - * Filters the Graph XML when:
354 - * <ul>
355 - * <li>
356 - * the XML is <b>loaded</b> from the XWiki database
357 - * <ul>
358 - * <li>convert the draw.io WAR paths to draw.io WebJar paths (e.g. include the draw.io version)</li>
359 - * <li>replace the attachment reference from the image source with the attachment URL</li>
360 - * </ul>
361 - * </li>
362 - * <li>
363 - * the XML is <b>saved</b> to the XWiki database
364 - * <ul>
365 - * <li>convert the draw.io WebJar paths to draw.io WAR paths (e.g. remove the draw.io version)</li>
366 - * <li>internal links should be saved using the entity reference instead of the entity URL</li>
367 - * <li>internal images should be saved using the attachment reference instead of the attachment URL</li>
368 - * </ul>
369 - * </li>
370 - * <li>
371 - * the XML is <b>imported</b> from an external source
372 - * <ul>
373 - * <li>convert the draw.io WAR paths to draw.io WebJar paths (e.g. include the draw.io version)</li>
374 - * <li>replace absolute URLs with internal custom links, if the target entity reference is indicated</li>
375 - * </ul>
376 - * </li>
377 - * <li>
378 - * the XML is <b>exported</b> to an external source
379 - * <ul>
380 - * <li>convert the draw.io WebJar paths to draw.io WAR paths (e.g. remove the draw.io version)</li>
381 - * <li>convert attached images to data URI (but keep some metadata to idicate the attachment reference)</li>
382 - * <li>replace custom internal links with absolute URLs (but keep some metadata to indicate the entity reference)</li>
383 - * </ul>
384 - * </li>
385 - * </ul>
386 - */
387 -define('diagram-graph-xml-filter', ['jquery', 'diagram-config', 'diagram-link-handler'], function($, diagramConfig, diagramLinkHandler) {
388 - var originalGetGraphXml = Editor.prototype.getGraphXml;
389 - Editor.prototype.getGraphXml = function(ignoreSelection, forStorage) {
390 - var node = originalGetGraphXml.apply(this, arguments);
391 - var filterImage = forStorage === true ? onSaveImage : onExportImage;
392 - var filterLink = forStorage === true ? onSaveLink : onExportLink;
393 - var filterBackgroundImage = forStorage === true ? onSaveBackgroundImage : onExportBackgroundImage;
394 - filter(this.graph, node, filterImage, filterLink, filterBackgroundImage);
395 - return node;
396 - };
397 -
398 - var originalSetGraphXml = Editor.prototype.setGraphXml;
399 - Editor.prototype.setGraphXml = function(node) {
400 - var filterImage = node.fromStorage === true ? onLoadImage : onImportImage;
401 - var filterLink = node.fromStorage === true ? onLoadLink : onImportLink;
402 - var filterBackgroundImage = node.forStorage === true ? onLoadBackgroundImage : onImportBackgroundImage;
403 - filter(this.graph, node, filterImage, filterLink, filterBackgroundImage);
404 - originalSetGraphXml.call(this, node);
405 - };
406 -
407 - var originalImportGraphModel = Graph.prototype.importGraphModel;
408 - Graph.prototype.importGraphModel = function(node, dx, dy, crop) {
409 - filter(this, node, onImportImage, onImportLink, onImportBackgroundImage);
410 - return originalImportGraphModel.call(this, node, dx, dy, crop);
411 - };
412 -
413 - var filter = function(graph, node, filterImage, filterLink, filterBackgroundImage) {
414 - findImageNodes(node).each(function() {
415 - filterImage(this, graph);
416 - });
417 - findLinkNodes(node).each(function() {
418 - filterLink(this, graph);
419 - });
420 - filterBackgroundImage(node);
421 - };
422 -
423 - var findImageNodes = function(node) {
424 - return $(node).find('mxCell[style*="image;"], mxCell[style*="shape=image;"]');
425 - };
426 -
427 - var findLinkNodes = function(node) {
428 - return $(node).find('UserObject[link], mxCell[value*="\\<a href"]');
429 - };
430 -
431 - // Convert the draw.io WebJar paths to draw.io WAR paths (e.g. remove the draw.io version from the path).
432 - // Internal images should be saved using the attachment reference instead of the attachment URL.
433 - var drawIOBasePath = diagramConfig.drawIOBasePath;
434 - var onSaveImage = function(node, graph) {
435 - var style = $(node).attr('style') || '';
436 - var styleObject = graph.stylesheet.getCellStyle(style, {});
437 - var oldSource = styleObject.image || '';
438 - var newSource = oldSource;
439 - if (oldSource.substring(0, drawIOBasePath.length) === drawIOBasePath) {
440 - // Convert draw.io WebJar URL to draw.io WAR path.
441 - // See https://github.com/xwikisas/application-diagram/issues/11
442 - newSource = oldSource.substring(drawIOBasePath.length);
443 - } else {
444 - var customLink = diagramLinkHandler.getCustomLinkFromURL(oldSource);
445 - if (customLink) {
446 - // Save the XWiki attachment reference instead of the attachment URL.
447 - // We have to encode the value in order to avoid breaking the style string.
448 - newSource = encodeURIComponent(customLink);
449 - }
450 - }
451 - if (newSource !== oldSource) {
452 - $(node).attr('style', style.replace(oldSource, newSource));
453 - }
454 - };
455 -
456 - // Convert the draw.io WAR paths to draw.io WebJar paths (e.g. include the draw.io version in the path).
457 - // Replace the attachment reference from the image source with the attachment URL.
458 - var onLoadImage = function(node, graph) {
459 - var style = $(node).attr('style') || '';
460 - var styleObject = graph.stylesheet.getCellStyle(style, {});
461 - var oldSource = styleObject.image || '';
462 - var newSource = oldSource;
463 - if (oldSource.substring(0, 4) === 'img/') {
464 - // Convert draw.io WAR path to draw.io WebJar URL.
465 - // See https://github.com/xwikisas/application-diagram/issues/11
466 - newSource = drawIOBasePath + oldSource;
467 - } else {
468 - try {
469 - var decodedOldSource = decodeURIComponent(oldSource);
470 - if (diagramLinkHandler.isXWikiCustomLink(decodedOldSource)) {
471 - // Replace the attachment reference from the image source with the attachment URL, but keep the attachment
472 - // reference in the fragment identifier in order to be able to restore it on save.
473 - var diagramReference = XWiki.Model.resolve($(graph.container).data('reference'), XWiki.EntityType.DOCUMENT);
474 - newSource = diagramLinkHandler.getURLFromCustomLink(decodedOldSource, diagramReference) + '#' + oldSource;
475 - }
476 - } catch (e) {
477 - // Ignore.
478 - }
479 - }
480 - if (newSource !== oldSource) {
481 - $(node).attr('style', style.replace(oldSource, newSource));
482 - }
483 - };
484 -
485 - // Convert the draw.io WebJar paths to draw.io WAR paths (e.g. remove the draw.io version).
486 - // Convert attached images to data URI (but keep some metadata to idicate the attachment reference).
487 - var onExportImage = function(node, graph) {
488 - var style = $(node).attr('style') || '';
489 - var styleObject = graph.stylesheet.getCellStyle(style, {});
490 - var oldSource = styleObject.image || '';
491 - var newSource = convertImageLink(oldSource, true);
492 - var customLink = diagramLinkHandler.getCustomLinkFromURL(oldSource);
493 - if (customLink) {
494 - // For image attachments, keep some metadata to indicate the original source.
495 - style = mxUtils.setStyle(style, 'xwikiImage', encodeURIComponent(customLink));
496 - }
497 - if (newSource !== oldSource) {
498 - $(node).attr('style', style.replace(oldSource, newSource));
499 - }
500 - };
501 -
502 - var onImportBackgroundImage = function(node) {
503 - // Do nothing.
504 - };
505 -
506 - var onSaveBackgroundImage = function(node) {
507 - // Do nothing.
508 - };
509 -
510 - var onLoadBackgroundImage = function(node) {
511 - // Do nothing.
512 - };
513 -
514 - var onExportBackgroundImage = function(node) {
515 - if (node.getAttribute('backgroundImage') == undefined) {
516 - return;
517 - }
518 - var backgroundImage = JSON.parse(node.getAttribute('backgroundImage'));
519 - var oldSource = backgroundImage.src;
520 - var newSource = convertImageLink(oldSource);
521 - var customLink = diagramLinkHandler.getCustomLinkFromURL(oldSource);
522 - if (customLink) {
523 - // For image attachments, keep some metadata to indicate the original source.
524 - backgroundImage.xwikiImage = encodeURIComponent(customLink);
525 - }
526 - if (newSource !== oldSource) {
527 - backgroundImage.src = newSource;
528 - node.setAttribute('backgroundImage', JSON.stringify(backgroundImage));
529 - }
530 - };
531 -
532 - var convertImageLink = function(oldSource, removeBase) {
533 - var newSource = oldSource;
534 - if (oldSource.substring(0, drawIOBasePath.length) === drawIOBasePath) {
535 - // Convert the draw.io WebJar paths to draw.io WAR paths (e.g. remove the draw.io version).
536 - newSource = oldSource.substring(drawIOBasePath.length);
537 - } else if (oldSource.substring(0, 5) !== 'data:') {
538 - // Convert other images to data URI.
539 - newSource = maybeConvertToDataURI(oldSource, removeBase);
540 - }
541 - return newSource;
542 - };
543 -
544 - var maybeConvertToDataURI = function(url, removeBase) {
545 - var image = getCachedImageByURL(url);
546 - if (image) {
547 - var canvas = document.createElement('canvas');
548 - var context2D = canvas.getContext('2d');
549 - canvas.height = image.naturalHeight;
550 - canvas.width = image.naturalWidth;
551 - context2D.drawImage(image, 0, 0);
552 - try {
553 - url = canvas.toDataURL();
554 - var semicolonIndex = url.indexOf(';');
555 - // Remove temporarily 'base64,' when the url is used in a style attribute, since a split is done by ',' afterwards.
556 - if (semicolonIndex > 0 && removeBase ) {
557 - url = url.substring(0, semicolonIndex) + url.substring(url.indexOf(',', semicolonIndex + 1));
558 - }
559 - } catch (e) {
560 - // Ignore.
561 - }
562 - }
563 - return url;
564 - };
565 -
566 - var diagramImages = {};
567 - var collectImages = function() {
568 - $(this.diagramContainer).find('image').each(function() {
569 - var absoluteURL = $(this).attr('xlink:href');
570 - if (diagramImages.hasOwnProperty(absoluteURL)) {
571 - return;
572 - }
573 - var image = diagramImages[absoluteURL] = new Image();
574 - image.crossOrigin = 'use-credentials';
575 - image.src = absoluteURL;
576 - });
577 - };
578 - $(document).on('diagramEditorCreated', function(event, editorUI) {
579 - editorUI.editor.addListener('fileLoaded', $.proxy(collectImages, editorUI));
580 - editorUI.editor.graph.model.addListener(mxEvent.CHANGE, $.proxy(collectImages, editorUI));
581 - });
582 -
583 - var getCachedImageByURL = function(url) {
584 - var absoluteURL = $('<a/>').attr('href', url).prop('href');
585 - var image = diagramImages[absoluteURL];
586 - if (image && image.complete && image.naturalWidth) {
587 - return image;
588 - }
589 - };
590 -
591 - // Convert the draw.io WAR paths to draw.io WebJar paths (e.g. include the draw.io version in the path).
592 - var onImportImage = function(node, graph) {
593 - onLoadImage(node, graph);
594 - };
595 -
596 - var onSaveLink = function(node) {
597 - // Nothing to do here (save the link as is).
598 - };
599 -
600 - var onLoadLink = function(node) {
601 - // Nothing to do here (keep the link as is).
602 - };
603 -
604 - // Replace custom internal links with absolute URLs (but keep some metadata to indicate the entity reference).
605 - // Consider both the cases when the node is UserObject or mxCell.
606 - var onExportLink = function(node) {
607 - var tagName = node.tagName.toLowerCase();
608 - var value = $(node).attr('value');
609 - var href = $('<div></div>').html(value).find('a[href]').attr('href');
610 - var link = tagName == 'userobject' ? $(node).attr('link') : href;
611 - if (diagramLinkHandler.isXWikiCustomLink(link)) {
612 - var url = diagramLinkHandler.getURLFromCustomLink(link);
613 - var absoluteURL = $('<a/>').attr('href', url).prop('href');
614 - updateLinkAttributes(node, value, link, absoluteURL);
615 - }
616 - };
617 -
618 - // Replace absolute URLs with internal custom links, if the target entity reference is indicated.
619 - var onImportLink = function(node) {
620 - var link = $(node).attr('data-link');
621 - if (diagramLinkHandler.isXWikiCustomLink(link)) {
622 - var value = $(node).attr('value');
623 - var href = $('<div></div>').html(value).find('a[href]').attr('href');
624 - updateLinkAttributes(node, value, href, link);
625 - }
626 - };
627 -
628 - var updateLinkAttributes = function(node, value, oldURL, newURL) {
629 - var attributesMap = {'data-link': null};
630 - if (node.tagName.toLowerCase() == 'userobject') {
631 - attributesMap.link = newURL;
632 - } else {
633 - attributesMap.value = value.replace(oldURL, newURL);
634 - }
635 - $(node).attr(attributesMap);
636 - };
637 -});
638 -
639 -/**
640 - * Utility functions used in both view and edit modes.
641 - */
642 -define('diagram-utils', ['jquery', 'diagram-link-handler'], function($, diagramLinkHandler) {
643 - //
644 - // Get a XML diagram from hash.
645 - // The hash begins with 'R' & continues with the encoded diagram.
646 - //
647 - var getDiagramXMLFromURL = function(url) {
648 - let hashIndex = url.indexOf('#R');
649 - if (hashIndex > -1) {
650 - // Exclude first 2 letters from hash (#R).
651 - let hash = url.substring(hashIndex+2);
652 - try {
653 - let decodedData = decodeURIComponent(hash);
654 - // Drawio uses a combination of URL encoding and base64 encoding in the hash and this breaks the import.
655 - // Since we decompress the diagram in our code when we save the page we can get rid of the
656 - // graph.decompress method and just return the serialized DOM with the imported diagram.
657 - const parser = new DOMParser();
658 - const xmlDoc = parser.parseFromString(decodedData, "application/xml");
659 - return new XMLSerializer().serializeToString(xmlDoc);
660 - } catch (e) {
661 - console.error(e.stack)
662 - }
663 - }
664 - return null;
665 - };
666 -
667 - //
668 - // Load the translation file and the default theme.
669 - //
670 - var loadTranslationAndTheme = function() {
671 - var deferred = $.Deferred();
672 - mxResources.loadDefaultBundle = false;
673 - var bundle = mxResources.getDefaultBundle(RESOURCE_BASE, mxLanguage) ||
674 - mxResources.getSpecialBundle(RESOURCE_BASE, mxLanguage);
675 - // The theme is important because it controls how the shapes are rendered.
676 - mxUtils.getAll([bundle, STYLE_PATH + '/default.xml'], function(response) {
677 - // Adds bundle text to resources.
678 - mxResources.parse(response[0].getText());
679 - deferred.resolve(response[1].getDocumentElement());
680 - }, function() {
681 - // Failed to load the translation file or the theme.
682 - deferred.reject();
683 - });
684 - return deferred.promise();
685 - };
686 -
687 - //
688 - // Fix XWiki custom links in print preview.
689 - //
690 - var originalPrintPreviewAddGraphFragment = mxPrintPreview.prototype.addGraphFragment;
691 - mxPrintPreview.prototype.addGraphFragment = function(dx, dy, scale, pageNumber, div, clip) {
692 - var result = originalPrintPreviewAddGraphFragment.apply(this, arguments);
693 - // Convert XWiki custom links to absolute URLs.
694 - $(div).find('a').each(function() {
695 - // We have to update both SVG links and HTML links (within foreign objects).
696 - ['xlink:href', 'href'].forEach(function(name) {
697 - var value = $(this).attr(name);
698 - if (diagramLinkHandler.isXWikiCustomLink(value)) {
699 - var url = diagramLinkHandler.getURLFromCustomLink(value);
700 - var absoluteURL = $('<a/>').attr('href', url).prop('href');
701 - $(this).attr(name, absoluteURL);
702 - }
703 - }, this);
704 - });
705 - return result;
706 - };
707 -
708 - // Add the required stylesheets, since in mxClient the basePath of the stylesheets is not considered.
709 - mxClient.link('stylesheet', mxClient.basePath + '/css/common.css');
710 -
711 - return {
712 - getDiagramXMLFromURL: getDiagramXMLFromURL,
713 - loadTranslationAndTheme: loadTranslationAndTheme
714 - };
715 -});
Name
... ... @@ -1,1 +1,0 @@
1 -Code used in both view and edit modes
Inhalt parsen
... ... @@ -1,1 +1,0 @@
1 -Nein
Benutze diese Erweiterung
... ... @@ -1,1 +1,0 @@
1 -onDemand
Icon XWiki.StyleSheetExtension[0]
Pufferstrategie
... ... @@ -1,1 +1,0 @@
1 -long
Code
... ... @@ -1,182 +1,0 @@
1 -/* The diagram styles should be loaded after the skin and before our overwrites. */
2 -@import url("$services.webjars.url('org.xwiki.contrib:draw.io', 'styles/grapheditor.css')");
3 -
4 -/**
5 - * Diagram Editor and Dialogs
6 - */
7 -.diagram-editor {
8 - height: 600px;
9 - min-height: 20px;
10 - position: relative;
11 -}
12 -
13 -.diagram-editor input[type="checkbox"], .diagram-editor input[type="radio"],
14 -.mxPopupMenu input[type="checkbox"], .mxPopupMenu input[type="radio"],
15 -.mxWindow input[type="checkbox"], .mxWindow input[type="radio"],
16 -.geDialog input[type="checkbox"], .geDialog input[type="radio"] {
17 - vertical-align: text-bottom;
18 -}
19 -
20 -.fullScreenWrapper .buttons > .buttonwrapper:first-child {
21 - /* Hide the "Exit Full Screen" button. We have a tool bar entry for this. */
22 - display: none !important;
23 -}
24 -
25 -/**
26 - * Overwrite XWiki skin styles
27 - */
28 -.diagram-editor *,
29 -.mxPopupMenu *,
30 -.mxWindow *,
31 -.geDialog,
32 -.geDialog * {
33 - box-sizing: content-box;
34 -}
35 -
36 -.mxPopupMenu,
37 -.mxWindow,
38 -.geDialog {
39 - /* We need the same font size as on draw.io because the dialog height is hard-coded. */
40 - font-size: 10pt;
41 -}
42 -
43 -.diagram-editor button, .diagram-editor select,
44 -.mxPopupMenu button, .mxPopupMenu select,
45 -.mxWindow button, .mxWindow select,
46 -.geDialog button, .geDialog select {
47 - box-sizing: border-box;
48 -}
49 -
50 -.diagram-editor input[type="text"],
51 -.mxPopupMenu input[type="text"],
52 -.mxWindow input[type="text"],
53 -.geDialog input[type="text"] {
54 - font-size: inherit;
55 - height: auto;
56 - padding: 1px;
57 -}
58 -
59 -.diagram-editor img,
60 -.mxPopupMenu img,
61 -.mxWindow img,
62 -.geDialog img {
63 - vertical-align: baseline;
64 -}
65 -
66 -.diagram-editor hr,
67 -.mxPopupMenu hr,
68 -.mxWindow hr,
69 -.geDialog hr {
70 - margin: 0;
71 -}
72 -
73 -.mxPopupMenu table,
74 -.mxWindow table,
75 -.geDialog table {
76 - margin-bottom: 0;
77 - width: auto;
78 -}
79 -
80 -.diagram-editor table > tbody > tr > td,
81 -.mxPopupMenu table > tbody > tr > td,
82 -.mxWindow table > tbody > tr > td,
83 -.geDialog table > tbody > tr > td {
84 - border-top: 0 none;
85 -}
86 -
87 -.geDialog table > tbody > tr > td {
88 - padding: 0;
89 - vertical-align: baseline;
90 -}
91 -
92 -.geDialog h3 {
93 - font-size: 1.17em;
94 - font-weight: bold;
95 -}
96 -
97 -.geDialog input[type='checkbox'] {
98 - vertical-align: baseline;
99 -}
100 -
101 -.geDialog label {
102 - display: inline;
103 -}
104 -
105 -.geDialog textarea {
106 - padding: inherit;
107 -}
108 -/**
109 - * Diagram Viewer
110 - */
111 -.diagram {
112 - /* Leave space for the toolbar. */
113 - margin-top: 30px;
114 - /* Make sure the diagram container always has some width (when not hidden) otherwise draw.io will think it's hidden
115 - and thus will delay the diagram rendering until it becomes visible. */
116 - min-width: 1px;
117 -}
118 -
119 -/**
120 - * Diagram Macro
121 - */
122 -.geDiagramContainer,
123 -.diagram-container > .thumbnail {
124 - max-width: 100%;
125 -}
126 -
127 -.diagram-container > .thumbnail {
128 - display: inline-block;
129 -}
130 -
131 -.diagram-container > .thumbnail .box {
132 - margin-bottom: 0;
133 -}
134 -
135 -.externalServicesDialog {
136 - text-align: center;
137 - padding: 2%;
138 - overflow: auto;
139 - line-height: 1.3em;
140 -}
141 -
142 -/* TODO when upgrading the parent
143 -Right now, there is no defined LESS value for the background color. If, in the future, a LESS variable is defined in https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/less/variablesInit.vm#L22-L27, we should swap to that. */
144 -.geEditor button.btn-primary:hover, .geEditor #tmDrawerActivator:hover {
145 - background-color: #2F6EAD;
146 -}
147 -
148 -/* This is not the ideal solution, but it's the only one that worked. I also tried using revert, revert-layer, and unset, but nothing else worked except this. */
149 -.geEditor button.close {
150 - font-size: x-large;
151 -}
152 -
153 -/* Solves the weird placement of buttons inside the More Shapes modal */
154 -.geEditor .geDialogFooter button {
155 - line-height: revert;
156 -}
157 -
158 -/* Draw.io added a gray border to all the panels, and this rule reverts the color back to transparent. */
159 -.geEditor .panel {
160 - border-color: transparent;
161 -}
162 -
163 -/* Disabled the button that changed the light/dark mode because I couldn't position it to make it look good. You can still modify the appearance in the Extras -> Appearance tab. */
164 -.geToolbarButton.geAdaptiveAsset {
165 - display: none;
166 -}
167 -
168 -/* Extend the width of the inputs that are located in the pdf export modal. */
169 -.geDialog tbody input {
170 - /* The original width which is too is directly on the element so we need the !imporant directive to make it work. */
171 - width: 70px !important;
172 -}
173 -
174 -/* Disables the highlighting of the panel with the figures, allowing us to drag and drop elements. */
175 -.geSidebarContainer {
176 - user-select: none;
177 -}
178 -
179 -/* Properly align the radio buttons in the change background popup. */
180 -input[name="geBackgroundImageDialogOption"] {
181 - margin-bottom: 0px !important;
182 -}
Content Type
... ... @@ -1,1 +1,0 @@
1 -CSS
Name
... ... @@ -1,1 +1,0 @@
1 -CSS
Inhalt parsen
... ... @@ -1,1 +1,0 @@
1 -Ja
Benutze diese Erweiterung
... ... @@ -1,1 +1,0 @@
1 -onDemand
Icon XWiki.StyleSheetExtension[1]
Pufferstrategie
... ... @@ -1,1 +1,0 @@
1 -long
Code
... ... @@ -1,11 +1,0 @@
1 -/* Overwrite the graph editor styles that affect the XWiki UI */
2 -body.geEditor {
3 - font-family: @font-family-base;
4 - font-size: @font-size-base;
5 -}
6 -
7 -/* Overwrite the .geEditor button to make all the primary buttons and the drawer button the right color. */
8 -.geEditor button.btn-primary, .geEditor #tmDrawerActivator {
9 - background-color: @btn-primary-bg;
10 -}
11 -
Content Type
... ... @@ -1,1 +1,0 @@
1 -LESS
Name
... ... @@ -1,1 +1,0 @@
1 -LESS
Inhalt parsen
... ... @@ -1,1 +1,0 @@
1 -Nein
Benutze diese Erweiterung
... ... @@ -1,1 +1,0 @@
1 -onDemand