From fe96eef206b15b88f6bd8d6364b3980ede970472 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 10 Mar 2015 20:14:36 +0400 Subject: [PATCH 01/13] fix require for paths ending with .js in the worker --- lib/ace/worker/worker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index 928000dd..7a047584 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -69,7 +69,8 @@ window.require = function(parentId, id) { if (!window.require.tlns) return console.log("unable to load " + id); chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; - var path = chunks.join("/") + ".js"; + var path = chunks.join("/"); + if (path.slice(-3) != ".js") path += ".js"; window.require.id = id; importScripts(path); From af5c7a9c3b44da1a64517bd8d5e4a07df32d20ba Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 22 May 2015 02:34:30 +0400 Subject: [PATCH 02/13] improve require support in worker --- lib/ace/worker/worker.js | 83 +++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index 7a047584..28fc0fe2 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -1,8 +1,9 @@ "no use strict"; ;(function(window) { -if (typeof window.window != "undefined" && window.document) { +if (typeof window.window != "undefined" && window.document) + return; +if (window.require && window.define) return; -} window.console = function() { var msgs = Array.prototype.slice.call(arguments, 0); @@ -19,6 +20,7 @@ window.ace = window; window.onerror = function(message, file, line, col, err) { postMessage({type: "error", data: { message: message, + data: err.data, file: file, line: line, col: col, @@ -37,7 +39,7 @@ window.normalizeModule = function(parentId, moduleName) { var base = parentId.split("/").slice(0, -1).join("/"); moduleName = (base ? base + "/" : "") + moduleName; - while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + while (moduleName.indexOf(".") !== -1 && previous != moduleName) { var previous = moduleName; moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); } @@ -46,7 +48,7 @@ window.normalizeModule = function(parentId, moduleName) { return moduleName; }; -window.require = function(parentId, id) { +window.require = function require(parentId, id) { if (!id) { id = parentId; parentId = null; @@ -64,18 +66,36 @@ window.require = function(parentId, id) { } return module.exports; } - - var chunks = id.split("/"); + if (!window.require.tlns) return console.log("unable to load " + id); - chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; - var path = chunks.join("/"); + + var path = resolveModuleId(id, window.require.tlns); if (path.slice(-3) != ".js") path += ".js"; window.require.id = id; + window.require.modules[id] = {}; // prevent infinite loop on broken modules importScripts(path); return window.require(parentId, id); }; +function resolveModuleId(id, paths) { + var testPath = id, tail = ""; + while (testPath) { + var alias = paths[testPath]; + if (typeof alias == "string") { + return alias + tail; + } else if (alias) { + return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name); + } else if (alias === false) { + return ""; + } + var i = testPath.lastIndexOf("/"); + if (i === -1) break; + tail = testPath.substr(i) + tail; + testPath = testPath.slice(0, i); + } + return id; +} window.require.modules = {}; window.require.tlns = {}; @@ -101,9 +121,9 @@ window.define = function(id, deps, factory) { } if (!deps.length) - // If there is no dependencies, we inject 'require', 'exports' and - // 'module' as dependencies, to provide CommonJS compatibility. - deps = ['require', 'exports', 'module']; + // If there is no dependencies, we inject "require", "exports" and + // "module" as dependencies, to provide CommonJS compatibility. + deps = ["require", "exports", "module"]; var req = function(childId) { return window.require(id, childId); @@ -114,16 +134,16 @@ window.define = function(id, deps, factory) { factory: function() { var module = this; var returnExports = factory.apply(this, deps.map(function(dep) { - switch(dep) { - // Because 'require', 'exports' and 'module' aren't actual - // dependencies, we must handle them seperately. - case 'require': return req; - case 'exports': return module.exports; - case 'module': return module; - // But for all other dependencies, we can just go ahead and - // require them. - default: return req(dep); - } + switch (dep) { + // Because "require", "exports" and "module" aren't actual + // dependencies, we must handle them seperately. + case "require": return req; + case "exports": return module.exports; + case "module": return module; + // But for all other dependencies, we can just go ahead and + // require them. + default: return req(dep); + } })); if (returnExports) module.exports = returnExports; @@ -132,9 +152,10 @@ window.define = function(id, deps, factory) { }; }; window.define.amd = {}; - +require.tlns = {}; window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { - require.tlns = topLevelNamespaces; + for (var i in topLevelNamespaces) + require.tlns[i] = topLevelNamespaces[i]; }; window.initSender = function initSender() { @@ -174,21 +195,23 @@ var sender = window.sender = null; window.onmessage = function(e) { var msg = e.data; - if (msg.command) { + if (msg.event && sender) { + sender._signal(msg.event, msg.data); + } + else if (msg.command) { if (main[msg.command]) main[msg.command].apply(main, msg.args); + else if (window[msg.command]) + window[msg.command].apply(window, msg.args); else throw new Error("Unknown command:" + msg.command); } - else if (msg.init) { - initBaseUrls(msg.tlns); + else if (msg.init) { + window.initBaseUrls(msg.tlns); require("ace/lib/es5-shim"); - sender = window.sender = initSender(); + sender = window.sender = window.initSender(); var clazz = require(msg.module)[msg.classname]; main = window.main = new clazz(sender); - } - else if (msg.event && sender) { - sender._signal(msg.event, msg.data); } }; })(this); \ No newline at end of file From a799a4086f1e9e9912c110e9c329b4101a4047af Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 25 Apr 2015 03:02:08 +0400 Subject: [PATCH 03/13] fix quote pairing for "\n" --- lib/ace/mode/behaviour/behaviour_test.js | 10 ++++++++++ lib/ace/mode/behaviour/cstyle.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js index 9dc27bf8..245edf99 100644 --- a/lib/ace/mode/behaviour/behaviour_test.js +++ b/lib/ace/mode/behaviour/behaviour_test.js @@ -144,6 +144,16 @@ module.exports = { exec("selectleft", 1); exec("insertstring", 1, '"'); assert.equal(editor.getValue(), '("foo")'); + + editor.setValue("", 1); + exec("selectleft", 1); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), '""'); + exec("insertstring", 1, '\\'); + exec("insertstring", 1, 'n'); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), '"\\n"'); + }, "test: xml": function() { editor = new Editor(new MockRenderer()); diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index a1dce91e..dd1b0d14 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -269,8 +269,8 @@ var CstyleBehaviour = function() { if (leftChar == "\\" && token && /escape/.test(token.type)) return null; - var stringBefore = token && /string/.test(token.type); - var stringAfter = !rightToken || /string/.test(rightToken.type); + var stringBefore = token && /string|escape/.test(token.type); + var stringAfter = !rightToken || /string|escape/.test(rightToken.type); var pair; if (rightChar == quote) { From 2e2d9bcdc9fa97b7b30e51dd0b864911c33e115c Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 26 Apr 2015 21:27:25 +0400 Subject: [PATCH 04/13] add more php extensions --- lib/ace/ext/modelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 7a5a1e9c..6bc79c8b 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -122,7 +122,7 @@ var supportedModes = { Pascal: ["pas|p"], Perl: ["pl|pm"], pgSQL: ["pgsql"], - PHP: ["php|phtml"], + PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"], Powershell: ["ps1"], Praat: ["praat|praatscript|psc|proc"], Prolog: ["plg|prolog"], From 5705a7c2c1090605877b8fdf7e9a7a9ee782d257 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 30 Apr 2015 03:55:19 +0400 Subject: [PATCH 05/13] fix toggle comments in handlebars mode --- lib/ace/mode/handlebars.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ace/mode/handlebars.js b/lib/ace/mode/handlebars.js index 3f2e7179..164ad43f 100644 --- a/lib/ace/mode/handlebars.js +++ b/lib/ace/mode/handlebars.js @@ -13,7 +13,6 @@ var Mode = function() { HtmlMode.call(this); this.HighlightRules = HandlebarsHighlightRules; this.$behaviour = new HtmlBehaviour(); - this.foldingRules = new HtmlFoldMode(); }; @@ -21,7 +20,7 @@ var Mode = function() { oop.inherits(Mode, HtmlMode); (function() { - this.blockComment = {start: "{!--", end: "--}"}; + this.blockComment = {start: "{{!--", end: "--}}"}; this.$id = "ace/mode/handlebars"; }).call(Mode.prototype); From dc7643db8df6611de25b5ce37468ee233fee5ff2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 22 May 2015 21:57:13 +0400 Subject: [PATCH 06/13] better invisible tabs (fixes #2109) --- lib/ace/layer/text.js | 7 +++---- lib/ace/layer/text_test.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index a105768d..01afb9f3 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -52,7 +52,7 @@ var Text = function(parentEl) { this.EOL_CHAR_LF = "\xAC"; this.EOL_CHAR_CRLF = "\xa4"; this.EOL_CHAR = this.EOL_CHAR_LF; - this.TAB_CHAR = "\u2192"; //"\u21E5"; + this.TAB_CHAR = "\u2014"; //"\u21E5"; this.SPACE_CHAR = "\xB7"; this.$padding = 0; @@ -128,8 +128,7 @@ var Text = function(parentEl) { for (var i = 1; i < tabSize + 1; i++) { if (this.showInvisibles) { tabStr.push("" - + this.TAB_CHAR - + lang.stringRepeat(" ", i - 1) + + lang.stringRepeat(this.TAB_CHAR, i) + ""); } else { tabStr.push(lang.stringRepeat(" ", i)); @@ -145,7 +144,7 @@ var Text = function(parentEl) { spaceClass = " ace_invisible_space"; tabClass = " ace_invisible_tab"; var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); - var tabContent = this.TAB_CHAR + lang.stringRepeat(" ", this.tabSize - 1); + var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); } else{ var spaceContent = lang.stringRepeat(" ", this.tabSize); var tabContent = spaceContent; diff --git a/lib/ace/layer/text_test.js b/lib/ace/layer/text_test.js index e3403ca4..3946ec66 100644 --- a/lib/ace/layer/text_test.js +++ b/lib/ace/layer/text_test.js @@ -91,7 +91,7 @@ module.exports = { var EOL = "" + textLayer.EOL_CHAR + ""; var SPACE = function(i) {return Array(i+1).join(" ")} var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)} - var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)} + var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR)} function testRender(results) { for (var i = results.length; i--; ) { var stringBuilder = []; From 386c508042e80aeab4fb388816babee9f74466ce Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 22 May 2015 22:14:15 +0400 Subject: [PATCH 07/13] convert paste into command --- lib/ace/commands/default_commands.js | 12 ++++++++++++ lib/ace/editor.js | 13 +++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index f1e267c1..de14df85 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -423,6 +423,12 @@ exports.commands = [{ exec: function() {}, passEvent: true, readOnly: true +}, { + name: "copy", + exec: function(editor) { + // placeholder for replay macro + }, + readOnly: true }, // commands disabled in readOnly mode @@ -439,6 +445,12 @@ exports.commands = [{ }, scrollIntoView: "cursor", multiSelectAction: "forEach" +}, { + name: "paste", + exec: function(editor, args) { + editor.$handlePaste(args); + }, + scrollIntoView: "cursor" }, { name: "removeline", bindKey: bindKey("Ctrl-D", "Command-D"), diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 22b43dd2..5da8a961 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -916,13 +916,15 @@ var Editor = function(renderer, session) { * **/ this.onPaste = function(text, event) { - // todo this should change when paste becomes a command - if (this.$readOnly) - return; - var e = {text: text, event: event}; + this.commands.exec("paste", this, e); + }; + + this.$handlePaste = function(e) { + if (typeof e == "string") + e = {text: e}; this._signal("paste", e); - text = e.text; + var text = e.text; if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { this.insert(text); } else { @@ -940,7 +942,6 @@ var Editor = function(renderer, session) { this.session.insert(range.start, lines[i]); } } - this.renderer.scrollCursorIntoView(); }; this.execCommand = function(command, args) { From 2a089863e24472836116a32973852af4a66d7f1e Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 18 May 2015 16:24:10 +0400 Subject: [PATCH 08/13] fix highlighting of line-height:1.5 in less mode --- lib/ace/mode/less_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/less_highlight_rules.js b/lib/ace/mode/less_highlight_rules.js index d39bdeae..a0162765 100644 --- a/lib/ace/mode/less_highlight_rules.js +++ b/lib/ace/mode/less_highlight_rules.js @@ -231,7 +231,7 @@ var LessHighlightRules = function() { regex: "\\.[a-z0-9-_]+" }, { token: "variable.language", - regex: ":[a-z0-9-_]+" + regex: ":[a-z_][a-z0-9-_]*" }, { token: "constant", regex: "[a-z0-9-_]+" From 446e3e1bf9fa5346100324b1e870329493bda1ef Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 31 May 2015 16:48:35 +0400 Subject: [PATCH 09/13] fix #2522 Popup position is off when gutter isn't shown --- demo/kitchen-sink/dev_util.js | 2 +- lib/ace/autocomplete.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/kitchen-sink/dev_util.js b/demo/kitchen-sink/dev_util.js index 8dab857c..f466285d 100644 --- a/demo/kitchen-sink/dev_util.js +++ b/demo/kitchen-sink/dev_util.js @@ -39,7 +39,7 @@ function warn() { s.shift(); // remove the getter s = s.join("\n"); // allow easy access to ace in console, but not in ace code - if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}/.test(s)) { + if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}|\(:\d+:\d+\)/.test(s)) { console.error("trying to access to global variable"); } } diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index d3b41b65..caef17ca 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -100,7 +100,7 @@ var Autocomplete = function() { var rect = editor.container.getBoundingClientRect(); pos.top += rect.top - renderer.layerConfig.offset; pos.left += rect.left - editor.renderer.scrollLeft; - pos.left += renderer.$gutterLayer.gutterWidth; + pos.left += renderer.gutterWidth; this.popup.show(pos, lineHeight); } else if (keepPopupPosition && !prefix) { From 1514d5f374b1b295894f5f911cb8e0ebbda0febe Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 31 May 2015 17:06:32 +0400 Subject: [PATCH 10/13] fix #2483 Exception on ctrl-alt-shift-click when $enableJumpToDef is true --- lib/ace/mouse/multi_select_handler.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/mouse/multi_select_handler.js b/lib/ace/mouse/multi_select_handler.js index 45704b39..649043fa 100644 --- a/lib/ace/mouse/multi_select_handler.js +++ b/lib/ace/mouse/multi_select_handler.js @@ -83,7 +83,7 @@ function onMouseDown(e) { var selectionMode; if (editor.$mouseHandler.$enableJumpToDef) { if (ctrl && alt || accel && alt) - selectionMode = "add"; + selectionMode = shift ? "block" : "add"; else if (alt && editor.$blockSelectEnabled) selectionMode = "block"; } else { @@ -117,7 +117,7 @@ function onMouseDown(e) { if (shift) { oldRange = null; - range = selection.ranges[0]; + range = selection.ranges[0] || range; editor.removeSelectionMarker(range); } editor.once("mouseup", function() { From 2249d06337d561508eebcf00966a011cbef061f1 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 31 May 2015 17:41:34 +0400 Subject: [PATCH 11/13] fix #2484 Hard-coded characterWidth in static_highlight.js and remove dependence on mockdom --- demo/static-highlighter/server.js | 17 +++++++++++------ lib/ace/ext/static_highlight.js | 10 +++++----- lib/ace/lib/dom.js | 8 +++++--- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/demo/static-highlighter/server.js b/demo/static-highlighter/server.js index 0878fec2..ea8361d4 100644 --- a/demo/static-highlighter/server.js +++ b/demo/static-highlighter/server.js @@ -2,15 +2,13 @@ * Simple node.js server, which generates the synax highlighted version of itself * using the Ace modes and themes on the server and serving a static web page. */ -// $' + // include ace search path and modules require("amd-loader"); -// load jsdom, which is required by Ace -require("../../lib/ace/test/mockdom"); - var http = require("http"); var fs = require("fs"); +var resolve = require("path").resolve; // load the highlighter and the desired mode and theme var highlighter = require("../../lib/ace/ext/static_highlight"); @@ -20,15 +18,22 @@ var theme = require("../../lib/ace/theme/twilight"); var port = process.env.PORT || 2222; http.createServer(function(req, res) { + var url = req.url; + var path = /[^#?\x00]*/.exec(url)[0]; + var root = resolve(__dirname + "/../../").replace(/\\/g, "/"); + path = resolve(root + "/" + path).replace(/\\/g, "/"); + if (path.indexOf(root + "/") != 0) + path = __filename; res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"}); - fs.readFile(__dirname + "/../../build/src/ace.js", "utf8", function(err, data) { + fs.readFile(path, "utf8", function(err, data) { + if (err) data = err.message; var highlighted = highlighter.render(data, new JavaScriptMode(), theme); res.end( '\n' + '\n' + - highlighted.html + + highlighted.html + '' ); }); diff --git a/lib/ace/ext/static_highlight.js b/lib/ace/ext/static_highlight.js index b2287f15..2acb3ac5 100644 --- a/lib/ace/ext/static_highlight.js +++ b/lib/ace/ext/static_highlight.js @@ -37,6 +37,10 @@ var baseStyles = require("../requirejs/text!./static.css"); var config = require("../config"); var dom = require("../lib/dom"); +var SimpleTextLayer = function() { + this.config = {}; +}; +SimpleTextLayer.prototype = TextLayer.prototype; var highlight = function(el, opts, callback) { var m = el.className.match(/lang-(\w+)/); @@ -149,12 +153,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { session.setUseWorker(false); session.setMode(mode); - var textLayer = new TextLayer(document.createElement("div")); + var textLayer = new SimpleTextLayer(); textLayer.setSession(session); - textLayer.config = { - characterWidth: 10, - lineHeight: 20 - }; session.setValue(input); diff --git a/lib/ace/lib/dom.js b/lib/ace/lib/dom.js index ef2f7caa..2cbfe23e 100644 --- a/lib/ace/lib/dom.js +++ b/lib/ace/lib/dom.js @@ -91,6 +91,11 @@ exports.toggleCssClass = function(el, name) { return add; }; +if (typeof document == "undefined") { + exports.importCssString = function() {}; + return; +} + /* * Add or remove a CSS class from the list of classes on the given node * depending on the value of include @@ -173,9 +178,6 @@ exports.getInnerHeight = function(element) { }; -if (typeof document == "undefined") - return; - if (window.pageYOffset !== undefined) { exports.getPageScrollTop = function() { return window.pageYOffset; From 3f31ca57ed5b31443e0874dd40e15f2990d552b2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 1 Jun 2015 01:06:39 +0400 Subject: [PATCH 12/13] fix typo --- static.js | 3 ++- tool/mode_creator.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/static.js b/static.js index a711715e..3b75c2b6 100755 --- a/static.js +++ b/static.js @@ -21,7 +21,7 @@ http.createServer(function(req, res) { if (req.method == "PUT") { if (!allowSave) return error(res, 404, "Saving not allowed pass --allow-save to enable"); - save(req, res, filename); + return save(req, res, filename); } fs.exists(filename, function(exists) { @@ -86,6 +86,7 @@ function save(req, res, filePath) { } res.statusCode = 200; res.end("OK"); + console.log("saved ", filePath); }); } diff --git a/tool/mode_creator.js b/tool/mode_creator.js index 7a2aea59..44aa67d0 100644 --- a/tool/mode_creator.js +++ b/tool/mode_creator.js @@ -126,8 +126,8 @@ function handleSaveResult(err, editor) { return log( "Write access to this file is disabled.\n"+ "To enable saving your changes to disk, clone the Ace repository\n"+ - "and run the included web server with the --allow-write option\n"+ - "`node static.js --allow-write` or `static.py --puttable=*`" + "and run the included web server with the --allow-save option\n"+ + "`node static.js --allow-save` or `static.py --puttable=*`" ); } editor.session.getUndoManager().markClean(); From 6cec0b28b2d8f7a41b8e16242bbb170ae5fab87d Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 1 Jun 2015 13:50:32 +0400 Subject: [PATCH 13/13] improve tmlanguage importer --- tool/lib.js | 105 +++++++++++++++++++++++++++++++++++++++++++-- tool/tmlanguage.js | 4 +- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/tool/lib.js b/tool/lib.js index 8809595c..3d57b6e0 100644 --- a/tool/lib.js +++ b/tool/lib.js @@ -14,8 +14,16 @@ exports.parsePlist = function(xmlOrJSON, callback) { }); } else { try { - xmlOrJSON = xmlOrJSON.replace(/^\s*\/\/.*/gm, ""); - json = JSON.parse(xmlOrJSON) + xmlOrJSON = xmlOrJSON.replace( + /("(?:\\.|[^"])*")|(?:,\s*)+([\]\}])|(\w+)\s*:|([\]\}]\s*[\[\{])|(\/\/.*|\/\*(?:[^\*]|\*(?=[^\/]))*?\*\/)/g, + function(_, str, extraComma, noQuote, missingComma, comment) { + if (comment) + return ""; + if (missingComma) + return missingComma[0] + "," + missingComma.slice(1); + return str || extraComma || '"' + noQuote + '":'; + }); + json = JSON.parse(xmlOrJSON); } catch(e) { json = cson.parse(xmlOrJSON); } @@ -24,10 +32,101 @@ exports.parsePlist = function(xmlOrJSON, callback) { return json; }; + exports.formatJSON = function(object, initialIndent) { - return util.inspect(object, false, 40).replace(/^/gm, initialIndent||""); + return JSON.stringify(object, null, 4).replace(/^/gm, initialIndent||""); }; +exports.formatJS = function(object, initialIndent) { + return formatJS(object, 4, initialIndent); +}; + +function formatJS(object, indent, initialIndent) { + if (typeof indent == "number") + indent = Array(indent + 1).join(" "); + + function $format(buffer, totalIndent, state, o) { + if (typeof o != "object" || !o) { + if (typeof o == "string") + buffer.push(JSON.stringify(o)); + else + buffer.push("" + o); + } + else if (Array.isArray(o)) { + buffer.push("[") + + var len = totalIndent.length + var oneLine = true; + for (var i = 0; i < o.length; i++) { + if (typeof o[i] == "string") { + len += o[i].length + 2 + } else if (!o[i]) { + len += (o[i] + "").length + } else { + oneLine = false; + break; + } + len += 2; + if (len > 60) { + oneLine = false; + break; + } + } + + for (var i = 0; i < o.length; i++) { + if (o[i] && typeof o[i] == "object") { + $format(buffer, totalIndent, state, o[i]); + if (i < o.length - 1) + buffer.push(", "); + } else { + if (oneLine) + i && buffer.push(" "); + else + buffer.push("\n", totalIndent + indent) + $format(buffer, totalIndent + indent, state, o[i]); + if (i < o.length - 1) + buffer.push(","); + } + + } + if (!oneLine && buffer[buffer.length - 1] != "}") + buffer.push("\n" + totalIndent) + buffer.push("]") + } + else { + var keys = Object.keys(o); + buffer.push("{", "\n"); + for (var i = 0; i < keys.length; i++) { + buffer.push(totalIndent + indent); + if (/^\w+$/.test(keys[i])) + buffer.push(keys[i]); + else + buffer.push(JSON.stringify(keys[i])); + buffer.push(": ") + + if (keys[i] == "regex" && typeof o[keys[i]] == "string") { + try { + var re = new RegExp(o[keys[i]]); + buffer.push("/" + re.source.replace(/\\.|\//g, function(f) { + return f.length == 1 ? "\\" + f : f; + }) + "/"); + } catch(e) { + $format(buffer, totalIndent + indent, state, o[keys[i]]); + } + } else { + $format(buffer, totalIndent + indent, state, o[keys[i]]); + } + + if (i < keys.length - 1) + buffer.push(",", "\n"); + } + buffer.push("\n", totalIndent, "}"); + } + } + var buffer = []; + $format(buffer, initialIndent || "", {}, object); + return buffer.join(""); +} exports.fillTemplate = function(template, replacements) { return template.replace(/%(.+?)%/g, function(str, m) { diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index 0e458330..b5d8b851 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -662,10 +662,10 @@ function convertTmLanguage(name, langStr) { var languageHighlightRules = lib.fillTemplate(modeHighlightTemplate, { language: languageNameSanitized, - languageTokens: lib.formatJSON(patterns, " ").trim(), + languageTokens: lib.formatJS(patterns, " ").trim(), uuid: language.uuid, name: name, - metaData: lib.formatJSON(language, " ").trim() + metaData: lib.formatJS(language, "").trim() }); if (devMode) {