Gaudenz Alder 7 gadi atpakaļ
vecāks
revīzija
ec04f309fe

+ 14 - 0
ChangeLog

@@ -1,3 +1,17 @@
+04-JAN-2018: 7.9.4
+
+- Adds Extras, Plugins in desktop app
+- Adds command line arguments in desktop app
+- Fixes images in SVG export preview
+- Uses mxGraph 3.8.1 beta 8
+- Adds table option in insert text dialog
+- Fixes text formatting for input selection
+
+02-JAN-2018: 7.9.3
+
+- Workaround for null variable in Jira Connect
+- Uses mxGraph 3.8.1 beta 6
+
 31-DEC-2017: 7.9.2
 
 - Improves app icons for Android

+ 1 - 1
VERSION

@@ -1 +1 @@
-7.9.2
+7.9.4

BIN
etc/build/Xml2Js.class


+ 308 - 0
etc/build/Xml2Js.java

@@ -0,0 +1,308 @@
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.Deflater;
+
+public class Xml2Js
+{
+	/**
+	 * 
+	 */
+	protected static final int IO_BUFFER_SIZE = 4 * 1024;
+
+	/**
+	 * 
+	 */
+	public static String CHARSET_FOR_URL_ENCODING = "ISO-8859-1";
+
+	/**
+	 * 
+	 * @param path
+	 * @return
+	 */
+	public List<String> walk(File base, File root) throws IOException
+	{
+		if (root == null)
+		{
+			root = base;
+		}
+
+		List<String> result = new LinkedList<String>();
+		String basePath = base.getCanonicalPath();
+		File[] list = root.listFiles();
+
+		if (list != null)
+		{
+			for (File f : list)
+			{
+				if (f.isDirectory())
+				{
+					result.addAll(walk(base, f));
+				}
+				else if (f.getCanonicalPath().toLowerCase().endsWith(".xml"))
+				{
+					String name = f.getCanonicalPath()
+							.substring(basePath.length() + 1);
+					result.add(
+							"f['" + name + "'] = '" + processFile(f) + "';\n");
+				}
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * 
+	 * @param file
+	 * @return
+	 * @throws IOException
+	 */
+	public static String processFile(File file) throws IOException
+	{
+		System.out.println("Processing " + file.getCanonicalPath() + "...");
+
+		Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
+		byte[] inBytes = encodeURIComponent(
+				readInputStream(new FileInputStream(file)),
+				CHARSET_FOR_URL_ENCODING).getBytes("UTF-8");
+		deflater.setInput(inBytes);
+
+		ByteArrayOutputStream outputStream = new ByteArrayOutputStream(
+				inBytes.length);
+		deflater.finish();
+		byte[] buffer = new byte[IO_BUFFER_SIZE];
+
+		while (!deflater.finished())
+		{
+			int count = deflater.deflate(buffer); // returns the generated code... index  
+			outputStream.write(buffer, 0, count);
+		}
+
+		outputStream.close();
+
+		return encodeToString(outputStream.toByteArray(), false);
+	}
+
+	/**
+	 * 
+	 * @param stream
+	 * @return
+	 * @throws IOException
+	 */
+	public static String readInputStream(InputStream stream) throws IOException
+	{
+		BufferedReader reader = new BufferedReader(
+				new InputStreamReader(stream));
+		StringBuffer result = new StringBuffer();
+		String tmp = reader.readLine();
+
+		while (tmp != null)
+		{
+			result.append(tmp + "\n");
+			tmp = reader.readLine();
+		}
+
+		reader.close();
+
+		return result.toString();
+	}
+
+	public static String encodeURIComponent(String s, String charset)
+	{
+		if (s == null)
+		{
+			return null;
+		}
+		else
+		{
+			String result;
+
+			try
+			{
+				result = URLEncoder.encode(s, charset).replaceAll("\\+", "%20")
+						.replaceAll("\\%21", "!").replaceAll("\\%27", "'")
+						.replaceAll("\\%28", "(").replaceAll("\\%29", ")")
+						.replaceAll("\\%7E", "~");
+			}
+			catch (UnsupportedEncodingException e)
+			{
+				// This exception should never occur
+				result = s;
+			}
+
+			return result;
+		}
+	}
+
+	private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+			.toCharArray();
+
+	private static final int[] IA = new int[256];
+	static
+	{
+		Arrays.fill(IA, -1);
+		for (int i = 0, iS = CA.length; i < iS; i++)
+			IA[CA[i]] = i;
+		IA['='] = 0;
+	}
+
+	// ****************************************************************************************
+	// *  char[] version
+	// ****************************************************************************************
+
+	/** Encodes a raw byte array into a BASE64 <code>char[]</code> representation i accordance with RFC 2045.
+	 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned.
+	 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br>
+	 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a
+	 * little faster.
+	 * @return A BASE64 encoded array. Never <code>null</code>.
+	 */
+	public final static char[] encodeToChar(byte[] sArr, boolean lineSep)
+	{
+		// Check special case
+		int sLen = sArr != null ? sArr.length : 0;
+		if (sLen == 0)
+			return new char[0];
+
+		int eLen = (sLen / 3) * 3; // Length of even 24-bits.
+		int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count
+		int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
+		char[] dArr = new char[dLen];
+
+		// Encode even 24-bits
+		for (int s = 0, d = 0, cc = 0; s < eLen;)
+		{
+			// Copy next three bytes into lower 24 bits of int, paying attension to sign.
+			int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8
+					| (sArr[s++] & 0xff);
+
+			// Encode the int into four chars
+			dArr[d++] = CA[(i >>> 18) & 0x3f];
+			dArr[d++] = CA[(i >>> 12) & 0x3f];
+			dArr[d++] = CA[(i >>> 6) & 0x3f];
+			dArr[d++] = CA[i & 0x3f];
+
+			// Add optional line separator
+			if (lineSep && ++cc == 19 && d < dLen - 2)
+			{
+				dArr[d++] = '\r';
+				dArr[d++] = '\n';
+				cc = 0;
+			}
+		}
+
+		// Pad and encode last bits if source isn't even 24 bits.
+		int left = sLen - eLen; // 0 - 2.
+		if (left > 0)
+		{
+			// Prepare the int
+			int i = ((sArr[eLen] & 0xff) << 10)
+					| (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0);
+
+			// Set last four chars
+			dArr[dLen - 4] = CA[i >> 12];
+			dArr[dLen - 3] = CA[(i >>> 6) & 0x3f];
+			dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '=';
+			dArr[dLen - 1] = '=';
+		}
+		return dArr;
+	}
+
+	// ****************************************************************************************
+	// * String version
+	// ****************************************************************************************
+
+	/** Encodes a raw byte array into a BASE64 <code>String</code> representation i accordance with RFC 2045.
+	 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned.
+	 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br>
+	 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a
+	 * little faster.
+	 * @return A BASE64 encoded array. Never <code>null</code>.
+	 */
+	public final static String encodeToString(byte[] sArr, boolean lineSep)
+	{
+		// Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower.
+		return new String(encodeToChar(sArr, lineSep));
+	}
+
+	/**
+	 * Main
+	 */
+	public static void main(String[] args)
+	{
+		if (args.length < 2)
+		{
+			System.out.println("Usage: xml2js path file");
+		}
+		else
+		{
+			try
+			{
+				Xml2Js fw = new Xml2Js();
+
+				// Generates result
+				StringBuffer result = new StringBuffer();
+				result.append("(function() {\nvar f = {};\n");
+
+				List<String> files = fw
+						.walk(new File(new File(".").getCanonicalPath()
+								+ File.separator + args[0]), null);
+				Iterator<String> it = files.iterator();
+
+				while (it.hasNext())
+				{
+					result.append(it.next());
+				}
+
+				result.append("\n");
+				result.append("var l = mxStencilRegistry.loadStencil;\n\n");
+				result.append(
+						"mxStencilRegistry.loadStencil = function(filename, fn)\n{\n");
+				result.append("  var t = f[filename.substring(9)];\n");
+				result.append("  var s = null;\n");
+				result.append("  if (t != null) {\n");
+				result.append("    t = pako.inflateRaw(atob(t));\n");
+				result.append("    s = new Array(t.length);\n");
+				result.append("    for (var i = 0; i < t.length; i++) {\n");
+				result.append("      s[i] = String.fromCharCode(t[i]);\n");
+				result.append("    };\n");
+				result.append("    s = decodeURIComponent(s.join(''));\n");
+				result.append("  }\n");
+				result.append("  if (fn != null && s != null) {\n");
+				result.append(
+						"    window.setTimeout(function(){fn(mxUtils.parseXml(s))}, 0);\n");
+				result.append("  } else {\n");
+				result.append(
+						"    return (s != null) ? mxUtils.parseXml(s) : l.apply(this, arguments)\n");
+				result.append("  }\n");
+				result.append("};\n");
+				result.append("})();\n");
+
+				FileWriter writer = new FileWriter(
+						new File(new File(".").getCanonicalPath()
+								+ File.separator + args[1]));
+				writer.write(result.toString());
+				writer.flush();
+				writer.close();
+			}
+			catch (IOException ex)
+			{
+				ex.printStackTrace();
+			}
+		}
+	}
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 43 - 41
etc/mxgraph/mxClient.js


+ 1 - 1
war/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 12/31/2017 01:30 PM
+# 01/04/2018 07:34 PM
 
 app.html
 index.html?offline=1

+ 58 - 40
war/electron.js

@@ -8,6 +8,7 @@ const dialog = electron.dialog
 const app = electron.app
 const BrowserWindow = electron.BrowserWindow
 const log = require('electron-log')
+const program = require('commander')
 
 const __DEV__ = process.env.NODE_ENV === 'development'
 		
@@ -20,9 +21,10 @@ function createWindow (opt = {})
 		width: 1600,
 		height: 1200,
 		'web-security': false,
+		allowRunningInsecureContent: __DEV__,
 		webPreferences: {
 			// preload: path.resolve('./preload.js'),
-		},
+		}
 	}, opt)
 
 	let mainWindow = new BrowserWindow(options)
@@ -32,11 +34,11 @@ function createWindow (opt = {})
 
 	let wurl = url.format(
 	{
-		pathname: `www.draw.io`,
-		protocol: 'https:',
+		pathname: __DEV__ ? 'test.draw.io' : 'www.draw.io',
+		protocol: __DEV__ ? 'http' : 'https:',
 		query:
 		{
-			'dev': __DEV__ ? 1 : 0,
+		    'https': __DEV__ ? 0 : 1,
 			'test': __DEV__ ? 1 : 0,
 			'db': 0,
 			'gapi': 0,
@@ -47,14 +49,11 @@ function createWindow (opt = {})
 			'picker': 0,
 			'mode': 'device',
 			'browser': 0,
-			'p': 'electron',
 			'appcache': 1
 		},
-		slashes: true,
+		slashes: true
 	})
 
-//`file://${__dirname}/index.html?dev=1&test=1&db=0&gapi=0&od=0&analytics=0&picker=0&mode=device&browser=0&p=electron`
-	// and load the index.html of the app.
 	mainWindow.loadURL(wurl)
 
 	// Open the DevTools.
@@ -63,16 +62,16 @@ function createWindow (opt = {})
 		mainWindow.webContents.openDevTools()
 	}
 
-	mainWindow.on('close', (event/*:WindowEvent*/) =>
+	mainWindow.on('close', (event) =>
 	{
 		const win = event.sender
 		const index = windowsRegistry.indexOf(win)
-		console.log('Window on close idx:%d', index)
+		console.log('Window on close', index)
 		const contents = win.webContents
 
 		if (contents != null)
 		{
-			contents.executeJavaScript(`global.__emt_isModified()`, true,
+			contents.executeJavaScript('global.__emt_isModified()', true,
 				isModified =>
 				{
 					console.log('__emt_isModified', isModified)
@@ -110,34 +109,34 @@ function createWindow (opt = {})
 		windowsRegistry.splice(index, 1)
 	})
 	
-	mainWindow.webContents.on('did-fail-load', function()
+	mainWindow.webContents.on('did-fail-load', function(err)
     {
         let ourl = url.format(
-					{
-						pathname: `${__dirname}/index.html`,
-						protocol: 'file:',
-						query:
-						{
-							'dev': __DEV__ ? 1 : 0,
-							'test': __DEV__ ? 1 : 0,
-							'db': 0,
-							'gapi': 0,
-							'od': 0,
-							'gh': 0,
-							'tr': 0,
-							'analytics': 0,
-							'picker': 0,
-							'mode': 'device',
-							'browser': 0,
-							'p': 'electron'
-						},
-						slashes: true,
-					})
+			{
+				pathname: `${__dirname}/index.html`,
+				protocol: 'file:',
+				query:
+				{
+					'dev': __DEV__ ? 1 : 0,
+					'drawdev': __DEV__ ? 1 : 0,
+					'test': __DEV__ ? 1 : 0,
+					'db': 0,
+					'gapi': 0,
+					'od': 0,
+					'gh': 0,
+					'tr': 0,
+					'analytics': 0,
+					'picker': 0,
+					'mode': 'device',
+					'browser': 0
+				},
+				slashes: true,
+			})
 		
 		mainWindow.loadURL(ourl)
-    });
+    })
 
-	return mainWindow.id
+	return mainWindow
 }
 
 // This method will be called when Electron has finished
@@ -158,14 +157,33 @@ app.on('ready', e =>
 		
 		if (arg.action === 'newfile')
 		{
-			event.returnValue = createWindow(arg.opt)
+			event.returnValue = createWindow(arg.opt).id
+			
 			return
 		}
 		
 		event.returnValue = 'pong'
 	})
 	
-	createWindow()
+    let argv = process.argv
+    // https://github.com/electron/electron/issues/4690#issuecomment-217435222
+    if (process.defaultApp != true)
+    {
+        argv.unshift(null)
+    }
+
+    program
+        .version(app.getVersion())
+        .usage('[options] [file]')
+        .option('-c, --create', 'creates a new empty file if no file is passed')
+        .parse(argv)
+        
+    let win = createWindow()
+    
+    win.webContents.on('did-finish-load', function()
+    {
+        win.webContents.send('args-obj', program)
+    });
 	
 	let template = [{
 	    label: app.getName(),
@@ -186,7 +204,7 @@ app.on('ready', e =>
 	        accelerator: 'CmdOrCtrl+Q',
 	        click() { app.quit(); }
 	      }]
-	}];
+	}]
 	
 	if (process.platform === 'darwin')
 	{
@@ -225,11 +243,11 @@ app.on('ready', e =>
 	        accelerator: 'CmdOrCtrl+V',
 	        selector: 'paste:'
 	      }]
-	    }];
+	    }]
 	}
 	
-	const menuBar = menu.buildFromTemplate(template);
-	menu.setApplicationMenu(menuBar);
+	const menuBar = menu.buildFromTemplate(template)
+	menu.setApplicationMenu(menuBar)
 })
 
 // Quit when all windows are closed.

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 732 - 726
war/js/app.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 312 - 310
war/js/atlas-viewer.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 827 - 821
war/js/atlas.min.js


+ 2 - 6
war/js/diagramly/App.js

@@ -52,11 +52,7 @@ App = function(editor, container, lightbox)
 	// Initial state for toolbar items is disabled
 	this.updateDocumentTitle();
 	this.updateUi();
-	
-	// Checks if canvas is supported
-	var cnv = document.createElement('canvas');
-	this.canvasSupported = !!(cnv.getContext && cnv.getContext('2d'));
-	
+
 	// Global helper method to display error messages
 	window.showOpenAlert = mxUtils.bind(this, function(message)
 	{
@@ -504,7 +500,7 @@ App.main = function(callback, createUi)
 					}
 				}
 			}
-			else if (urlParams['chrome'] != '0')
+			else if (urlParams['chrome'] != '0' && !EditorUi.isElectronApp)
 			{
 				mxscript(App.FOOTER_PLUGIN_URL);
 			}

+ 139 - 9
war/js/diagramly/Dialogs.js

@@ -2118,12 +2118,12 @@ var ParseDialog = function(editorUi, title)
 		{
 			var plantUmlServerUrl = (type == 'plantUmlPng') ? 'https://exp.draw.io/plantuml2/png/' :
 				'https://exp.draw.io/plantuml2/svg/';
-	    	var graph = editorUi.editor.graph;
-	    	
-	    	// TODO: Change server to return base64 & accept POST request
-	    	if (editorUi.spinner.spin(document.body, mxResources.get('inserting')))
-	    	{
-		    	function encode64(data) {
+		    	var graph = editorUi.editor.graph;
+		    	
+		    	// TODO: Change server to return base64 & accept POST request
+		    	if (editorUi.spinner.spin(document.body, mxResources.get('inserting')))
+		    	{
+	    			function encode64(data) {
 					r = "";
 					for (i=0; i<data.length; i+=3) {
 				 		if (i+2==data.length) {
@@ -2231,7 +2231,93 @@ var ParseDialog = function(editorUi, title)
 				};
 				 
 				xhr.send();
-	    	}
+	    		}
+		}
+		else if (type == 'table')
+		{
+			var tableCell = null;
+			var rows = null;
+			var cells = [];
+			var dx = 0;
+
+			for (var i = 0; i < lines.length; i++)
+			{
+				var tmp = mxUtils.trim(lines[i]);
+				
+				if (tmp.substring(0, 12).toLowerCase() == 'create table')
+				{
+					var name = mxUtils.trim(tmp.substring(12));
+					
+					if (name.charAt(name.length - 1) == '(')
+					{
+						name = name.substring(0, name.lastIndexOf(' '));
+					}
+					
+					tableCell = new mxCell(name, new mxGeometry(dx, 0, 160, 26),
+						'swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=26;fillColor=#e0e0e0;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;align=center;');
+					tableCell.vertex = true;
+					cells.push(tableCell);
+					
+					var size = editorUi.editor.graph.getPreferredSizeForCell(rowCell);
+		   			
+		   			if (size != null)
+		   			{
+		   				tableCell.geometry.width = size.width + 10;
+		   			}
+		   			
+		   			// For primary key lookups
+		   			rows = {};
+				}
+				else if (tableCell != null && tmp.charAt(0) == ')')
+				{
+					dx += tableCell.geometry.width + 40;
+					tableCell = null;
+				}
+				else if (tmp != '(' && tableCell != null)
+				{
+					var name = tmp.substring(0, (tmp.charAt(tmp.length - 1) == ',') ? tmp.length - 1 : tmp.length);
+					
+					if (name.substring(0, 11).toLowerCase() != 'primary key')
+					{
+						var rowCell = new mxCell(name, new mxGeometry(0, 0, 90, 26),
+							'shape=partialRectangle;top=0;left=0;right=0;bottom=0;align=left;verticalAlign=top;spacingTop=-2;fillColor=none;spacingLeft=34;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;dropTarget=0;');
+			   			rowCell.vertex = true;
+		
+						var left = sb.cloneCell(rowCell, '' /* eg. PK */);
+			   			left.connectable = false;
+			   			left.style = 'shape=partialRectangle;top=0;left=0;bottom=0;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[];portConstraint=eastwest;part=1;'
+			   			left.geometry.width = 30;
+			   			left.geometry.height = 26;
+			   			rowCell.insert(left);
+			   			
+			   			var size = editorUi.editor.graph.getPreferredSizeForCell(rowCell);
+			   			
+			   			if (size != null && tableCell.geometry.width < size.width + 10)
+			   			{
+			   				tableCell.geometry.width = size.width + 10;
+			   			}
+			   			
+			   			tableCell.insert(rowCell);
+			   			tableCell.geometry.height += 26;
+			   			
+			   			rows[rowCell.value] = rowCell;
+					}
+				}
+			}
+			
+			if (cells.length > 0)
+			{
+				var graph = editorUi.editor.graph;
+				var view = graph.view;
+				var bds = graph.getGraphBounds();
+				
+				// Computes unscaled, untranslated graph bounds
+				var x = Math.ceil(Math.max(0, bds.x / view.scale - view.translate.x) + 4 * graph.gridSize);
+				var y = Math.ceil(Math.max(0, (bds.y + bds.height) / view.scale - view.translate.y) + 4 * graph.gridSize);
+
+				graph.setSelectionCells(graph.importCells(cells, x, y));
+				graph.scrollCellToVisible(graph.getSelectionCell());
+			}
 		}
 		else if (type == 'list')
 		{
@@ -2414,6 +2500,11 @@ var ParseDialog = function(editorUi, title)
 	listOption.setAttribute('selected', 'selected');
 	mxUtils.write(listOption, mxResources.get('list'));
 	typeSelect.appendChild(listOption);
+
+	var tableOption = document.createElement('option');
+	tableOption.setAttribute('value', 'table');
+	mxUtils.write(tableOption, mxResources.get('table'));
+	typeSelect.appendChild(tableOption);
 	
 	var diagramOption = document.createElement('option');
 	diagramOption.setAttribute('value', 'diagram');
@@ -2437,6 +2528,28 @@ var ParseDialog = function(editorUi, title)
 
 	function getDefaultValue()
 	{
+		if (typeSelect.value == 'list')
+		{
+			return 'Person\n-name: String\n-birthDate: Date\n--\n+getName(): String\n+setName(String): void\n+isBirthday(): boolean';
+		}
+		else if (typeSelect.value == 'table')
+		{
+			return 'CREATE TABLE Persons\n(\nPersonID int,\nLastName varchar(255),\n' +
+	  			'FirstName varchar(255),\nAddress varchar(255),\nCity varchar(255)\n);';
+		}
+		else if (typeSelect.value == 'plantUmlPng')
+		{
+			return '@startuml\nskinparam backgroundcolor transparent\nskinparam shadowing false\nAlice -> Bob: Authentication Request\nBob --> Alice: Authentication Response\n\nAlice -> Bob: Another authentication Request\nAlice <-- Bob: another authentication Response\n@enduml';
+		}
+		else if (typeSelect.value == 'plantUmlSvg')
+		{
+			return '@startuml\nskinparam shadowing false\nAlice -> Bob: Authentication Request\nBob --> Alice: Authentication Response\n\nAlice -> Bob: Another authentication Request\nAlice <-- Bob: another authentication Response\n@enduml';
+		}
+		else if (typeSelect.value == '')
+		{
+			return ';Example:\na->b\nb->c\nc->a\n';
+		}
+		
 		return  (typeSelect.value == 'list') ?
 			'Person\n-name: String\n-birthDate: Date\n--\n+getName(): String\n+setName(String): void\n+isBirthday(): boolean' :
 			((typeSelect.value == 'plantUmlPng') ? '@startuml\nskinparam backgroundcolor transparent\nskinparam shadowing false\nAlice -> Bob: Authentication Request\nBob --> Alice: Authentication Response\n\nAlice -> Bob: Another authentication Request\nAlice <-- Bob: another authentication Response\n@enduml' :
@@ -3081,9 +3194,26 @@ var CreateDialog = function(editorUi, title, createFn, cancelFn, dlgTitle, btnLa
 	if (data != null && mimeType != null && mimeType.substring(0, 6) == 'image/')
 	{
 		nameInput.style.width = '160px';
+		var preview = null;
+		
+		// Workaround for broken images in SVG preview in Chrome
+		if (mimeType == 'image/svg+xml' && mxClient.IS_SVG)
+		{
+			preview = document.createElement('div');
+			preview.innerHTML = mxUtils.trim(data);
+			var svg = preview.getElementsByTagName('svg')[0];
+			var w = parseInt(svg.getAttribute('width'));
+			var h = parseInt(svg.getAttribute('height'));
+			svg.setAttribute('viewBox', '0 0 ' + w + ' ' + h);
+			svg.setAttribute('width', '120px');
+			svg.setAttribute('height', '80px');
+		}
+		else
+		{
+			preview = document.createElement('img');
+			preview.setAttribute('src', 'data:' + mimeType + ((base64Encoded) ? ';base64,': ';utf8,') + data);
+		}
 		
-		var preview = document.createElement('img');
-		preview.setAttribute('src', 'data:' + mimeType + ((base64Encoded) ? ';base64,': ';utf8,') + data );
 		preview.style.position = 'absolute';
 		preview.style.top = '70px';
 		preview.style.right = '100px';

+ 27 - 7
war/js/diagramly/EditorUi.js

@@ -115,6 +115,17 @@
 		EditorUi.prototype.useCanvasForExport = false;
 		EditorUi.prototype.jpgSupported = false;
 		
+		// Checks if canvas is supported
+		try
+		{
+			var cnv = document.createElement('canvas');
+			EditorUi.prototype.canvasSupported = !!(cnv.getContext && cnv.getContext('2d'));
+		}
+		catch (e)
+		{
+			// ignore
+		}
+		
 		try
 		{
 			var canvas = document.createElement('canvas');
@@ -2217,7 +2228,7 @@
 	/**
 	 * EditorUi Overrides
 	 */
-    if (urlParams['offline'] == '1')
+    if (urlParams['offline'] == '1' || EditorUi.isElectronApp)
     {
 		EditorUi.prototype.footerHeight = 4;
     }
@@ -2836,7 +2847,7 @@
 	 */
 	EditorUi.prototype.openInNewWindow = function(data, mimeType, base64Encoded)
 	{
-		// In Google Chrome 60 the code from below produces a blank window 
+		// In Google Chrome 60 the code from below produces a blank window
 		if (mxClient.IS_GC || mxClient.IS_EDGE || document.documentMode == 11 || document.documentMode == 10)
 		{
 			var win = window.open('about:blank');
@@ -2847,10 +2858,19 @@
 			}
 			else
 			{
-				win.document.write('<html><img src="data:' +
-					mimeType + ((base64Encoded) ? ';base64,' +
-					data : ';charset=utf8,' + encodeURIComponent(data)) +
-					'"/></html>');
+				// Workaround for broken images in SVG output in Chrome
+				if (mimeType == 'image/svg+xml')
+				{
+					win.document.write('<html>' + data + '</html>');
+				}
+				else
+				{
+					win.document.write('<html><img src="data:' +
+						mimeType + ((base64Encoded) ? ';base64,' +
+						data : ';charset=utf8,' + encodeURIComponent(data)) +
+						'"/></html>');
+				}
+				
 				win.document.close();
 			}
 		}
@@ -5649,7 +5669,7 @@
 					'verticalAlign=top;aspect=fixed;imageAspect=0;image=' + data + ';')];
 			}
 		}
-		else if (/(\.*<graphml )/.test(data)) 
+		else if (/(\.*<graphml )/.test(data) && typeof window.mxGraphMlCodec !== 'undefined') 
         {
             new mxGraphMlCodec().decode(data, mxUtils.bind(this, function(xml)
             {

+ 115 - 30
war/js/diagramly/ElectronApp.js

@@ -106,6 +106,14 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 			}
 			
 			this.addMenuItems(menu, ['autosave', '-', 'createShape', 'editDiagram', '-'], parent);
+			
+			var item = this.addMenuItem(menu, 'plugins', parent);
+			
+			if (!editorUi.isOffline())
+			{
+				this.addLinkToItem(item, 'https://desk.draw.io/support/solutions/articles/16000056430');
+			}
+			
 			var item = this.addMenuItem(menu, 'tags', parent);
 			
 			if (!editorUi.isOffline())
@@ -346,6 +354,79 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 		});
 	}
 
+	App.prototype.load = function()
+	{
+		const {ipcRenderer} = require('electron');
+		
+		ipcRenderer.on('args-obj', (event, argsObj) =>
+		{
+			this.loadArgs(argsObj)
+		})
+	}
+	
+	App.prototype.loadArgs = function(argsObj)
+	{
+		var paths = argsObj.args;
+		
+		// If a file is passed 
+		if (paths !== undefined && paths[0] != null)
+		{
+			var path = paths[0];
+			
+			var success = mxUtils.bind(this, function(fileEntry, data)
+			{
+				var file = new LocalFile(this, data, '');
+				file.fileObject = fileEntry;
+				this.fileLoaded(file);
+				
+				this.start();
+			});
+			
+			var error = mxUtils.bind(this, function(e)
+			{
+				if (e.code === 'ENOENT')
+				{
+					var title = path.replace(/^.*[\\\/]/, '');
+					var data = this.emptyDiagramXml;
+					var file = new LocalFile(this, data, title, null);
+					
+					file.fileObject = new Object();
+					file.fileObject.path = path;
+					file.fileObject.name = title;
+					file.fileObject.type = 'utf-8';
+					this.fileCreated(file, null, null, null);					
+					this.saveFile();
+					
+					this.start();
+				}
+				else
+				{
+					this.start();
+					this.handleError(e);
+				}
+				
+			});
+			
+			// Tries to open the file
+			this.readGraphFile(success, error, path);
+		}
+		// If no file is passed, but there is the "create-if-not-exists" flag
+		else if (argsObj.create != null)
+		{
+			var title = 'Untitled document';
+			var data = this.emptyDiagramXml;
+			var file = new LocalFile(this, data, title, null);
+			this.fileCreated(file, null, null, null);
+			
+			this.start();
+		}
+		// If no args are passed 
+		else
+		{
+			this.start();
+		}		
+	}
+
 	// Uses local picker
 	App.prototype.pickFile = function()
 	{
@@ -405,37 +486,41 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 	           
         if (paths !== undefined && paths[0] != null)
         {
-        	var fs = require('fs');
-        	var path = paths[0];
-        	var index = path.lastIndexOf('.png');
-        	var isPng = index > -1 && index == path.length - 4;
-        	var encoding = isPng ? 'base64' : 'utf-8'
-
-        	fs.readFile(path, encoding, mxUtils.bind(this, function (e, data)
-        	{
-        		if (e)
-        		{
-        			this.handleError(e);
-        		}
-        		else
-        		{
-        			if (isPng)
-        			{
-        				// Detecting png by extension. Would need https://github.com/mscdex/mmmagic
-        				// to do it by inspection
-        				data = this.extractGraphModelFromPng(data, true);
-        			}
-
-        			var fileEntry = new Object();
-        			fileEntry.path = path;
-        			fileEntry.name = path.replace(/^.*[\\\/]/, '');
-        			fileEntry.type = encoding;
-        			fn(fileEntry, data);
-        		}
-        	}));
+			this.readGraphFile(fn, this.handleError.bind(this), paths[0]);
         }
 	};
 
+	App.prototype.readGraphFile = function(fn, fnErr, path)
+	{
+		var fs = require('fs');
+		var index = path.lastIndexOf('.png');
+		var isPng = index > -1 && index == path.length - 4;
+		var encoding = isPng ? 'base64' : 'utf-8'
+
+		fs.readFile(path, encoding, mxUtils.bind(this, function (e, data)
+		{
+			if (e)
+			{
+				fnErr(e);
+			}
+			else
+			{
+				if (isPng)
+				{
+					// Detecting png by extension. Would need https://github.com/mscdex/mmmagic
+					// to do it by inspection
+					data = this.extractGraphModelFromPng(data, true);
+				}
+
+				var fileEntry = new Object();
+				fileEntry.path = path;
+				fileEntry.name = path.replace(/^.*[\\\/]/, '');
+				fileEntry.type = encoding;
+				fn(fileEntry, data);
+			}
+		}));
+	};
+
 	// Disables temp files in Electron
 	var LocalFileCtor = LocalFile;
 	
@@ -624,7 +709,7 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 				}), mxUtils.bind(this, function(resp)
 				{
 					this.editor.setStatus('');
-					this.handleError(resp, (resp != null) ? mxResources.get('errorSavingFile') : null);
+					this.handleError(resp, mxResources.get('errorSavingFile'));
 				}));
 			}
 			else
@@ -636,7 +721,7 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 				}), mxUtils.bind(this, function(resp)
 				{
 					this.editor.setStatus('');
-					this.handleError(resp, (resp != null) ? mxResources.get('errorSavingFile') : null);
+					this.handleError(resp, mxResources.get('errorSavingFile'));
 				}));
 			}
 		}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 116 - 116
war/js/embed-static.min.js


+ 16 - 4
war/js/mxgraph/Format.js

@@ -656,12 +656,18 @@ BaseFormatPanel.prototype.installInputHandler = function(input, key, defaultValu
 		// Text size via arrow button limits to 16 in IE11. Why?
 		mxEvent.addListener(input, 'mousedown', function()
 		{
-			selState = graph.cellEditor.saveSelection();
+			if (document.activeElement == graph.cellEditor.textarea)
+			{
+				selState = graph.cellEditor.saveSelection();
+			}
 		});
 		
 		mxEvent.addListener(input, 'touchstart', function()
 		{
-			selState = graph.cellEditor.saveSelection();
+			if (document.activeElement == graph.cellEditor.textarea)
+			{
+				selState = graph.cellEditor.saveSelection();
+			}
 		});
 	}
 	
@@ -2990,12 +2996,18 @@ TextFormatPanel.prototype.addFont = function(container)
 			// Text size via arrow button limits to 16 in IE11. Why?
 			mxEvent.addListener(input, 'mousedown', function()
 			{
-				selState = graph.cellEditor.saveSelection();
+				if (document.activeElement == graph.cellEditor.textarea)
+				{
+					selState = graph.cellEditor.saveSelection();
+				}
 			});
 			
 			mxEvent.addListener(input, 'touchstart', function()
 			{
-				selState = graph.cellEditor.saveSelection();
+				if (document.activeElement == graph.cellEditor.textarea)
+				{
+					selState = graph.cellEditor.saveSelection();
+				}
 			});
 			
 			input.value = '120 %';

+ 8 - 5
war/js/mxgraph/Graph.js

@@ -4117,13 +4117,16 @@ if (typeof mxVertexHandler != 'undefined')
 		mxConstants.HIGHLIGHT_OPACITY = 30;
 		mxConstants.HIGHLIGHT_SIZE = 8;
 		
-		//Enables snapping to off-grid terminals for edge waypoints
+		// Enables snapping to off-grid terminals for edge waypoints
 		mxEdgeHandler.prototype.snapToTerminals = true;
 	
-		//Enables guides
+		// Enables guides
 		mxGraphHandler.prototype.guidesEnabled = true;
 	
-		//Alt-move disables guides
+		// Enables fading of rubberband
+		mxRubberband.prototype.fadeOut = true;
+		
+		// Alt-move disables guides
 		mxGuide.prototype.isEnabledForEvent = function(evt)
 		{
 			return !mxEvent.isAltDown(evt);
@@ -7719,7 +7722,7 @@ if (typeof mxVertexHandler != 'undefined')
 			}
 		};
 	
-		var edgeHandlerReset = 	mxEdgeHandler.prototype.reset;
+		var edgeHandlerReset = mxEdgeHandler.prototype.reset;
 		mxEdgeHandler.prototype.reset = function()
 		{
 			edgeHandlerReset.apply(this, arguments);
@@ -7730,7 +7733,7 @@ if (typeof mxVertexHandler != 'undefined')
 			}
 		};
 		
-		var edgeHandlerDestroy = 	mxEdgeHandler.prototype.destroy;
+		var edgeHandlerDestroy = mxEdgeHandler.prototype.destroy;
 		mxEdgeHandler.prototype.destroy = function()
 		{
 			edgeHandlerDestroy.apply(this, arguments);

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 116 - 116
war/js/reader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 312 - 310
war/js/viewer.min.js


+ 2 - 2
war/package.json

@@ -23,8 +23,8 @@
   },
   "homepage": "https://github.com/jgraph/draw.io",
   "dependencies": {
-    "electron-log": "^2.2.7",
-    "electron-updater": "^2.8.7"
+    "commander": "^2.12.2",
+    "electron-log": "^2.2.7"
   },
   "devDependencies": {
     "electron": "^1.7.5"