Jelajahi Sumber

13.7.2 release

David Benson [draw.io] 4 tahun lalu
induk
melakukan
916290d3e8

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+16-SEP-2020: 13.7.2
+
+- Removes PWA on draw.io domains
+
+14-SEP-2020: 13.7.1
+
+- Improves Gliffy import
+
 14-SEP-2020: 13.7.0
 
 - Adds conf cloud change notifications for collab

+ 1 - 1
VERSION

@@ -1 +1 @@
-13.7.0
+13.7.2

+ 34 - 15
src/main/webapp/electron.js

@@ -29,6 +29,39 @@ let cmdQPressed = false
 let firstWinLoaded = false
 let firstWinFilePath = null
 
+//Read config file
+var queryObj = {
+	'dev': __DEV__ ? 1 : 0,
+	'test': __DEV__ ? 1 : 0,
+	'gapi': 0,
+	'db': 0,
+	'od': 0,
+	'gh': 0,
+	'gl': 0,
+	'tr': 0,
+	'browser': 0,
+	'picker': 0,
+	'mode': 'device',
+	'export': 'https://exp.draw.io/ImageExport4/export'
+};
+
+try
+{
+	if (fs.existsSync(process.cwd() + '/urlParams.json'))
+	{
+		let urlParams = JSON.parse(fs.readFileSync(process.cwd() + '/urlParams.json'));
+		
+		for (var param in urlParams)
+		{
+			queryObj[param] = urlParams[param];
+		}
+	}
+}
+catch(e)
+{
+	console.log('Error in urlParams.json file: ' + e.message);
+}
+
 function createWindow (opt = {})
 {
 	let options = Object.assign(
@@ -57,21 +90,7 @@ function createWindow (opt = {})
 	{
 		pathname: `${__dirname}/index.html`,
 		protocol: 'file:',
-		query:
-		{
-			'dev': __DEV__ ? 1 : 0,
-			'test': __DEV__ ? 1 : 0,
-			'gapi': 0,
-			'db': 0,
-			'od': 0,
-			'gh': 0,
-			'gl': 0,
-			'tr': 0,
-			'browser': 0,
-			'picker': 0,
-			'mode': 'device',
-			'export': 'https://exp.draw.io/ImageExport4/export'
-		},
+		query: queryObj,
 		slashes: true
 	})
 	

File diff ditekan karena terlalu besar
+ 527 - 519
src/main/webapp/js/app.min.js


+ 2 - 2
src/main/webapp/js/diagramly/App.js

@@ -582,7 +582,7 @@ App.main = function(callback, createUi)
 				/.*\.draw\.io$/.test(window.location.hostname) || urlParams['offline'] == '1'))
 			{
 				// Removes PWA cache on www.draw.io to force use of new domain
-				if (urlParams['offline'] == '0' || /www\.draw\.io$/.test(window.location.hostname) ||
+				if (urlParams['offline'] == '0' || /.*\.draw\.io$/.test(window.location.hostname) ||
 					(urlParams['offline'] != '1' && urlParams['dev'] == '1'))
 				{
 					navigator.serviceWorker.getRegistrations().then(function(registrations)
@@ -3301,7 +3301,7 @@ App.prototype.showSplash = function(force)
 				if (cancel && !mxClient.IS_CHROMEAPP)
 				{
 					var prev = Editor.useLocalStorage;
-					this.createFile(this.defaultFilename, null, null, null, null, null, null,
+					this.createFile(this.defaultFilename + (EditorUi.isElectronApp? '.drawio' : ''), null, null, null, null, null, null,
 						urlParams['local'] != '1');
 					Editor.useLocalStorage = prev;
 				}

+ 3 - 1
src/main/webapp/js/diagramly/Editor.js

@@ -1917,7 +1917,9 @@
 	Editor.prototype.timeout = 25000;
 	
 	/**
-	 * Zoomed mathjax output is causing problems in Safari.
+	 * Mathjax output ignores CSS transforms in Safari (lightbox and normal mode).
+	 * Check the following test case on page 2 before enabling this in production:
+	 * https://devhost.jgraph.com/git/drawio/etc/embed/sf-math-fo-clipping.html?dev=1
 	 */
 	Editor.prototype.useForeignObjectForMath = !mxClient.IS_SF;
 

+ 6 - 0
src/main/webapp/js/diagramly/EditorUi.js

@@ -4454,6 +4454,12 @@
 					{
 						this.openInNewWindow(data, mimeType, base64Encoded);
 					}
+					else if (mimeType != null && mimeType.substring(0, 9) == 'text/html')
+					{
+						var dlg = new EmbedDialog(this, data);
+						this.showDialog(dlg.container, 440, 240, true, true);
+						dlg.init();
+					}
 					else
 					{
 						var win = window.open('about:blank');

+ 27 - 39
src/main/webapp/js/diagramly/ElectronApp.js

@@ -1666,11 +1666,6 @@ mxStencilRegistry.allowEval = false;
 			var range = null;
 			var allPages = null;
 			
-			if (bounds.width * bounds.height > MAX_AREA || data.length > MAX_REQUEST_SIZE)
-			{
-				throw {message: mxResources.get('drawingTooLarge')};
-			}
-			
 			var embed = '0';
 			
 			if (format == 'pdf' && currentPage == false)
@@ -1752,48 +1747,41 @@ mxStencilRegistry.allowEval = false;
 			var w = Math.floor(bounds.width * s / graph.view.scale);
 			var h = Math.floor(bounds.height * s / graph.view.scale);
 			
-			if (data.length <= MAX_REQUEST_SIZE && w * h < MAX_AREA)
+			editorUi.hideDialog();
+			
+			if ((format == 'png' || format == 'jpg' || format == 'jpeg') && editorUi.isExportToCanvas())
 			{
-				editorUi.hideDialog();
-				
-				if ((format == 'png' || format == 'jpg' || format == 'jpeg') && editorUi.isExportToCanvas())
+				if (format == 'png')
 				{
-					if (format == 'png')
-					{
-						editorUi.exportImage(s, bg == null || bg == 'none', true,
-					   		false, false, b, true, false, null, null, dpi);
-					}
-					else 
-					{
-						editorUi.exportImage(s, false, true,
-							false, false, b, true, false, 'jpeg');
-					}
+					editorUi.exportImage(s, bg == null || bg == 'none', true,
+				   		false, false, b, true, false, null, null, dpi);
 				}
 				else 
 				{
-					var extras = {globalVars: graph.getExportVariables()};
-					
-					editorUi.saveRequest(name, format,
-						function(newTitle, base64)
-						{
-							return new mxElectronRequest('export', {
-								format: format,
-								xml: data,
-								bg: (bg != null) ? bg : mxConstants.NONE,
-								filename: (newTitle != null) ? newTitle : null,
-								w: w,
-								h: h,
-								border: b,
-								base64: (base64 || '0'),
-								extras: JSON.stringify(extras),
-								dpi: dpi > 0? dpi : null
-							}); 
-						});
+					editorUi.exportImage(s, false, true,
+						false, false, b, true, false, 'jpeg');
 				}
 			}
-			else
+			else 
 			{
-				mxUtils.alert(mxResources.get('drawingTooLarge'));
+				var extras = {globalVars: graph.getExportVariables()};
+				
+				editorUi.saveRequest(name, format,
+					function(newTitle, base64)
+					{
+						return new mxElectronRequest('export', {
+							format: format,
+							xml: data,
+							bg: (bg != null) ? bg : mxConstants.NONE,
+							filename: (newTitle != null) ? newTitle : null,
+							w: w,
+							h: h,
+							border: b,
+							base64: (base64 || '0'),
+							extras: JSON.stringify(extras),
+							dpi: dpi > 0? dpi : null
+						}); 
+					});
 			}
 		}
 	};

+ 99 - 21
src/main/webapp/js/diagramly/GraphViewer.js

@@ -86,6 +86,14 @@ GraphViewer.prototype.minHeight = 28;
  */
 GraphViewer.prototype.minWidth = 100;
 
+/**
+ * Implements viewBox to keep the contents inside the bounding box
+ * of the container. This is currently not supported in Safari (due
+ * to clipping in labels with viewBox) and all browsers that do not
+ * support foreignObjects (eg. IE11).
+ */
+GraphViewer.prototype.responsive = false;
+
 /**
  * Initializes the viewer.
  */
@@ -111,6 +119,9 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 	this.initialWidth = (container != null) ? container.style.width : null;
 	this.widthIsEmpty = (this.initialWidth != null) ? this.initialWidth == '' : true;
 	this.currentPage = parseInt(this.graphConfig.page) || 0;
+	this.responsive = ((this.graphConfig['responsive'] != null) ?
+		this.graphConfig['responsive'] : this.responsive) &&
+		!this.zoomEnabled && !mxClient.NO_FO && !mxClient.IS_SF;
 	this.pageId = this.graphConfig.pageId;
 	this.editor = null;
 
@@ -133,6 +144,45 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 				this.graph.defaultPageBackgroundColor = 'transparent';
 				this.graph.transparentBackground = false;
 				
+				if (this.responsive && this.graph.dialect == mxConstants.DIALECT_SVG)
+				{
+					var root = this.graph.view.getDrawPane().ownerSVGElement;
+					var canvas = this.graph.view.getCanvas();
+						
+					if (this.graphConfig.border != null)
+					{
+						root.style.padding = this.graphConfig.border + 'px';
+					}
+					else if (container.style.padding == '')
+					{
+						root.style.padding = '8px';
+					}
+					
+					root.style.boxSizing = 'border-box';
+					root.style.overflow = 'visible';
+					
+					this.graph.fit = function()
+					{
+						// Automatic
+					};
+					
+					this.graph.sizeDidChange = function()
+					{
+						var bounds = this.view.graphBounds;
+						var tr = this.view.translate;
+						
+						root.setAttribute('viewBox',
+							(bounds.x + tr.x - this.panDx) + ' ' +
+							(bounds.y + tr.y - this.panDy) + ' ' +
+							(bounds.width + 1) + ' ' +
+							(bounds.height + 1));
+						this.container.style.backgroundColor =
+							root.style.backgroundColor;
+
+						this.fireEvent(new mxEventObject(mxEvent.SIZE, 'bounds', bounds));
+					};
+				}
+				
 				if (this.graphConfig.move)
 				{
 					this.graph.isMoveCellsEvent = function(evt)
@@ -286,8 +336,12 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 					urlParams['nav'] = (this.graphConfig.nav != false) ? '1' : '0';
 					
 					this.editor.setGraphXml(this.xmlNode);
-					this.graph.border = (this.graphConfig.border != null) ? this.graphConfig.border : 8;
 					this.graph.view.scale = this.graphConfig.zoom || 1;
+					
+					if (!this.responsive)
+					{
+						this.graph.border = (this.graphConfig.border != null) ? this.graphConfig.border : 8;
+					}
 				}
 				finally
 				{
@@ -295,15 +349,20 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 				}
 		
 				// Adds left-button panning only if scrollbars are visible
-				this.graph.panningHandler.useLeftButtonForPanning = true;
-				this.graph.panningHandler.isForcePanningEvent = function(me)
+				if (!this.responsive)
 				{
-					return !mxEvent.isPopupTrigger(me.getEvent()) &&
-						this.graph.container.style.overflow == 'auto';
-				};
-				this.graph.panningHandler.usePopupTrigger = false;
-				this.graph.panningHandler.pinchEnabled = false;
-				this.graph.panningHandler.ignoreCell = true;
+					this.graph.panningHandler.isForcePanningEvent = function(me)
+					{
+						return !mxEvent.isPopupTrigger(me.getEvent()) &&
+							this.graph.container.style.overflow == 'auto';
+					};
+					
+					this.graph.panningHandler.useLeftButtonForPanning = true;					
+					this.graph.panningHandler.ignoreCell = true;
+					this.graph.panningHandler.usePopupTrigger = false;
+					this.graph.panningHandler.pinchEnabled = false;
+				}
+				
 				this.graph.setPanning(false);
 		
 				if (this.graphConfig.toolbar != null)
@@ -315,7 +374,11 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 					container.setAttribute('title', this.graphConfig.title);
 				}
 				
-				this.addSizeHandler();
+				if (!this.responsive)
+				{
+					this.addSizeHandler();
+				}
+				
 				this.showLayers(this.graph);
 				this.addClickHandler(this.graph);
 				this.graph.setTooltips(this.graphConfig.tooltips != false);
@@ -473,19 +536,23 @@ GraphViewer.prototype.setGraphXml = function(xmlNode)
 		this.graph.view.scale = 1;
 		this.graph.getModel().clear();
 		this.editor.setGraphXml(xmlNode);
-				
-		// Restores initial CSS state
-		if (this.widthIsEmpty)
-		{
-			this.graph.container.style.width = '';
-			this.graph.container.style.height = '';
-		}
-		else
-		{
-			this.graph.container.style.width = this.initialWidth;
+
+		if (!this.responsive)
+		{				
+			// Restores initial CSS state
+			if (this.widthIsEmpty)
+			{
+				this.graph.container.style.width = '';
+				this.graph.container.style.height = '';
+			}
+			else
+			{
+				this.graph.container.style.width = this.initialWidth;
+			}
+			
+			this.positionGraph();
 		}
 		
-		this.positionGraph();
 		this.graph.initialViewState = {
 			translate: this.graph.view.translate.clone(),
 			scale: this.graph.view.scale
@@ -1304,6 +1371,17 @@ GraphViewer.prototype.addToolbar = function()
 	{
 		enter();
 	}
+	
+	if (this.responsive && typeof ResizeObserver !== 'undefined')
+	{
+		new ResizeObserver(function()
+		{
+			if (toolbar.parentNode != null)
+			{
+				enter();
+			}
+		}).observe(container)
+	}
 };
 
 /**

+ 33 - 26
src/main/webapp/js/diagramly/Menus.js

@@ -2411,50 +2411,57 @@
 				{
 					var dlg = new CreateDialog(editorUi, title, mxUtils.bind(this, function(newTitle, mode)
 					{
-						// Mode is "download" if Create button is pressed, means use Google Drive
-						if (mode == 'download')
+						if (mode == '_blank')
 						{
-							mode = App.MODE_GOOGLE;
+							editorUi.editor.editAsNew(editorUi.getFileData(), newTitle);
 						}
-						
-						if (newTitle != null && newTitle.length > 0)
+						else
 						{
-							if (mode == App.MODE_GOOGLE)
+							// Mode is "download" if Create button is pressed, means use Google Drive
+							if (mode == 'download')
+							{
+								mode = App.MODE_GOOGLE;
+							}
+	
+							if (newTitle != null && newTitle.length > 0)
 							{
-								if (editorUi.spinner.spin(document.body, mxResources.get('saving')))
+								if (mode == App.MODE_GOOGLE)
 								{
-									// Saveas does not update the file descriptor in Google Drive
-									file.saveAs(newTitle, mxUtils.bind(this, function(resp)
+									if (editorUi.spinner.spin(document.body, mxResources.get('saving')))
 									{
-										// Replaces file descriptor in-place and saves
-										file.desc = resp;
-										
-										// Makes sure the latest XML is in the file
-										file.save(false, mxUtils.bind(this, function()
+										// Saveas does not update the file descriptor in Google Drive
+										file.saveAs(newTitle, mxUtils.bind(this, function(resp)
 										{
-											editorUi.spinner.stop();
-											file.setModified(false);
-											file.addAllSavedStatus();
+											// Replaces file descriptor in-place and saves
+											file.desc = resp;
+											
+											// Makes sure the latest XML is in the file
+											file.save(false, mxUtils.bind(this, function()
+											{
+												editorUi.spinner.stop();
+												file.setModified(false);
+												file.addAllSavedStatus();
+											}), mxUtils.bind(this, function(resp)
+											{
+												editorUi.handleError(resp);
+											}));
 										}), mxUtils.bind(this, function(resp)
 										{
 											editorUi.handleError(resp);
 										}));
-									}), mxUtils.bind(this, function(resp)
-									{
-										editorUi.handleError(resp);
-									}));
+									}
+								}
+								else
+								{
+									editorUi.createFile(newTitle, editorUi.getFileData(true), null, mode);
 								}
-							}
-							else
-							{
-								editorUi.createFile(newTitle, editorUi.getFileData(true), null, mode);
 							}
 						}
 					}), mxUtils.bind(this, function()
 					{
 						editorUi.hideDialog();
 					}), mxResources.get('makeCopy'), mxResources.get('create'), null,
-						null, null, null, true, null, null, null, null,
+						null, true, null, true, null, null, null, null,
 						editorUi.editor.fileExtensions);
 					editorUi.showDialog(dlg.container, 420, 380, true, true);
 					dlg.init();

+ 203 - 16
src/main/webapp/js/diagramly/OneDriveClient.js

@@ -783,9 +783,7 @@ OneDriveClient.prototype.insertFile = function(filename, data, success, error, a
 				folder = this.getItemURL(folderId, true);
 			}
 			
-			var url = this.baseUrl + folder + '/children/' + encodeURIComponent(filename) + '/content';
-			
-			this.writeFile(url, data, 'PUT', null, mxUtils.bind(this, function(meta)
+			var insertSuccess = mxUtils.bind(this, function(meta)
 			{
 				if (asLibrary)
 				{
@@ -795,7 +793,23 @@ OneDriveClient.prototype.insertFile = function(filename, data, success, error, a
 				{
 					success(new OneDriveFile(this.ui, data, meta));
 				}
-			}), error);
+			});
+
+			var url = this.baseUrl + folder + '/children/' + encodeURIComponent(filename) + '/content';
+			
+			//OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
+			if (data.length >= 4000000 /*4MB*/)
+			{
+				//Create empty file first then upload. TODO Can we get an upload session for non-existing files?
+				this.writeFile(url, '', 'PUT', null, mxUtils.bind(this, function(meta)
+				{
+					this.writeLargeFile(this.getItemURL(meta.id), data, insertSuccess, error);
+				}), error);
+			}
+			else
+			{
+				this.writeFile(url, data, 'PUT', null, insertSuccess, error);
+			}
 		}
 		else
 		{
@@ -869,12 +883,22 @@ OneDriveClient.prototype.saveFile = function(file, success, error, etag)
 		
 		var fn = mxUtils.bind(this, function(data)
 		{
+			var saveSuccess = mxUtils.bind(this, function(resp)
+			{
+				success(resp, savedData);
+			});
+
 			var url = this.getItemURL(file.getId());
 			
-			this.writeFile(url + '/content/', data, 'PUT', null, mxUtils.bind(this, function(resp)
+			//OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
+			if (data.length >= 4000000 /*4MB*/)
 			{
-				success(resp, savedData);
-			}), error, etag);
+				this.writeLargeFile(url, data, saveSuccess, error, etag);
+			}
+			else
+			{
+				this.writeFile(url + '/content/', data, 'PUT', null, saveSuccess, error, etag);
+			}
 		});
 		
 		if (this.ui.useCanvasForExport && /(\.png)$/i.test(file.meta.name))
@@ -898,6 +922,178 @@ OneDriveClient.prototype.saveFile = function(file, success, error, etag)
 	}
 };
 
+OneDriveClient.prototype.writeLargeFile = function(url, data, success, error, etag)
+{
+	try
+	{
+		var chunkSize = 4 * 1024 * 1024; //4MB chunk;
+		
+		if (data != null)
+		{
+			var uploadPart = mxUtils.bind(this, function(uploadUrl, index, retryCount)
+			{
+				try
+				{
+					retryCount = retryCount || 0;
+					var acceptResponse = true;
+					var timeoutThread = null;
+						
+					timeoutThread = window.setTimeout(mxUtils.bind(this, function()
+					{
+						acceptResponse = false;
+						error({code: App.ERROR_TIMEOUT});
+					}), this.ui.timeout);
+	
+					var part = data.substr(index, chunkSize);
+					var req = new mxXmlRequest(uploadUrl, part, 'PUT');
+						
+					req.setRequestHeaders = mxUtils.bind(this, function(request, params)
+					{
+						request.setRequestHeader('Content-Length', part.length);
+						request.setRequestHeader('Content-Range', 'bytes ' + index + '-' + (index + part.length - 1) + '/' + data.length);
+					});
+
+					req.send(mxUtils.bind(this, function(req)
+					{
+				    	window.clearTimeout(timeoutThread);
+				    	
+				    	if (acceptResponse)
+				    	{
+							var status = req.getStatus();
+					    	if (status >= 200 && status <= 299)
+							{
+								var nextByte = index + part.length;
+								
+								if (nextByte == data.length)
+								{
+									success(JSON.parse(req.getText()));
+								}
+								else
+								{
+									uploadPart(uploadUrl, nextByte, retryCount);
+								}
+							}
+							else if (status >= 500 && status <= 599 && retryCount < 2) //Retry on server errors
+							{
+								retryCount++;
+								uploadPart(uploadUrl, index, retryCount);
+							}
+							else
+							{
+								error(this.parseRequestText(req), req);
+							}
+				    	}
+					}), mxUtils.bind(this, function(req)
+					{
+				    	window.clearTimeout(timeoutThread);
+				    	
+				    	if (acceptResponse)
+				    	{
+							error(this.parseRequestText(req));
+				    	}
+					}));
+				}
+				catch (e)
+				{
+					error(e);
+				}
+			});
+			
+			var doExecute = mxUtils.bind(this, function(failOnAuth)
+			{
+				try
+				{
+					var acceptResponse = true;
+					var timeoutThread = null;
+					
+					try
+					{
+						timeoutThread = window.setTimeout(mxUtils.bind(this, function()
+						{
+							acceptResponse = false;
+							error({code: App.ERROR_TIMEOUT});
+						}), this.ui.timeout);
+					}
+					catch (e)
+					{
+						// Ignore window closed
+					}
+					
+					var req = new mxXmlRequest(url + '/createUploadSession', '{}', 'POST');
+					
+					req.setRequestHeaders = mxUtils.bind(this, function(request, params)
+					{
+						request.setRequestHeader('Content-Type', 'application/json');
+						request.setRequestHeader('Authorization', 'Bearer ' + this.token);
+						
+						if (etag != null)
+						{
+							request.setRequestHeader('If-Match', etag);
+						}
+					});
+					
+					req.send(mxUtils.bind(this, function(req)
+					{
+				    	window.clearTimeout(timeoutThread);
+				    	
+				    	if (acceptResponse)
+				    	{
+					    	if (req.getStatus() >= 200 && req.getStatus() <= 299)
+							{
+								var resp = JSON.parse(req.getText());
+					    		uploadPart(resp.uploadUrl, 0);
+							}
+							else if (!failOnAuth && req.getStatus() === 401)
+							{
+								this.authenticate(function()
+								{
+									doExecute(true);
+								}, error, failOnAuth);
+							}
+							else
+							{
+								error(this.parseRequestText(req), req);
+							}
+				    	}
+					}), mxUtils.bind(this, function(req)
+					{
+				    	window.clearTimeout(timeoutThread);
+				    	
+				    	if (acceptResponse)
+				    	{
+							error(this.parseRequestText(req));
+				    	}
+					}));
+				}
+				catch (e)
+				{
+					error(e);
+				}
+			});
+			
+			if (this.token == null || this.tokenExpiresOn - Date.now() < 60000) //60 sec tolerance window
+			{
+				this.authenticate(function()
+				{
+					doExecute(true);
+				}, error);
+			}
+			else
+			{
+				doExecute(false);
+			}
+		}
+		else
+		{
+			error({message: mxResources.get('unknownError')});
+		}
+	}
+	catch (e)
+	{
+		error(e);
+	}
+};
+
 /**
  * Translates this point by the given vector.
  * 
@@ -910,15 +1106,6 @@ OneDriveClient.prototype.writeFile = function(url, data, method, contentType, su
 	{
 		if (url != null && data != null)
 		{
-			//OneDrive has a limit on PUT API of 4MB, larger files needs to use the upload session method
-			if (data.length >= 4000000 /*4MB*/)
-			{
-				error({message: mxResources.get('drawingTooLarge') + ' (' +
-					this.ui.formatFileSize(data.length) + ' / 4 MB)'});
-				
-				return;
-			}
-			
 			var doExecute = mxUtils.bind(this, function(failOnAuth)
 			{
 				try

+ 2 - 0
src/main/webapp/js/mxgraph/Graph.js

@@ -1793,6 +1793,8 @@ Graph.prototype.init = function(container)
 	/**
 	 * Only foreignObject supported for now (no IE11). Safari disabled as it ignores
 	 * overflow visible on foreignObject in negative space (lightbox and viewer).
+	 * Check the following test case on page 1 before enabling this in production:
+	 * https://devhost.jgraph.com/git/drawio/etc/embed/sf-math-fo-clipping.html?dev=1
 	 */
 	Graph.prototype.isCssTransformsSupported = function()
 	{

File diff ditekan karena terlalu besar
+ 715 - 712
src/main/webapp/js/viewer-static.min.js


File diff ditekan karena terlalu besar
+ 715 - 712
src/main/webapp/js/viewer.min.js


+ 1 - 1
src/main/webapp/service-worker.js

@@ -6,7 +6,7 @@ if (workbox)
 	workbox.precaching.precacheAndRoute([
   {
     "url": "js/app.min.js",
-    "revision": "08b997f0e7d5f8c5d354a80078d2a27f"
+    "revision": "045d5e9faff926eaf7c7002c8cbfb6c9"
   },
   {
     "url": "js/extensions.min.js",