فهرست منبع

13.1.9 release

Gaudenz Alder 5 سال پیش
والد
کامیت
2fc83a764d

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+29-MAY-2020: 13.1.9
+
+- Fixes insert tables on touch devices
+- Adds Feature-Policy header
+
 29-MAY-2020: 13.1.8
 
 - Removes CSP from GAE config

+ 1 - 1
VERSION

@@ -1 +1 @@
-13.1.8
+13.1.9

+ 1 - 0
src/main/webapp/WEB-INF/appengine-web.xml

@@ -13,6 +13,7 @@
   <!-- Path patterns not supported in production -->
   <static-files>
     <include path="/**">
+	  <http-header name="Feature-Policy" value="accelerometer 'none'; ambient-light-sensor 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; usb 'none'; wake-lock 'none'; xr-spatial-tracking 'none';"/>	
       <http-header name="Referrer-Policy" value="strict-origin" />
 	  <http-header name="Access-Control-Allow-Origin" value="*"/>
 	</include>

+ 43 - 34
src/main/webapp/index.html

@@ -17,8 +17,6 @@
     <meta name="mobile-web-app-capable" content="yes">
 	<meta name="theme-color" content="#d89000">
 	<script type="text/javascript">
-		var mxIsElectron = window && window.process && window.process.type;
-
 		/**
 		 * URL Parameters and protocol description are here:
 		 *
@@ -74,6 +72,9 @@
 			}
 		}
 		
+		// Global variable for desktop
+		var mxIsElectron = window && window.process && window.process.type;
+
 		// Redirects page if required
 		if (urlParams['dev'] != '1')
 		{
@@ -105,46 +106,34 @@
 		}
 		
 		/**
-		 * Adds meta tags with application name (depends on offline URL parameter)
+		 * Adds meta tag to the page.
 		 */
-		(function()
+		function mxmeta(name, content, httpEquiv)
 		{
-			function addMeta(name, content, httpEquiv)
+			try
 			{
-				try
+				var s = document.createElement('meta');
+				
+				if (name != null) 
 				{
-					var s = document.createElement('meta');
-					
-					if (name != null) 
-					{
-						s.setAttribute('name', name);
-					}
-
-					s.setAttribute('content', content);
-					
-					if (httpEquiv != null) 
-					{
-						s.setAttribute('http-equiv', httpEquiv);
-					}
-
-				  	var t = document.getElementsByTagName('meta')[0];
-				  	t.parentNode.insertBefore(s, t);
+					s.setAttribute('name', name);
 				}
-				catch (e)
+
+				s.setAttribute('content', content);
+				
+				if (httpEquiv != null) 
 				{
-					// ignore
+					s.setAttribute('http-equiv', httpEquiv);
 				}
-			};
-			
-			var name = 'diagrams.net';
-			addMeta('apple-mobile-web-app-title', name);
-			addMeta('application-name', name);
 
-			if (mxIsElectron)
+			  	var t = document.getElementsByTagName('meta')[0];
+			  	t.parentNode.insertBefore(s, t);
+			}
+			catch (e)
 			{
-				addMeta(null, 'default-src \'self\' \'unsafe-inline\'; connect-src \'self\' https://*.draw.io https://fonts.googleapis.com https://fonts.gstatic.com; img-src * data:; media-src *; font-src *; style-src-elem \'self\' \'unsafe-inline\' https://fonts.googleapis.com', 'Content-Security-Policy');
+				// ignore
 			}
-		})();
+		};
 		
 		/**
 		 * Synchronously adds scripts to the page.
@@ -199,10 +188,30 @@
 		 */
 		function mxinclude(src)
 		{
-			var g = document.createElement('script'); g.type = 'text/javascript'; g.async = true; g.src = src;
-		    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(g, s);
+			var g = document.createElement('script');
+			g.type = 'text/javascript';
+			g.async = true;
+			g.src = src;
+			
+		    var s = document.getElementsByTagName('script')[0];
+		    s.parentNode.insertBefore(g, s);
 		};
 		
+		/**
+		 * Adds meta tags with application name (depends on offline URL parameter)
+		 */
+		(function()
+		{
+			var name = 'diagrams.net';
+			mxmeta('apple-mobile-web-app-title', name);
+			mxmeta('application-name', name);
+
+			if (mxIsElectron)
+			{
+				mxmeta(null, 'default-src \'self\' \'unsafe-inline\'; connect-src \'self\' https://*.draw.io https://fonts.googleapis.com https://fonts.gstatic.com; img-src * data:; media-src *; font-src *; style-src-elem \'self\' \'unsafe-inline\' https://fonts.googleapis.com', 'Content-Security-Policy');
+			}
+		})();
+		
 		// Checks for local storage
 		var isLocalStorage = false;
 		

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 539 - 539
src/main/webapp/js/app.min.js


+ 34 - 0
src/main/webapp/js/diagramly/Devel.js

@@ -6,6 +6,40 @@
  * is used for development mode where the JS is in separate
  * files and the mxClient.js loads other files.
  */
+if (!mxIsElectron)
+{
+	(function()
+	{
+		var csp = 'default-src \'self\'; ' +
+			'script-src %dev-script-src% \'self\' https://storage.googleapis.com ' +
+				'https://apis.google.com https://*.pusher.com https://code.jquery.com '+
+				'https://www.dropbox.com https://api.trello.com ' +
+				// Scripts in index.html (not checked here)
+				'\'sha256-JqdgAC+ydIDMtmQclZEqgbw94J4IeABIfXAxwEJGDJs=\' ' +
+				'\'sha256-4Dg3/NrB8tLC7TUSCbrtUDWD/J6bSLka01GHn+qtNZ0=\';' +
+			'connect-src \'self\' https://*.draw.io https://*.googleapis.com wss://*.pusher.com ' +
+				'https://api.github.com https://raw.githubusercontent.com https://gitlab.com ' +
+				'https://graph.microsoft.com https://*.sharepoint.com  https://*.1drv.com ' +
+				'https://*.dropboxapi.com https://api.trello.com https://*.google.com ' +
+				'https://fonts.gstatic.com https://fonts.googleapis.com;' +
+			'img-src * data:; media-src * data:; font-src *; ' +
+			'frame-src \'self\' https://*.google.com; ' +
+			'style-src %dev-style-src% \'self\' \'unsafe-inline\' https://fonts.googleapis.com;';
+		var devCsp = csp.
+			// Loads common.css from mxgraph
+			replace(/%dev-style-src%/g, 'https://devhost.jgraph.com').
+			// Adds script tags and loads shapes with eval
+			replace(/%dev-script-src%/g, 'https://devhost.jgraph.com \'unsafe-eval\'');
+		mxmeta(null, devCsp, 'Content-Security-Policy');
+
+		console.log('Development', 'Content-Security-Policy', devCsp)
+		console.log('Production', 'Content-Security-Policy',
+			csp.replace(/%dev-style-src%/g, '').
+				replace(/%dev-script-src%/g, '').
+				replace(/  /g, ' '));
+	})();
+}
+			
 mxscript(drawDevUrl + 'js/cryptojs/aes.min.js');
 mxscript(drawDevUrl + 'js/spin/spin.min.js');
 mxscript(drawDevUrl + 'js/deflate/pako.min.js');

+ 10 - 8
src/main/webapp/js/diagramly/Dialogs.js

@@ -5837,7 +5837,8 @@ var DraftDialog = function(editorUi, title, xml, editFn, discardFn, editLabel, d
 	container.style.position = 'absolute';
 	container.style.border = '1px solid lightGray';
 	container.style.marginTop = '10px';
-	container.style.width = '640px';
+	container.style.left = '40px';
+	container.style.right = '40px';
 	container.style.top = '46px';
 	container.style.bottom = '74px';
 	container.style.overflow = 'hidden';
@@ -5986,7 +5987,7 @@ var DraftDialog = function(editorUi, title, xml, editFn, discardFn, editLabel, d
 	var buttons = document.createElement('div');
 	buttons.style.position = 'absolute';
 	buttons.style.bottom = '30px';
-	buttons.style.width = '640px';
+	buttons.style.right = '40px';
 	buttons.style.textAlign = 'right';
 
 	var tb = document.createElement('div');
@@ -8590,7 +8591,9 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 		btns.appendChild(cancelBtn);
 	}
 
-	if (editorUi.getServiceName() == 'draw.io' && file != null)
+	if (editorUi.getServiceName() == 'draw.io' && file != null &&
+		// Limits button to ibraries which are known to have public URLs
+		(file.constructor == DriveLibrary || file.constructor == GitHubLibrary))
 	{
 		var btn = mxUtils.button(mxResources.get('link'), function()
 		{
@@ -8602,7 +8605,7 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 					
 					if (url != null)
 					{
-						var search = editorUi.getSearch(['create', 'title', 'mode', 'url', 'drive', 'splash', 'state']);
+						var search = editorUi.getSearch(['create', 'title', 'mode', 'url', 'drive', 'splash', 'state', 'clibs', 'ui']);
 						search += ((search.length == 0) ? '?' : '&') + 'splash=0&clibs=U' + encodeURIComponent(url);
 						var dlg = new EmbedDialog(editorUi, window.location.protocol + '//' +
 							window.location.host + '/' + search, null, null, null, null,
@@ -8629,12 +8632,11 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 				});
 			}
 		});
+
+		btn.className = 'geBtn';
+		btns.appendChild(btn);
 	}
 	
-	btn.setAttribute('id', 'btnDownload');
-	btn.className = 'geBtn';
-	btns.appendChild(btn);
-	
 	var btn = mxUtils.button(mxResources.get('export'), function()
 	{
     	var data = editorUi.createLibraryDataFromImages(images);

+ 19 - 2
src/main/webapp/js/diagramly/Editor.js

@@ -1483,13 +1483,30 @@
 	};
 
 	/**
-	 * Returns true if the given URL is known to have CORS headers.
+	 * Returns true if the given URL is known to have CORS headers and is
+	 * allowed by CSP.
 	 */
 	Editor.prototype.isCorsEnabledForUrl = function(url)
 	{
-		return mxClient.IS_CHROMEAPP || EditorUi.isElectronApp;
+		// Disables proxy for desktop and chrome app as it is served locally
+		if (mxClient.IS_CHROMEAPP || EditorUi.isElectronApp)
+		{
+			return true;
+		}
+		
+		// Blocked by CSP in production but allowed for hosted deployment
+		if (urlParams['cors'] != null && this.corsRegExp == null)
+		{
+			this.corsRegExp = new RegExp(decodeURIComponent(urlParams['cors']));
+		}
+		
+		// No access-control-allow-origin for some Iconfinder images, add this when fixed:
+		// /^https?:\/\/[^\/]*\.iconfinder.com\//.test(url) ||
+		return (this.corsRegExp != null && this.corsRegExp.test(url)) ||
+			url.substring(0, 34) === 'https://raw.githubusercontent.com/';
 	};
 	
+	
 	/**
 	 * Converts all images in the SVG output to data URIs for immediate rendering
 	 */

+ 1 - 1
src/main/webapp/js/diagramly/Pages.js

@@ -1594,7 +1594,7 @@ EditorUi.prototype.getLinkForPage = function(page)
 		
 		if (file != null && file.constructor != LocalFile && this.getServiceName() == 'draw.io')
 		{
-			var search = this.getSearch(['create', 'title', 'mode', 'url', 'drive', 'splash', 'state']);
+			var search = this.getSearch(['create', 'title', 'mode', 'url', 'drive', 'splash', 'state', 'clibs', 'ui']);
 			search += ((search.length == 0) ? '?' : '&') + 'page-id=' + page.getId();
 			
 			return window.location.protocol + '//' + window.location.host + '/' + search + '#' + file.getHash();

+ 18 - 12
src/main/webapp/js/mxgraph/Graph.js

@@ -4832,14 +4832,18 @@ TableLayout.prototype.execute = function(parent)
 						row = row.clone();
 						row.x = offset.x;
 						row.width = tw;
+						row.y = Math.round(y);
 						
-						if (!resizeLastRow)
+						if (resizeLastRow)
+						{
+							y += row.height;
+						}
+						else
 						{
-							row.y = Math.round(y);
 							y += (row.height / sh) * th;
-							row.height = Math.round(y) - row.y;
-						}	
+						}
 						
+						row.height = Math.round(y) - row.y;
 						model.setGeometry(rows[i], row);
 					}
 					
@@ -8184,30 +8188,32 @@ if (typeof mxVertexHandler != 'undefined')
 			try
 			{
 				var table = cell;
+				var rows = null;
 				var index = 0;
 				
 				if (this.isTableCell(cell))
 				{
 					var row = model.getParent(cell);
 					table = model.getParent(row);
-					index = row.getIndex(cell);
+					index = mxUtils.indexOf(model.getChildCells(row, true), cell);
 				}
 				else if (this.isTableRow(cell))
 				{
 					table = model.getParent(cell);
-					index = model.getChildCount(cell) - 1;
+					index = model.getChildCells(cell, true).length - 1;
 				}
 				else if (this.isTable(cell))
 				{
-					index = model.getChildCount(model.getChildAt(cell, 0)) - 1;	
+					rows = model.getChildCells(cell, true);
+					index = model.getChildCells(rows[0], true).length - 1;
 				}
 				
 				var width = 0;
+				rows = (rows != null) ? rows : model.getChildCells(table, true);
 				
-				for (var i = 0; i < model.getChildCount(table); i++)
+				for (var i = 0; i < rows.length; i++)
 				{
-					var row = model.getChildAt(table, i);
-					var child = model.getChildAt(row, index);
+					var child = model.getChildCells(rows[i], true)[index];
 					model.remove(child);
 					
 					var geo = this.getCellGeometry(child);
@@ -8252,8 +8258,8 @@ if (typeof mxVertexHandler != 'undefined')
 				}
 				else if (this.isTable(cell))
 				{
-					row = model.getChildAt(cell,
-						model.getChildCount(cell) - 1);
+					var rows = model.getChildCells(cell, true);
+					row = rows[rows.length - 1];
 				}
 				
 				var table = model.getParent(row);

+ 33 - 12
src/main/webapp/js/mxgraph/Menus.js

@@ -648,13 +648,7 @@ Menus.prototype.addInsertTableItem = function(menu, insertFn, parent)
 	};
 	
 	// Show table size dialog
-	var elt2 = menu.addItem('', null, mxUtils.bind(this, function(evt)
-	{
-		if (td != null && row2 != null)
-		{
-			insertFn(evt, row2.sectionRowIndex + 1, td.cellIndex + 1);
-		}
-	}), parent, null, null, null, true);
+	var elt2 = menu.addItem('', null, null, parent, null, null, null, true);
 	
 	// Quirks mode does not add cell padding if cell is empty, needs good old spacer solution
 	var quirksCellHtml = '<img src="' + mxClient.imageBasePath + '/transparent.gif' + '" width="16" height="16"/>';
@@ -732,14 +726,16 @@ Menus.prototype.addInsertTableItem = function(menu, insertFn, parent)
 	label.innerHTML = '1x1';
 	elt2.firstChild.appendChild(label);
 	
-	mxEvent.addListener(picker, 'mouseover', function(e)
+	function mouseover(e)
 	{
-		td = graph.getParentByName(mxEvent.getSource(e), 'TD');
+		td = graph.getParentByName(mxEvent.getSource(e), 'TD');		
+		var selected = false;
 		
 		if (td != null)
 		{
 			row2 = graph.getParentByName(td, 'TR');
-			extendPicker(picker, Math.min(20, row2.sectionRowIndex + 2), Math.min(20, td.cellIndex + 2));
+			var ext = (mxEvent.isMouseEvent(e)) ? 2 : 4;
+			extendPicker(picker, Math.min(20, row2.sectionRowIndex + ext), Math.min(20, td.cellIndex + ext));
 			label.innerHTML = (td.cellIndex + 1) + 'x' + (row2.sectionRowIndex + 1);
 			
 			for (var i = 0; i < picker.rows.length; i++)
@@ -750,6 +746,12 @@ Menus.prototype.addInsertTableItem = function(menu, insertFn, parent)
 				{
 					var cell = r.cells[j];
 					
+					if (i == row2.sectionRowIndex &&
+						j == td.cellIndex)
+					{
+						selected = cell.style.backgroundColor == 'blue';
+					}
+					
 					if (i <= row2.sectionRowIndex && j <= td.cellIndex)
 					{
 						cell.style.backgroundColor = 'blue';
@@ -760,10 +762,29 @@ Menus.prototype.addInsertTableItem = function(menu, insertFn, parent)
 					}
 				}
 			}
+		}
+		
+		mxEvent.consume(e);
+
+		return selected;
+	};
+	
+	mxEvent.addGestureListeners(picker, null, null, mxUtils.bind(this, function (e)
+	{
+		var selected = mouseover(e);
+		
+		if (td != null && row2 != null && selected)
+		{
+			insertFn(e, row2.sectionRowIndex + 1, td.cellIndex + 1);
 			
-			mxEvent.consume(e);
+			// Async required to block event for elements under menu
+			window.setTimeout(mxUtils.bind(this, function()
+			{
+				this.editorUi.hideCurrentMenu();
+			}), 0);
 		}
-	});
+	}));
+	mxEvent.addListener(picker, 'mouseover', mouseover);
 };
 
 /**

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 421 - 421
src/main/webapp/js/viewer.min.js


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

@@ -6,7 +6,7 @@ if (workbox)
 	workbox.precaching.precacheAndRoute([
   {
     "url": "js/app.min.js",
-    "revision": "092164cd50b7e6b4ee96f8e85b8d8684"
+    "revision": "cff100af7cbd76d60113c1c8269bcda7"
   },
   {
     "url": "js/extensions.min.js",
@@ -22,7 +22,7 @@ if (workbox)
   },
   {
     "url": "index.html",
-    "revision": "a656f54b727cb6956aeaf2ed56eb2eba"
+    "revision": "c356c0a671c0e709c0b49d17dbf99cf9"
   },
   {
     "url": "open.html",