Änderungen von Dokument DiagramSheet
Zuletzt geändert von Daniel Herrmann am 2026/02/04 20:25
Von Version
2.1
bearbeitet von Daniel Herrmann
am 2026/02/04 20:25
am 2026/02/04 20:25
Änderungskommentar:
Install extension [com.xwiki.diagram:application-diagram/1.22.11]
Auf Version 1.1
bearbeitet von Mike Schneider
am 2025/12/30 10:37
am 2025/12/30 10:37
Änderungskommentar:
Install extension [org.xwiki.contrib:application-diagram/1.3]
Zusammenfassung
Details
- Seiteneigenschaften
-
- Dokument-Autor
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. dherrman1 +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
- 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
- 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
- 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