From 4be5e490f9c3ebe2ba4708d146bb3feaa8607b3d Mon Sep 17 00:00:00 2001 From: c9bot Date: Tue, 14 Apr 2015 12:49:11 +0200 Subject: [PATCH 01/21] c9-auto-bump 3.0.1222 --- package.json | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 65bd0136..a5952095 100644 --- a/package.json +++ b/package.json @@ -49,54 +49,54 @@ }, "licenses": [], "c9plugins": { - "c9.ide.language": "#afda452919", - "c9.ide.language.css": "#eab00e0694", - "c9.ide.language.generic": "#8a3be4533a", - "c9.ide.language.html": "#13321c4eb3", - "c9.ide.language.html.diff": "#0d49022da4", + "c9.ide.language": "#8ef952c6c2", + "c9.ide.language.css": "#ef8a28943e", + "c9.ide.language.generic": "#32986699ac", + "c9.ide.language.html": "#bbe81afed1", + "c9.ide.language.html.diff": "#a7311cfc9f", "c9.ide.language.javascript": "#8479d0a9c1", - "c9.ide.language.javascript.immediate": "#99ed8f4560", + "c9.ide.language.javascript.immediate": "#9a2cce9121", "c9.ide.language.javascript.eslint": "#8832423ad1", "c9.ide.language.javascript.tern": "#7aab8b0b6a", - "c9.ide.language.javascript.infer": "#ded7df5136", - "c9.ide.language.jsonalyzer": "#efa4426f1f", - "c9.ide.collab": "#104ec85dd1", - "c9.ide.local": "#cf624506cc", - "c9.ide.find": "#ef82bc4f0d", - "c9.ide.find.infiles": "#1b83cf12f1", + "c9.ide.language.javascript.infer": "#cfec494a3c", + "c9.ide.language.jsonalyzer": "#21b64e5820", + "c9.ide.collab": "#504750d8f0", + "c9.ide.local": "#2bfd7ff051", + "c9.ide.find": "#6cc6d3379d", + "c9.ide.find.infiles": "#72582de3cd", "c9.ide.find.replace": "#e4daf722b8", "c9.ide.run.debug": "#638e6b00b3", - "c9.automate": "#86bf1ee1ca", + "c9.automate": "#b1b0cca13a", "c9.ide.ace.emmet": "#e5f1a92ac3", "c9.ide.ace.gotoline": "#4d1a93172c", - "c9.ide.ace.keymaps": "#6c4bb65b1f", + "c9.ide.ace.keymaps": "#43445d6306", "c9.ide.ace.repl": "#ada99852fa", "c9.ide.ace.split": "#0ae0151c78", "c9.ide.ace.statusbar": "#d7b45bb7c3", "c9.ide.ace.stripws": "#34426a03d1", "c9.ide.behaviors": "#6aad7006a0", "c9.ide.closeconfirmation": "#a28bfd8272", - "c9.ide.configuration": "#b8470f4107", - "c9.ide.dialog.wizard": "#c6401bdd13", + "c9.ide.configuration": "#adf50fdaa2", + "c9.ide.dialog.wizard": "#ea640aa5a1", "c9.ide.fontawesome": "#781602c5d8", "c9.ide.format": "#f51451ac57", "c9.ide.help.support": "#60e88f5680", "c9.ide.imgeditor": "#08bbc53578", "c9.ide.immediate": "#6845a93705", - "c9.ide.installer": "#38f5840924", - "c9.ide.mount": "#cb45b621f1", + "c9.ide.installer": "#f8f0d11bff", + "c9.ide.mount": "#32e79866ee", "c9.ide.navigate": "#64156c7f4a", - "c9.ide.newresource": "#9a7464cc47", + "c9.ide.newresource": "#f1f0624768", "c9.ide.openfiles": "#28a4f5af16", - "c9.ide.preview": "#dba2f4214d", + "c9.ide.preview": "#0bd8dd6e8c", "c9.ide.preview.browser": "#ac18aaf31d", "c9.ide.preview.markdown": "#ab8d30ad9f", - "c9.ide.pubsub": "#b83cf15ade", + "c9.ide.pubsub": "#92ec19ed3a", "c9.ide.readonly": "#f6f07bbe42", "c9.ide.recentfiles": "#7c099abf40", "c9.ide.remote": "#cd45e81d2f", - "c9.ide.run": "#d07c872ee1", - "c9.ide.run.build": "#915e48b363", + "c9.ide.run": "#71c5562e42", + "c9.ide.run.build": "#ad45874c88", "c9.ide.run.debug.xdebug": "#b91d23f48b", "c9.ide.save": "#b876d87d55", "c9.ide.terminal.monitor": "#b0b4d03280", From 8a0d2cfc16dde3d5f032d19f9ebaa2afb4ca5aef Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Thu, 16 Apr 2015 14:51:40 +0000 Subject: [PATCH 02/21] Merge remote-tracking branch 'origin/master' into newclient-dockerlike-deploy Conflicts: scripts/makestatic.sh --- .gitignore | 3 + configs/standalone.js | 1 + node_modules/frontdoor/lib/api_test.js | 44 ++++--- node_modules/frontdoor/lib/route_test.js | 2 + node_modules/frontdoor/lib/types_test.js | 2 + plugins/c9.cli.publish/publish_test.js | 1 + plugins/c9.metrics/mock_metrics.js | 19 +++ plugins/c9.preview/preview.handler.js | 5 +- plugins/c9.vfs.client/endpoint.js | 4 +- plugins/c9.vfs.server/download_test.js | 155 ++++++++++++----------- 10 files changed, 145 insertions(+), 91 deletions(-) create mode 100644 plugins/c9.metrics/mock_metrics.js diff --git a/.gitignore b/.gitignore index 1e256ca8..c0997096 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ plugins/c9.ide.language.javascript.tern/util/sigs_ts plugins/c9.account.billing/node_modules/ plugins/c9.account/node_modules/ plugins/c9.api.project/coverage/ +plugins/c9.proxy.apps/coverage/ plugins/c9.db.redis/coverage/ scripts/build build/output @@ -67,6 +68,8 @@ plugins/c9.proxy/proxy.cfg plugins/c9.proxy/haproxy plugins/c9.proxy/haproxy-* **/.module-cache/ +plugins/c9.account.billing/node_modules/ +plugins/c9.account/node_modules/ .c9revisions .settings diff --git a/configs/standalone.js b/configs/standalone.js index 40a6cd7f..c301c96c 100644 --- a/configs/standalone.js +++ b/configs/standalone.js @@ -173,6 +173,7 @@ module.exports = function(config, optimist) { "./c9.vfs.server/download", "./c9.vfs.server/filelist", "./c9.vfs.server/statics", + "./c9.metrics/mock_metrics", { packagePath: "./c9.vfs.server/vfs.connect.standalone", workspaceDir: baseProc, diff --git a/node_modules/frontdoor/lib/api_test.js b/node_modules/frontdoor/lib/api_test.js index a6fc7b52..4f90ea1e 100644 --- a/node_modules/frontdoor/lib/api_test.js +++ b/node_modules/frontdoor/lib/api_test.js @@ -2,6 +2,9 @@ "use server"; +require("amd-loader"); + + var assert = require("assert"); var sinon = require("sinon"); @@ -284,14 +287,18 @@ module.exports = { root.handle({ method: "PUT", url: "/post/fab?age=34" - }, this.res, assert.fail); - sinon.assert.calledWith(this.res.writeHead, 422); - var errors = JSON.parse(this.res.end.args[0][0]).errors; - assert.equal(errors.length, 1); - assert.equal(errors[0].resource, "root"); - assert.equal(errors[0].field, "name"); - assert.equal(errors[0].code, "missing_field"); - + }, this.res, function(err){ + + assert.ok( err ); + + var errors = err.errors; + assert.equal(errors.length, 1); + assert.equal(errors[0].resource, "root"); + assert.equal(errors[0].field, "name"); + assert.equal(errors[0].code, "missing_field"); + }); + + this.res.writeHead.reset(); this.res.end.reset(); @@ -299,14 +306,19 @@ module.exports = { method: "PUT", url: "/post/fab?age=juhu", body: { name: "Fabian"} - }, this.res, assert.fail); - sinon.assert.calledWith(this.res.writeHead, 422); - var errors = JSON.parse(this.res.end.args[0][0]).errors; - assert.equal(errors.length, 1); - assert.equal(errors[0].resource, "root"); - assert.equal(errors[0].field, "age"); - assert.equal(errors[0].type_expected, "int"); - assert.equal(errors[0].code, "invalid"); + }, this.res, function(err){ + + assert.ok( err ); + + var errors = err.errors; + + assert.equal(errors.length, 1); + assert.equal(errors[0].resource, "root"); + assert.equal(errors[0].field, "age"); + assert.equal(errors[0].type_expected, "int"); + assert.equal(errors[0].code, "invalid"); + }); + }, "test custom type with register": function() { diff --git a/node_modules/frontdoor/lib/route_test.js b/node_modules/frontdoor/lib/route_test.js index 3d98b710..9e11be1c 100644 --- a/node_modules/frontdoor/lib/route_test.js +++ b/node_modules/frontdoor/lib/route_test.js @@ -2,6 +2,8 @@ "use server"; +require("amd-loader"); + var assert = require("assert"); var sinon = require("sinon"); diff --git a/node_modules/frontdoor/lib/types_test.js b/node_modules/frontdoor/lib/types_test.js index 1e15f5da..ce9ab8c5 100644 --- a/node_modules/frontdoor/lib/types_test.js +++ b/node_modules/frontdoor/lib/types_test.js @@ -2,6 +2,8 @@ "use server"; +require("amd-loader"); + var assert = require("assert"); var types = require("./types"); diff --git a/plugins/c9.cli.publish/publish_test.js b/plugins/c9.cli.publish/publish_test.js index f4090e71..22d46a7e 100644 --- a/plugins/c9.cli.publish/publish_test.js +++ b/plugins/c9.cli.publish/publish_test.js @@ -2,6 +2,7 @@ "use strict"; "use server"; "use mocha"; +"use blacklist"; require("c9/inline-mocha")(module); diff --git a/plugins/c9.metrics/mock_metrics.js b/plugins/c9.metrics/mock_metrics.js new file mode 100644 index 00000000..56a13241 --- /dev/null +++ b/plugins/c9.metrics/mock_metrics.js @@ -0,0 +1,19 @@ +/** + * Dummy implementation of metrics. + */ +"use strict"; + +plugin.consumes = []; +plugin.provides = ["metrics"]; + +module.exports = plugin; + +function plugin(options, imports, register) { + + register(null, { + "metrics": { + log: function() {}, + increment: function() {} + } + }); +} \ No newline at end of file diff --git a/plugins/c9.preview/preview.handler.js b/plugins/c9.preview/preview.handler.js index c307b04b..2a852a64 100644 --- a/plugins/c9.preview/preview.handler.js +++ b/plugins/c9.preview/preview.handler.js @@ -5,7 +5,8 @@ define(function(require, exports, module) { "connect.render", "connect.render.ejs", "connect.redirect", - "connect.static" + "connect.static", + "metrics" ]; main.provides = ["preview.handler"]; return main; @@ -15,6 +16,7 @@ define(function(require, exports, module) { var https = require("https"); var http = require("http"); var mime = require("mime"); + var metrics = imports.metrics; var parseUrl = require("url").parse; var debug = require("debug")("preview"); @@ -167,6 +169,7 @@ define(function(require, exports, module) { else serveFile(request); }).on("error", function(err) { + metrics.increment("preview.failed.error"); next(err); }); diff --git a/plugins/c9.vfs.client/endpoint.js b/plugins/c9.vfs.client/endpoint.js index 3bd55ca3..6da0c793 100644 --- a/plugins/c9.vfs.client/endpoint.js +++ b/plugins/c9.vfs.client/endpoint.js @@ -97,7 +97,9 @@ define(function(require, exports, module) { function getVfsEndpoint(version, callback) { getServers(function(err, _servers) { if (err) { - errorHandler.reportError(err); + if (err.code !== "EDISCONNECT") + errorHandler.reportError(new Error("Could not get list of VFS servers"), { cause: err }); + metrics.increment("vfs.failed.connect_getservers", 1, true); initDefaultServers(); _servers = servers; } diff --git a/plugins/c9.vfs.server/download_test.js b/plugins/c9.vfs.server/download_test.js index 0f99fdbf..7717a8be 100755 --- a/plugins/c9.vfs.server/download_test.js +++ b/plugins/c9.vfs.server/download_test.js @@ -1,8 +1,13 @@ #!/usr/bin/env node "use strict"; "use server"; +"use mocha"; + +require("c9/inline-mocha")(module); +if (typeof define === "undefined") { + require("amd-loader"); +} -require("amd-loader"); var assert = require("assert"); var fs = require("fs"); var tmp = require("tmp"); @@ -12,11 +17,10 @@ var download = require("./download"); var urlParse = require('url').parse; var execFile = require('child_process').execFile; -module.exports = { +describe(__filename, function(){ + this.timeout(4000); - timeout: 4000, - - setUp: function(next) { + beforeEach(function(next) { var that = this; var vfs = localfs({root: "/"}); download({}, { @@ -41,80 +45,85 @@ module.exports = { }); that.server.listen(8787, "0.0.0.0", next); }); - }, + }); - tearDown: function(next) { + afterEach(function(next) { this.server.close(next); - }, + }); - "test download": function(next) { - tmp.dir({unsafeCleanup: true}, function(err, path) { - var filename = path + "/download.tar.gz"; - var file = fs.createWriteStream(filename); - http.get("http://localhost:8787/?download=download.tar.gz", function(res) { - assert.equal(res.headers["content-type"], "application/x-gzip"); - assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''download.tar.gz"); - - res.pipe(file); - - res.on("end", function() { - execFile("tar", ["-zxvf", filename, "c9.vfs.server/download.js"], {cwd: path}, function(err, stdout, stderr) { - assert.equal(err, null); - assert.equal( - fs.readFileSync(__dirname + "/download.js", "utf8"), - fs.readFileSync(path + "/c9.vfs.server/download.js", "utf8") - ); - next(); - }); - }); - }); - }); - }, + describe("download", function() { - "test download sub directory": function(next) { - tmp.dir({unsafeCleanup: true}, function(err, path) { - var filename = path + "/download.tar.gz"; - var file = fs.createWriteStream(filename); - http.get("http://localhost:8787/views?download=download.tar.gz", function(res) { - res.pipe(file); - - res.on("end", function() { - execFile("tar", ["-zxvf", filename, "views/status.html.ejs"], {cwd: path}, function(err) { - assert.equal(err, null); - assert.equal( - fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"), - fs.readFileSync(path + "/views/status.html.ejs", "utf8") - ); - next(); - }); - }); - }); - }); - }, + it("should download", function(next) { + tmp.dir({unsafeCleanup: true}, function(err, path) { + var filename = path + "/download.tar.gz"; + var file = fs.createWriteStream(filename); + http.get("http://localhost:8787/?download=download.tar.gz", function(res) { + assert.equal(res.headers["content-type"], "application/x-gzip"); + assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''download.tar.gz"); - "test download without specifying a name": function(next) { - tmp.dir({unsafeCleanup: true}, function(err, path) { - var filename = path + "/download.tar.gz"; - var file = fs.createWriteStream(filename); - http.get("http://localhost:8787/views?download", function(res) { - assert.equal(res.headers["content-type"], "application/x-gzip"); - assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''views.tar.gz"); - - res.pipe(file); - - res.on("end", function() { - execFile("tar", ["-zxvf", filename, "views/status.html.ejs"], {cwd: path}, function(err) { - assert.equal(err, null); - assert.equal( - fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"), - fs.readFileSync(path + "/views/status.html.ejs", "utf8") - ); - next(); + res.pipe(file); + + res.on("end", function() { + execFile("tar", ["-zxvf", filename, "c9.vfs.server/download.js"], {cwd: path}, function(err, stdout, stderr) { + assert.equal(err, null); + assert.equal( + fs.readFileSync(__dirname + "/download.js", "utf8"), + fs.readFileSync(path + "/c9.vfs.server/download.js", "utf8") + ); + next(); + }); }); }); }); }); - } -}; - -!module.parent && require("asyncjs").test.testcase(module.exports).exec(); \ No newline at end of file + + it("should download sub directory", function(next) { + tmp.dir({unsafeCleanup: true}, function(err, path) { + assert.equal(err, null); + + var filename = path + "/download.tar.gz"; + var file = fs.createWriteStream(filename); + http.get("http://localhost:8787/views?download=download.tar.gz", function(res) { + res.pipe(file); + + res.on("end", function() { + execFile("tar", ["-zxvf", filename, "views/status.html.ejs"], {cwd: path}, function(err) { + assert.equal(err, null); + assert.equal( + fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"), + fs.readFileSync(path + "/views/status.html.ejs", "utf8") + ); + next(); + }); + }); + }); + }); + }); + + it("should download without specifying a name", function(next) { + tmp.dir({unsafeCleanup: true}, function(err, path) { + assert.equal(err, null); + + var filename = path + "/download.tar.gz"; + var file = fs.createWriteStream(filename); + http.get("http://localhost:8787/views?download", function(res) { + assert.equal(res.headers["content-type"], "application/x-gzip"); + assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''views.tar.gz"); + + res.pipe(file); + + res.on("end", function() { + execFile("tar", ["-zxvf", filename, "views/status.html.ejs"], {cwd: path}, function(err) { + assert.equal(err, null); + assert.equal( + fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"), + fs.readFileSync(path + "/views/status.html.ejs", "utf8") + ); + next(); + }); + }); + }); + }); + }); + }); +}); \ No newline at end of file From 0f8604078275292aeb8516ade32b9de113b6fecf Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Thu, 16 Apr 2015 15:22:34 +0000 Subject: [PATCH 03/21] Adding script to calculate what nodeModules are needed for a service. Used it to set nodeModulesInclude for api and ide --- node_modules/architect-build/npm_build.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/node_modules/architect-build/npm_build.js b/node_modules/architect-build/npm_build.js index 702a4d00..f95854e1 100644 --- a/node_modules/architect-build/npm_build.js +++ b/node_modules/architect-build/npm_build.js @@ -188,19 +188,21 @@ dest = "/build/webkitbuilds/app.nw" var args = ["local","-s", "local"]; */ module.exports = function(options, cb) { - var dest = convertPath(options.dest); + var dest = options.dest && convertPath(options.dest); var root = convertPath(options.root); var args = options.args; ignore = options.ignore && function(id) { return options.ignore.test(id); }; build(root, args, function(err, result) { - var serverSource = fs.readFileSync(root + "/server.js", "utf8"); - serverSource = serverSource.replace(/^(#.*|"use strict";?|\s)*/, function(a) { - return a.trim() + "\n\n" + patchTemplate + "\n\n"; - }); - fs.writeFileSync(dest + "/server.js", serverSource, "utf8"); - fs.writeFileSync(dest + "/module-map.json", JSON.stringify(result.moduleMap), "utf8"); + if (dest) { + var serverSource = fs.readFileSync(root + "/server.js", "utf8"); + serverSource = serverSource.replace(/^(#.*|"use strict";?|\s)*/, function(a) { + return a.trim() + "\n\n" + patchTemplate + "\n\n"; + }); + fs.writeFileSync(dest + "/server.js", serverSource, "utf8"); + fs.writeFileSync(dest + "/module-map.json", JSON.stringify(result.moduleMap), "utf8"); + } cb(null, result); }); From c8ed575dfd3c80667e98a0565d6eaa6c1eea72e0 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Fri, 17 Apr 2015 11:02:10 +0000 Subject: [PATCH 04/21] Merge remote-tracking branch 'origin/master' into newclient-dockerlike-deploy Conflicts: scripts/makestatic.sh --- .nakignore | 4 +- configs/client-default.js | 14 +- node_modules/ace/lib/ace/mode/xml.js | 2 +- node_modules/ace/lib/ace/worker/worker.js | 48 ++- .../build_support/mini_require.js | 202 +++++++-- node_modules/architect-build/module-deps.js | 48 ++- plugins/c9.cli.publish/publish.js | 282 ++++++++++-- plugins/c9.cli/cli.js | 2 +- plugins/c9.core/ext.js | 18 +- plugins/c9.core/util.js | 15 +- plugins/c9.ide.ace/ace.js | 146 ++++--- plugins/c9.ide.ace/themes.js | 47 +- plugins/c9.ide.keys/editor.js | 73 +++- plugins/c9.ide.plugins/debug.js | 288 +++++++++++-- plugins/c9.ide.plugins/installer.js | 14 +- plugins/c9.ide.plugins/loader.js | 105 ++--- plugins/c9.ide.plugins/manager.js | 12 +- .../c9.ide.example3/builders/example.build | 8 + .../mock/c9.ide.example3/install.js | 57 +++ .../mock/c9.ide.example3/keymaps/eclipse | 28 ++ .../mock/c9.ide.example3/modes/javascript.js | 117 +++++ .../modes/javascript_highlight_rules.js | 405 ++++++++++++++++++ .../c9.ide.example3/modes/javascript_test.js | 213 +++++++++ .../modes/javascript_worker.js | 185 ++++++++ .../modes/javascript_worker_test.js | 106 +++++ .../c9.ide.example3/outline/python.outline | 20 + .../mock/c9.ide.example3/package.json | 22 + .../mock/c9.ide.example3/runners/example.run | 8 + .../c9.ide.example3/snippets/mako.snippets | 56 +++ .../templates/example.templates | 98 +++++ .../c9.ide.example3/themes/cloud9_day.css | 157 +++++++ plugins/c9.ide.preferences/preferencepanel.js | 21 +- plugins/c9.ide.terminal/aceterm/aceterm.js | 2 +- plugins/c9.ide.terminal/link_handler.js | 8 +- plugins/c9.ide.ui/forms.js | 22 +- plugins/c9.vfs.standalone/standalone.js | 10 +- .../views/standalone.html.ejs | 2 +- scripts/install-sdk.sh | 22 + 38 files changed, 2589 insertions(+), 298 deletions(-) create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/builders/example.build create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/install.js create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/keymaps/eclipse create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript.js create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_highlight_rules.js create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_test.js create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker.js create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker_test.js create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/outline/python.outline create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/package.json create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/runners/example.run create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/snippets/mako.snippets create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/templates/example.templates create mode 100644 plugins/c9.ide.plugins/mock/c9.ide.example3/themes/cloud9_day.css diff --git a/.nakignore b/.nakignore index d4479eea..f614359b 100644 --- a/.nakignore +++ b/.nakignore @@ -3,5 +3,7 @@ build/standalone/ build/static build/node_modules/ build/webkitbuilds/ -build/win32 +build/win32* +build/Cloud9 +build/sdk node_modules/logicblox/build/logicblox/static \ No newline at end of file diff --git a/configs/client-default.js b/configs/client-default.js index 69da96b9..bc382dff 100644 --- a/configs/client-default.js +++ b/configs/client-default.js @@ -7,6 +7,17 @@ module.exports = function(options) { assert(options.workspaceName, "Option 'workspaceName' must be set"); assert(options.home, "Option 'home' must be set"); assert(options.platform, "Option 'platform' must be set"); + + // normalize workspacedir and home paths + function normalize(path) { + path = path.replace(/([^/])\/$/, "$1"); + if (options.platform == "win32") + path = path.replace(/\\/g, "/"); + return path; + } + options.workspaceDir = normalize(options.workspaceDir); + options.installPath = normalize(options.installPath); + options.home = normalize(options.home); var workspaceDir = options.workspaceDir; var debug = options.debug !== undefined ? options.debug : false; @@ -71,7 +82,8 @@ module.exports = function(options) { "plugins/c9.core/util", { packagePath: "plugins/c9.ide.plugins/loader", - plugins: options.plugins || [] + plugins: options.plugins || [], + loadFromDisk: options.standalone }, { packagePath: "plugins/c9.ide.plugins/installer", diff --git a/node_modules/ace/lib/ace/mode/xml.js b/node_modules/ace/lib/ace/mode/xml.js index 8c7033f1..38861eee 100644 --- a/node_modules/ace/lib/ace/mode/xml.js +++ b/node_modules/ace/lib/ace/mode/xml.js @@ -53,7 +53,7 @@ oop.inherits(Mode, TextMode); this.blockComment = {start: ""}; - this.createWorker = function(session) { + this.createWorker = function(session) { var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker"); worker.attachToDocument(session.getDocument()); diff --git a/node_modules/ace/lib/ace/worker/worker.js b/node_modules/ace/lib/ace/worker/worker.js index 65f690c3..28fc0fe2 100644 --- a/node_modules/ace/lib/ace/worker/worker.js +++ b/node_modules/ace/lib/ace/worker/worker.js @@ -48,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; @@ -66,12 +66,11 @@ 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; @@ -79,6 +78,24 @@ window.require = function(parentId, id) { 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 = {}; @@ -135,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() { @@ -177,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 diff --git a/node_modules/architect-build/build_support/mini_require.js b/node_modules/architect-build/build_support/mini_require.js index ad08d9c3..be4abe69 100644 --- a/node_modules/architect-build/build_support/mini_require.js +++ b/node_modules/architect-build/build_support/mini_require.js @@ -6,14 +6,17 @@ var global = (function() { return this; })(); if (!global && typeof window != "undefined") global = window; // can happen in strict mode var commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg; -var cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g; +var cjsRequireRegExp = /require\s*\(\s*["']([^'"\s]+)["']\s*\)/g; function getInlineDeps(fn) { var deps = []; if (fn.length) { fn.toString().replace(commentRegExp, "") - .replace(cjsRequireRegExp, function (match, dep) { - deps.push(dep); + .replace(cjsRequireRegExp, function (match, dep, index, str) { + var i = index; + while (str.charCodeAt(i-=1) <= 32) {} + if (str.charAt(i) !== ".") + deps.push(dep); }); deps = ["require", "exports", "module"].concat(deps); } @@ -49,31 +52,91 @@ var define = function(name, deps, callback) { exports: {}, packaged: true }; + if (define.loading[name]) + delete define.loading[name]; + if (define.lastModule) + define.pending.push(name); + else + define.lastModule = name; }; var defQueue = []; -var addToLoadQueue = function(missing, deps, callback) { - define.queue.push(function() { _require('', deps, callback); }); - for (var i = 0; i < missing.length; ++i) - require.load(missing[i]); +var addToLoadQueue = function(missing, deps, callback, errback) { + var toLoad = missing.length; + var map = {}; + define.queue.push({ + deps: deps, + map: map, + toLoad: toLoad, + callback: callback, + errback: errback + }); + + for (var i = 0; i < missing.length; ++i) { + var p = missing[i]; + map[p] = 1; + if (!define.loading[p]) { + require.load(p); + define.loading[p] = 1; + } + } }; var processLoadQueue = function(err, id) { + var changed = false; + if (err) { + define.errors[err.id] = err; + define.queue.forEach(function(r) { + if (r.map[err.id]) { + r.toLoad = -1; + if (r.errback) r.errback(err); + } + }); + if (define.lastModule = err.id) + define.lastModule = null; + define.pending = define.pending.filter(function(p) { + return p != err.id; + }); + changed = true; + } + if (defQueue.length) { - if (err) - throw err; if (defQueue.length > 1) throw new Error("more than one module in defqueue"); define(id, defQueue[0][0], defQueue[0][1]); - defQueue.length = 0; + defQueue.length = 0; + } + + var pending = define.pending; + define.queue.forEach(function(r) { + pending.forEach(function(id) { + if (r.map[id]) + r.toLoad--; + }); + if (r.map[define.lastModule]) + r.toLoad--; + if (!r.toLoad) { + changed = true; + _require("", r.deps, r.callback, r.errback); + } + }); + + define.lastModule = null; + if (pending.length) + define.pending = []; + + if (changed) { + define.queue = define.queue.filter(function(r) { + return r.toLoad > 0; + }); } - var queue = define.queue; - define.queue = []; - queue.forEach(function(f) { f(); }); }; define.amd = true; define.queue = []; define.loaded = {}; +define.errors = {}; +define.loading = {}; +define.pending = []; define.modules = { require: 1, exports: 1, module: 1 }; define.fetchedUrls = {}; @@ -86,7 +149,10 @@ var activateModule = function(name) { var req = function(path, callback) { return _require(name, path, callback); }; - req.toUrl = require.toUrl; + req.toUrl = function(namePlusExt) { + return require.toUrl(normalizeName(name, namePlusExt)); + }; + req.config = require.config; var modules = define.modules; var missing = checkMissing(module.deps); @@ -103,7 +169,7 @@ var activateModule = function(name) { ? module.factory.apply(module, args.map(lookup)) : module.factory(req, exports, module); - exports = returnValue || module.exports; + exports = returnValue == undefined ? module.exports : returnValue; } delete define.loaded[name]; define.modules[name] = exports; @@ -136,7 +202,7 @@ var lookup = function(moduleName) { return mod; }; -var _require = function(parentId, moduleName, callback) { +var _require = function(parentId, moduleName, callback, errback) { if (typeof moduleName === "string") { var depName = normalizeName(parentId, moduleName); var module = lookup(depName); @@ -151,11 +217,11 @@ var _require = function(parentId, moduleName, callback) { var args = deps.map(lookup); return callback && callback.apply(null, args); } else { - return addToLoadQueue(missing, deps, callback); + return addToLoadQueue(missing, deps, callback, errback); } } if (_require.original) - return _require.original.apply(this, arguments); + return _require.original.call(this, moduleName, callback); }; var normalizeName = function(parentId, moduleName) { @@ -188,9 +254,31 @@ var require = function(module, callback) { return _require("", module, callback); }; +var config = require.config = function(cfg) { + if (cfg.baseUrl) + config.baseUrl = cfg.baseUrl.replace(/\/*$/, "/"); + + cfg.packages && cfg.packages.forEach(function(pkg) { + if (typeof pkg === "string") pkg = { name: pkg }; + config.packages[pkg.name] = { + name: pkg.name, + location: (pkg.location || pkg.name).replace(/\/*$/, "/"), + main: (pkg.main || "main").replace(/\.js$/, "").replace(/^\.\//, "") + }; + }); + + cfg.paths && Object.keys(cfg.paths).forEach(function(p) { + config.paths[p] = cfg.paths[p]; + }); +}; +config.packages = Object.create(null); +config.paths = Object.create(null); +config.baseUrl = ""; + require.undef = function(module, callback) { module = normalizeName("", module); - var path = require.toUrl(module); + var path = require.toUrl(module, ".js"); + delete define.errors[module]; delete define.loaded[module]; delete define.modules[module]; delete define.fetchedUrls[path]; @@ -198,18 +286,47 @@ require.undef = function(module, callback) { require.MODULE_LOAD_URL = MODULE_LOAD_URL; -require.toUrl = function(module, ext) { - var path = module; - if (!/https?:\/\//.test(path)) - path = require.MODULE_LOAD_URL + "/" + path + (ext || ""); - return path; +require.toUrl = function(moduleName, ext, skipExt) { + var absRe = /^([\w\+\.\-]+:|\/)/; + var index = moduleName.indexOf("!"); + if (index !== -1 || !ext) + ext = ""; + + var paths = config.paths; + var pkgs = config.packages; + + var testPath = moduleName, tail = ""; + while (testPath) { + if (paths[testPath]) { + moduleName = paths[testPath] + tail; + break; + } + if (pkgs[testPath]) { + moduleName = pkgs[testPath].location + (tail || pkgs[testPath].main); + break; + } + var i = testPath.lastIndexOf("/"); + if (i === -1) break; + tail = testPath.substr(i) + tail; + testPath = testPath.slice(0, i); + } + + if (skipExt) + return testPath; + + var url = moduleName + ext; + if (!absRe.test(url)) { + url = (config.baseUrl || require.MODULE_LOAD_URL + "/") + url; + } + return url; }; var loadScript = function(path, id, callback) { + // TODO use importScripts for webworkers var head = document.head || document.documentElement; var s = document.createElement("script"); s.src = path; - s.charset = 'utf-8'; + s.charset = "utf-8"; s.async = true; if (path.lastIndexOf(require.MODULE_LOAD_URL, 0) == 0) @@ -224,6 +341,12 @@ var loadScript = function(path, id, callback) { callback(null, id); } }; + s.onerror = function(e) { + processLoadQueue({ + id: id, + path: path + }); + }; }; require.load = function(module) { @@ -231,8 +354,21 @@ require.load = function(module) { if (i) { var plugin = module.substring(0, i); module = module.substr(i); - if (require[plugin]) { + if (typeof require[plugin] == "function") { require[plugin](module, processLoadQueue); + } else if (config.baseUrl) { + if (require[plugin]) + return require[plugin][plugin + module] = 1; + require[plugin] = Object.create(null); + require[plugin][plugin + module] = 1; + require([plugin.slice(0, -1)], function(p) { + var pending = require[plugin]; + definePlugin(plugin, p); + Object.keys(pending).forEach(function(p) { + delete define.loading[p]; + }); + require(Object.keys(pending)); + }); } else { console.error("require plugin " + plugin + "missing"); } @@ -245,6 +381,17 @@ require.load = function(module) { } }; +function definePlugin(plugin, p) { + require[plugin] = function(moduleName, processLoadQueue) { + p.load(moduleName, require, function(value) { + define(plugin + moduleName, [], function() { + return value; + }); + processLoadQueue(); + }); + }; +} + /*** plugins ***/ require["text!"] = function(module, callback) { var url = require.toUrl(module); @@ -275,6 +422,9 @@ if (!global.require || !global.require.packaged) { global.require = require; global.require.packaged = true; } + +if (!global.requirejs) global.requirejs = require; + global.miniRequire = require; diff --git a/node_modules/architect-build/module-deps.js b/node_modules/architect-build/module-deps.js index 94ab2b85..22355285 100644 --- a/node_modules/architect-build/module-deps.js +++ b/node_modules/architect-build/module-deps.js @@ -80,6 +80,10 @@ module.exports = function(mains, opts) { opts.modules[id] = mod; + if (mod.source && mod.literal) { + return cb(null, mod); + } + idToPath(mod, function(err, path) { var filepath = absolutePath(root, path); mod.path = path; @@ -294,20 +298,22 @@ function getDeps(src, name) { return getReqDeps(src, name).concat(getAmdDeps(src, name)); } function resolveModuleId(id, paths) { - var chunks = id.split("/"); - - var alias = paths[chunks[0]]; - if (typeof alias == "string") { - chunks[0] = alias; - } else if (alias) { - chunks[0] = alias.location; - if (chunks.length == 1) - chunks.push(alias.main || alias.name); - } else if (alias === false) { - return ""; + 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 chunks.join("/"); + return id; } function resolveModulePath(id, pathMap) { var testPath = id, tail = ""; @@ -315,11 +321,11 @@ function resolveModulePath(id, pathMap) { testPath = "/" + testPath; while (testPath) { if (pathMap[testPath]) { - return pathMap[testPath] + (tail && "/" + tail); + return pathMap[testPath] + tail; } var i = testPath.lastIndexOf("/"); if (i === -1) break; - tail = testPath.substr(i + 1) + (tail && "/" + tail); + tail = testPath.substr(i) + tail; testPath = testPath.slice(0, i); } return id; @@ -360,7 +366,7 @@ function wrapUMD(module) { return; } console.log("wrapping module " + module.id); - + module.source = 'define(function(require, exports, module) {\n' + 'var _ = {require: require, exports: exports, module: module};\n' @@ -369,19 +375,19 @@ function wrapUMD(module) { + ' if (typeof name == "function") {\n' + ' m = name; deps = ["require", "exports", "module"]; name = _.module.id\n' + ' }\n' - + ' if (typeof name == "object") {\n' + + ' if (typeof name !== "string") {\n' + ' m = deps; deps = name; name = _.module.id\n' + ' }\n' - + ' if (typeof deps == "function") {\n' + + ' if (!m) {\n' + ' m = deps; deps = [];\n' + ' }\n' - + ' var ret = m ? m.apply(_.module, deps.map(function(n){return _[n] || require(n)})) : deps\n' - + ' if (ret) _.module.exports = ret;\n' + + ' var ret = typeof m == "function" ?\n' + + ' m.apply(_.module, deps.map(function(n){return _[n] || require(n)})) : m\n' + + ' if (ret != undefined) _.module.exports = ret;\n' + '}\n' + 'define.amd = true;' + module.source + '});'; - } function debugSrc(module) { diff --git a/plugins/c9.cli.publish/publish.js b/plugins/c9.cli.publish/publish.js index 476bb923..b812bc4e 100644 --- a/plugins/c9.cli.publish/publish.js +++ b/plugins/c9.cli.publish/publish.js @@ -35,11 +35,14 @@ define(function(require, exports, module) { var os = require("os"); var FormData = require("form-data"); var http = require(APIHOST.indexOf("localhost") > -1 ? "http" : "https"); + var Path = require("path"); var basename = require("path").basename; var dirname = require("path").dirname; + var async = require("async"); var verbose = false; var force = false; + var dryRun = false; // Set up basic auth for api if needed if (BASICAUTH) api.basicAuth = BASICAUTH; @@ -70,6 +73,11 @@ define(function(require, exports, module) { "alias": "f", "default": false, "boolean": true + }, + "dry-run" : { + "description": "Only build a test version", + "default": false, + "boolean": true } }, check: function(argv) { @@ -79,6 +87,7 @@ define(function(require, exports, module) { exec: function(argv) { verbose = argv["verbose"]; force = argv["force"]; + dryRun = argv["dry-run"]; publish( argv._[1], @@ -344,7 +353,7 @@ define(function(require, exports, module) { // Validate plugins var plugins = {}; fs.readdirSync(cwd).forEach(function(filename) { - if (/_test\.js$/.test(filename) || !/\.js$/.test(filename)) return; + if (/(__\w*__|_test)\.js$/.test(filename) || !/\.js$/.test(filename)) return; try { var val = fs.readFileSync(cwd + "/" + filename); } catch(e) { @@ -400,6 +409,8 @@ define(function(require, exports, module) { fs.writeFile(packagePath, JSON.stringify(json, 1, " "), function(err){ if (err) return callback(err); + if (dryRun) return build(); + SHELLSCRIPT = SHELLSCRIPT .replace(/\$1/, packagePath) .replace(/\$2/, json.version); @@ -437,47 +448,252 @@ define(function(require, exports, module) { var base = dirname(cwd); var packageName = json.name; var config = Object.keys(plugins).map(function(p) { - return packageName + "/" + p; + return "plugins/" + packageName + "/" + p.replace(/\.js$/, ""); }); - var paths = {}; - paths[packageName] = cwd; - - var build = require("architect-build/build"); - build(config, { - paths: paths, - enableBrowser: true, - includeConfig: false, - noArchitect: true, - compress: true, - obfuscate: true, - oneLine: true, - filter: [], - ignore: [], - withRequire: false, - stripLess: false, - basepath: base, - }, function(e, result) { - var packedFiles = result.sources.map(function(m) { - return m.file - }); - fs.writeFile("__packed__.js", result.code, "utf8", function(err, result) { - if (err) console.log(err); + var result, packedFiles = [], staticPlugin; + async.series([ + function(next) { + fs.readdir(cwd, function(err, files) { + if (err) + return next(); + var extraCode = []; + function forEachFile(dir, f) { + try { + fs.readdirSync(dir).forEach(function(filename) { + var data = fs.readFileSync(dir + "/" + filename, "utf8"); + f(filename, data); + }); + } catch(e) { + console.error(e); + } + } + + if (files.indexOf("builders") != -1) { + forEachFile(cwd + "/builders", function(filename, data) { + packedFiles.push(cwd + "/builders/" + filename); + extraCode.push({ + type: "builders", + filename: filename, + data: data + }); + }); + } + if (files.indexOf("keymaps") != -1) { + forEachFile(cwd + "/keymaps", function(filename, data) { + packedFiles.push(cwd + "/keymaps/" + filename); + extraCode.push({ + type: "keymaps", + filename: filename, + data: data + }); + }); + } + if (files.indexOf("modes") != -1) { + forEachFile(cwd + "/modes", function(filename, data) { + if (/(?:_highlight_rules|_test|_worker|_fold|_behaviou?r).js$/.test(filename)) + return; + var firstLine = data.split("\n", 1)[0]; + extraCode.push({ + type: "modes", + filename: filename, + data: firstLine + }); + }); + } + if (files.indexOf("outline") != -1) { + forEachFile(cwd + "/outline", function(filename, data) { + packedFiles.push(cwd + "/outline/" + filename); + extraCode.push({ + type: "outline", + filename: filename, + data: data + }); + }); + } + if (files.indexOf("runners") != -1) { + forEachFile(cwd + "/runners", function(filename, data) { + packedFiles.push(cwd + "/runners/" + filename); + extraCode.push({ + type: "runners", + filename: filename, + data: data + }); + }); + } + if (files.indexOf("snippets") != -1) { + forEachFile(cwd + "/snippets", function(filename, data) { + packedFiles.push(cwd + "/snippets/" + filename); + extraCode.push({ + type: "snippets", + filename: filename, + data: data + }); + }); + } + if (files.indexOf("themes") != -1) { + forEachFile(cwd + "/themes", function(filename, data) { + packedFiles.push(cwd + "/themes/" + filename); + extraCode.push({ + type: "themes", + filename: filename, + data: data + }); + }); + } + if (files.indexOf("templates") != -1) { + forEachFile(cwd + "/templates", function(filename, data) { + packedFiles.push(cwd + "/templates/" + filename); + extraCode.push({ + type: "templates", + filename: filename, + data: data + }); + }); + } + + if (json.installer) { + var path = join(cwd, json.installer); + var installerCode = fs.readFileSync(path, "utf8"); + + var m = installerCode.match(/\.version\s*=\s*(\d+)/g); + + var installerVersion = m && m[0]; + if (!installerVersion) + return callback(new Error("ERROR: missing installer version in " + json.installer)); + extraCode.push({ + type: "installer", + filename: json.installer, + data: version + }); + } + + if (!extraCode.length) + return next(); + + var code = (function() { + define(function(require, exports, module) { + main.consumes = [ + "Plugin", "plugin.debug" + ]; + main.provides = []; + return main; + function main(options, imports, register) { + var debug = imports["plugin.debug"]; + var Plugin = imports.Plugin; + var plugin = new Plugin(); + plugin.version = "VERSION"; + plugin.on("load", function load() { + extraCode.forEach(function(x) { + debug.addStaticPlugin(x.type, "PACKAGE_NAME", x.filename, x.data, plugin); + }); + }); + + plugin.load("PACKAGE_NAME.bundle"); + + register(null, {}); + } + }); + }).toString(); + + var indent = code.match(/\n\r?(\s*)/)[1].length; + code = code + .replace(/\r/g, "") + .replace(new RegExp("^ {" + indent + "}", "gm"), "") + .replace(/^.*?{|}$/g, "") + .replace(/PACKAGE_NAME/g, packageName) + .replace(/VERSION/g, json.version) + .replace(/^(\s*)extraCode/gm, function(_, indent) { + return JSON.stringify(extraCode, null, 4) + .replace(/^/gm, indent); + }); + + staticPlugin = { + source: code, + id: "plugins/" + packageName + "/__static__", + path: "" + }; + next(); + }); + }, + + function(next) { + var build = require("architect-build/build"); + var paths = {}; + paths["plugins/" + packageName] = cwd; + var additional = []; + var packedConfig = config.slice(); + if (staticPlugin) { + additional.push(staticPlugin); + packedConfig.push(staticPlugin.id); + } + var path = "plugins/" + packageName + "/__installed__"; + additional.push({ + id: path, + source: 'define("' + path + '", [],' + + JSON.stringify(packedConfig, null, 4) + ')', + literal : true, + order: -1 + }); + + build(config, { + additional: additional, + paths: paths, + enableBrowser: true, + includeConfig: false, + noArchitect: true, + compress: !dryRun, + obfuscate: true, + oneLine: true, + filter: [], + ignore: [], + withRequire: false, + stripLess: false, + basepath: base, + }, function(e, r) { + result = r; + result.sources.forEach(function(m) { + m.file && packedFiles.push(m.file); + }); + next(); + }); + }, + function(next) { + fs.writeFile("__packed__.js", result.code, "utf8", next); + }, + function(next) { + // console.log(packedFiles) zip(packedFiles); - }); - }); + } + ]); + + } + + function normalizePath(p) { + if (process.platform == "win32") + p = p.replace(/\\/g, "/").replace(/^(\w):/, "/$1"); + return p; } function zip(ignore){ - zipFilePath = join(os.tmpDir(), json.name + "@" + json.version); - var tarArgs = ["-zcvf", zipFilePath, "."]; - var c9ignore = process.env.HOME + "/.c9/.c9ignore"; + zipFilePath = join(os.tmpDir(), json.name + "@" + json.version) + ".tar.gz"; + var tarArgs = ["-zcvf", normalizePath(zipFilePath), "."]; + var c9ignore = normalizePath(process.env.HOME + "/.c9/.c9ignore"); fs.exists(c9ignore, function (exists) { if (exists) { tarArgs.push("--exclude-from=" + c9ignore); } - proc.spawn(TAR, { - args: tarArgs + ignore.forEach(function(p) { + p = Path.relative(cwd, p); + if (!/^\.+\//.test(p)) { + tarArgs.push("--exclude=./" + normalizePath(p)); + } + }); + tarArgs.push("--transform='flags=r;s|__packed__|__installed__|'"); + // console.log(tarArgs) + proc.spawn(TAR, { + args: tarArgs, + cwd: cwd }, function(err, p){ if (err) return callback(err); @@ -496,6 +712,8 @@ define(function(require, exports, module) { console.log("Built package", json.name + "@" + json.version); + if (dryRun) return callback(1); + upload(); }); }); diff --git a/plugins/c9.cli/cli.js b/plugins/c9.cli/cli.js index 0b7689cb..ab533f32 100755 --- a/plugins/c9.cli/cli.js +++ b/plugins/c9.cli/cli.js @@ -21,7 +21,7 @@ define(function(require, exports, module) { var module; var argv; - process.argv.some(function(n){ + process.argv.slice(2).some(function(n){ if (!n.match(/^[-\/]/) && n != "node") { module = n; return true; diff --git a/plugins/c9.core/ext.js b/plugins/c9.core/ext.js index 5d613650..f5b90e52 100644 --- a/plugins/c9.core/ext.js +++ b/plugins/c9.core/ext.js @@ -121,7 +121,7 @@ define(function(require, exports, module) { } } - return usedBy + return usedBy; } function unloadAllPlugins(exclude) { @@ -184,7 +184,7 @@ define(function(require, exports, module) { if (!lut[name]) throw new Error("Could not find plugin: " + name); - var plugin = lut[name] + var plugin = lut[name]; if (plugin.unload({ keep: true }) === false) throw new Error("Failed unloading plugin: " + name); @@ -407,7 +407,7 @@ define(function(require, exports, module) { this.freezePublicAPI.baseclass = function(){ baseclass = true; }; function getElement(name, callback) { - //remove id's after storing them. + // remove id's after storing them. if (!callback) { // If we run without APF, just return a simple object if (typeof apf == "undefined") @@ -442,13 +442,13 @@ define(function(require, exports, module) { return; // Delete their global reference delete window[id]; - //delete apf.nameserver.lookup.all[node.id]; + // delete apf.nameserver.lookup.all[node.id]; // Keep their original name in a lookup table names[id] = node; // Set a new unique id - if (node.localName != "page") { //Temp hack, should fix in tabs + if (node.localName != "page") { // Temp hack, should fix in tabs node.id = "element" + node.$uniqueId; apf.nameserver.lookup.all[node.id] = node; } @@ -532,7 +532,7 @@ define(function(require, exports, module) { function cleanUp(keepElements) { if (!keepElements) { - //Loop through elements + // Loop through elements elements.forEach(function(element) { element.destroy(true, true); }); @@ -541,7 +541,7 @@ define(function(require, exports, module) { waiting = []; } - //Loop through events + // Loop through events events.forEach(function(eventRecord) { var event = eventRegistry[eventRecord[0]]; if (!event) return; // this happens with mock plugins during testing @@ -562,7 +562,7 @@ define(function(require, exports, module) { }); events = []; - //Loop through other + // Loop through other other.forEach(function(o) { o(); }); @@ -594,7 +594,7 @@ define(function(require, exports, module) { api[type].get("persistent/" + apiKey, function(err, data){ if (err) return callback(err); - try{ callback(null, JSON.stringify(data)); } + try { callback(null, JSON.stringify(data)); } catch(e){ return callback(e); } }); } diff --git a/plugins/c9.core/util.js b/plugins/c9.core/util.js index fd78dff6..cec28160 100644 --- a/plugins/c9.core/util.js +++ b/plugins/c9.core/util.js @@ -209,6 +209,14 @@ define(function(require, exports, module) { return JSON.stringify(sortByKeys(obj), replacer, spaces); }; + plugin.safeParseJson = function(strJson, cb){ + // Remove comments + var data = strJson.replace(/(^|\n)\s*\/\/.*/g, ""); + + try { return JSON.parse(data); } + catch (e) { cb(e); return false; } + } + /** * */ @@ -269,8 +277,7 @@ define(function(require, exports, module) { var reHome = new RegExp("^" + plugin.escapeRegExp(c9.home || "/home/ubuntu")); plugin.normalizePath = function(path){ - if (!path || path.charAt(0) == "~") return path; - return normalize(path.replace(reHome, "~")); + return path && normalize(path.replace(reHome, "~")); }; /** @@ -340,10 +347,10 @@ define(function(require, exports, module) { }; plugin.escapeShell = function(cmd) { - var re = /([\#\&\;\`\|\*\?<>\^\(\)\[\]\{\}\$\,\x0A\xFF\' \"])/g; + var re = /([\#\&\;\`\|\*\?<>\^\(\)\[\]\{\}\$\,\x0A\xFF\' \"\\])/g; return cmd.replace(re, "\\$1");//.replace(/^~/, "\\~"); }; - + var cloneObject = plugin.cloneObject = function(obj) { if (obj === null || typeof obj !== "object") return obj; diff --git a/plugins/c9.ide.ace/ace.js b/plugins/c9.ide.ace/ace.js index 43d2ea37..d1f1e89c 100644 --- a/plugins/c9.ide.ace/ace.js +++ b/plugins/c9.ide.ace/ace.js @@ -90,7 +90,8 @@ define(function(require, exports, module) { var isMinimal = options.minimal; var themeLoaded = {}; - var lastTheme, grpSyntax; + var themeCounter = 100; + var lastTheme, grpSyntax, grpThemes; var theme; var skin = settings.get("user/general/@skin"); @@ -140,8 +141,10 @@ define(function(require, exports, module) { function setTheme(path, isPreview, fromServer, $err) { // Get Theme or wait for theme to load - try{ - theme = fromServer || require(path); + try { + theme = typeof path == "object" + ? path + : fromServer || require(path); // fixes a problem with Ace architect loading /lib/ace // creating a conflict with themes @@ -1089,69 +1092,90 @@ define(function(require, exports, module) { /**** Themes ****/ - var grpThemes = new ui.group(); - var mnuThemes = new ui.menu({ + grpThemes = new ui.group(); + + menus.addItemByPath("View/Themes/", new ui.menu({ "onprop.visible" : function(e) { if (e.value) grpThemes.setValue(settings.get("user/ace/@theme")); } - }); - menus.addItemByPath("View/Themes/", mnuThemes, 350000, handle); + }), 350000, handle); - var preview; - var setMenuThemeDelayed = lang.delayedCall(function(){ - setMenuTheme(preview, true); - }, 150); - function setMenuTheme(path, isPreview) { - setTheme(path || settings.get("user/ace/@theme"), isPreview); - } - - function addThemeMenu(name, path, index) { - menus.addItemByPath("View/Themes/" + name, new ui.item({ - type: "radio", - value: path || themes[name], - group: grpThemes, - - onmouseover: function(e) { - preview = this.value; - setMenuThemeDelayed.schedule(); - }, - - onmouseout: function(e) { - preview = null; - setMenuThemeDelayed.schedule(); - }, - - onclick: function(e) { - setMenuTheme(e.currentTarget.value); - } - }), index, handle); - } - // Create Theme Menus - var mainCounter = 100; for (var name in themes) { if (themes[name] instanceof Array) { // Add Menu Item (for submenu) - menus.addItemByPath("View/Themes/" + name + "/", null, mainCounter++, handle); + menus.addItemByPath("View/Themes/" + name + "/", null, themeCounter++, handle); themes[name].forEach(function (n) { // Add Menu Item var themeprop = Object.keys(n)[0]; - addThemeMenu(name + "/" + themeprop, n[themeprop]); + addThemeMenu(name + "/" + themeprop, n[themeprop], -1); }); } else { // Add Menu Item - addThemeMenu(name, null, mainCounter++); + addThemeMenu(name, null, themeCounter++); } } + /**** Syntax ****/ + grpSyntax = new ui.group(); handle.addElement(grpNewline, grpSyntax, grpThemes); } + var preview; + var setMenuThemeDelayed = lang.delayedCall(function(){ + setMenuTheme(preview, true); + }, 150); + function setMenuTheme(path, isPreview) { + setTheme(path || settings.get("user/ace/@theme"), isPreview); + } + function addThemeMenu(name, path, index, plugin) { + menus.addItemByPath("View/Themes/" + name, new ui.item({ + type: "radio", + value: path || themes[name], + group: grpThemes, + + onmouseover: function(e) { + preview = this.value; + setMenuThemeDelayed.schedule(); + }, + + onmouseout: function(e) { + preview = null; + setMenuThemeDelayed.schedule(); + }, + + onclick: function(e) { + setMenuTheme(e.currentTarget.value); + } + }), index == -1 ? undefined : index || themeCounter++, plugin || handle); + } + function addTheme(css, plugin){ + var theme = { cssText: css }; + var firstLine = css.split("\n", 1)[0].replace(/\/\*|\*\//g, "").trim(); + firstLine.split(";").forEach(function(n){ + if (!n) return; + var info = n.split(":"); + theme[info[0].trim()] = info[1].trim(); + }); + theme.isDark = theme.isDark == "true"; + + themes[theme.name] = theme; + + ui.insertCss(exports.cssText, plugin); + addThemeMenu(theme.name, theme, null, plugin); + + handleEmit("addTheme"); + + plugin.addOther(function(){ + delete themes[theme.name]; + handleEmit("removeTheme"); + }); + } function rebuildSyntaxMenu() { menus.remove("View/Syntax/"); @@ -1194,22 +1218,35 @@ define(function(require, exports, module) { } } - var updateSyntaxMenu = lang.delayedCall(rebuildSyntaxMenu, 50); + var updateSyntaxMenu = lang.delayedCall(function() { + rebuildSyntaxMenu(); + tabs.getTabs().forEach(function(tab) { + if (tab.editorType == "ace") { + var c9Session = tab.document.getSession(); + if (c9Session && c9Session.session) + detectSyntax(c9Session, tab.path); + } + }); + }, 50); /***** Syntax *****/ function defineSyntax(opts) { if (!opts.name || !opts.caption) throw new Error("malformed syntax definition"); + var name = opts.name; modes.byCaption[opts.caption] = opts; modes.byName[name] = opts; if (!opts.extensions) opts.extensions = ""; + opts.extensions.split("|").forEach(function(ext) { modes.extensions[ext] = name; }); + + updateSyntaxMenu.schedule(); } @@ -1218,9 +1255,11 @@ define(function(require, exports, module) { var extPos = fileName.lastIndexOf(".") + 1; if (extPos) return fileName.substr(extPos).toLowerCase(); + // special case for new files if (/^Untitled\d+$/.test(fileName)) fileName = fileName.replace(/\d+/, ""); + return "^" + fileName; } @@ -1296,7 +1335,7 @@ define(function(require, exports, module) { syntax = "json"; } else if (/\.(bashrc|inputrc)$/.test(path)) { - syntax = "bash"; + syntax = "sh"; } else if (/\.(git(attributes|config|ignore)|npmrc)$/.test(path)) { syntax = "ini"; @@ -1500,7 +1539,7 @@ define(function(require, exports, module) { /** * Set the theme for ace. * - * Here's a list of known themes: + * Here's a list of default themes: * * * ace/theme/ambiance * * ace/theme/chrome @@ -1546,7 +1585,7 @@ define(function(require, exports, module) { * @param {Object} syntax * @param {Object} syntax.caption Caption to display in the menu * @param {Number} syntax.order order in the menu - * @param {String} syntax.id The path to corresponding ace language mode. (if doesn't contain "/" assumed to be from "ace/mode/") + * @param {String} syntax.name The path to corresponding ace language mode. (if doesn't contain "/" assumed to be from "ace/mode/") * @param {String} syntax.extensions file extensions in the form "ext1|ext2|^filename". this is case-insensitive */ defineSyntax: defineSyntax, @@ -1559,6 +1598,13 @@ define(function(require, exports, module) { return mode && mode.caption || "Text"; }, + /** + * Adds a menu item for a new theme + * @param {String} css + * @param {Plugin} plugin + */ + addTheme: addTheme, + /** * @ignore */ @@ -2085,12 +2131,12 @@ define(function(require, exports, module) { bgStyle.bottom = upload ? "" : 0; } - function detectSettingsOnLoad(c9Session) { + function detectSettingsOnLoad(c9Session, doc) { var session = c9Session.session; if (settings.get("project/ace/@guessTabSize")) whitespaceUtil.detectIndentation(session); if (!session.syntax) { - var syntax = detectSyntax(c9Session); + var syntax = detectSyntax(c9Session, doc && doc.tab && doc.tab.path); if (syntax) setSyntax(c9Session, syntax, true); } @@ -2147,7 +2193,7 @@ define(function(require, exports, module) { // aceSession.doc.setValue(e.value || ""); } else { aceSession.setValue(e.value || ""); - detectSettingsOnLoad(c9Session); + detectSettingsOnLoad(c9Session, doc); hideProgress(); } @@ -2259,7 +2305,7 @@ define(function(require, exports, module) { setState(doc, e.state); if (doc.meta.newfile) { - detectSettingsOnLoad(c9Session); + detectSettingsOnLoad(c9Session, doc); aceSession.on("change", function detectIndentation() { if (aceSession.$guessTabSize) { if (aceSession.getLength() <= 2) return; @@ -2270,7 +2316,7 @@ define(function(require, exports, module) { aceSession.off("change", detectIndentation); }); } else if (doc.hasValue()) { - detectSettingsOnLoad(c9Session); + detectSettingsOnLoad(c9Session, doc); } // Create the ace like undo manager that proxies to diff --git a/plugins/c9.ide.ace/themes.js b/plugins/c9.ide.ace/themes.js index 802bd111..94fe9cce 100644 --- a/plugins/c9.ide.ace/themes.js +++ b/plugins/c9.ide.ace/themes.js @@ -16,7 +16,7 @@ define(function(require, exports, module) { var plugin = new PreferencePanel("Ajax.org", main.consumes, { caption: "Themes", - className: "keybindings", + className: "flatform", form: true, noscroll: true, colwidth: 150, @@ -31,6 +31,18 @@ define(function(require, exports, module) { if (loaded) return false; loaded = true; + function update(){ + if (!drawn) return; + + var list = getThemes(); + plugin.form.update({ + id: "syntax", + items: list + }); + } + + ace.on("addTheme", update); + ace.on("removeTheme", update); } var drawn; @@ -38,17 +50,7 @@ define(function(require, exports, module) { if (drawn) return; drawn = true; - var list = []; - var themes = ace.themes - for (var base in themes) { - if (themes[base] instanceof Array) - themes[base].forEach(function (n) { - var themeprop = Object.keys(n)[0]; - list.push({ caption: themeprop, value: n[themeprop] }); - }); - else - list.push({ caption: base, value: themes[base] }); - } + var list = getThemes(); var rb1, rb2, rb3, rb4, rb5; plugin.form.add([ @@ -138,6 +140,7 @@ define(function(require, exports, module) { title: "Syntax Theme", type: "dropdown", path: "user/ace/@theme", + name: "syntax", width: 165, onchange: function(e) { ace.setTheme(e.value); @@ -175,6 +178,20 @@ define(function(require, exports, module) { /***** Methods *****/ + function getThemes(){ + var list = []; + var themes = ace.themes + for (var base in themes) { + if (themes[base] instanceof Array) + themes[base].forEach(function (n) { + var themeprop = Object.keys(n)[0]; + list.push({ caption: themeprop, value: n[themeprop] }); + }); + else + list.push({ caption: base, value: themes[base] }); + } + return list; + } /***** Lifecycle *****/ @@ -183,12 +200,6 @@ define(function(require, exports, module) { }); plugin.on("draw", function(e) { draw(e); - }); - plugin.on("enable", function() { - - }); - plugin.on("disable", function() { - }); plugin.on("unload", function() { loaded = false; diff --git a/plugins/c9.ide.keys/editor.js b/plugins/c9.ide.keys/editor.js index 970e4e08..9f60eb5c 100644 --- a/plugins/c9.ide.keys/editor.js +++ b/plugins/c9.ide.keys/editor.js @@ -38,6 +38,8 @@ define(function(require, exports, module) { }); // var emit = plugin.getEmitter(); + var customKeymaps = {}; + var model, datagrid, changed, container, filterbox; var appliedCustomSets, intro, reloading; @@ -57,6 +59,15 @@ define(function(require, exports, module) { } }, plugin); + settings.on("user/ace/@keyboardmode", function(){ + var mode = settings.getJson("user/ace/@keyboardmode"); + if (customKeymaps[mode]) { + settings.set("user/ace/@keyboardmode", "default"); + settings.setJson("user/key-bindings", customKeymaps[mode]); + updateCommandsFromSettings(); + } + }); + settings.on("read", function(e) { updateCommandsFromSettings(); }, plugin); @@ -184,6 +195,7 @@ define(function(require, exports, module) { title: "Keyboard Mode", type: "dropdown", path: "user/ace/@keyboardmode", + name: "kbmode", items: [ { caption: "Default", value: "default" }, { caption: "Vim", value: "vim" }, @@ -338,9 +350,12 @@ define(function(require, exports, module) { // Add key commands.bindKey(lastKey, commands.commands[name]); + var keys = {}; + keys[commands.platform] = (node.actualKeys || node.keys).split("|"); + var n = { command: node.name, - keys: (node.actualKeys || node.keys).split("|") + keys: keys }; var cmds = settings.getJson("user/key-bindings") || []; @@ -377,6 +392,8 @@ define(function(require, exports, module) { if (!cmd || !cmd.command) return; var keys = cmd.keys; + if (typeof keys == "object" && keys[commands.platform]) + keys = keys[commands.platform]; if (Array.isArray(keys)) keys = keys.join("|"); if (typeof keys == "string") @@ -472,7 +489,7 @@ define(function(require, exports, module) { }).join(",\n"); if (!keys.length) - value += ' // { "command": "nexttab", "keys": ["Ctrl-Tab"] }'; + value += ' // { "command": "nexttab", "keys": { win: "Ctrl-Tab", mac: "Cmd-Tab" } }'; value += "\n]"; @@ -495,6 +512,46 @@ define(function(require, exports, module) { } } + function addCustomKeymap(name, keymap, plugin){ + customKeymaps[name] = keymap; + + if (!Object.keys(customKeymaps).length) { + menus.addItemByPath("Edit/Keyboard Mode/~", + new ui.divider(), 10000, plugin); + } + + menus.addItemByPath("Edit/Keyboard Mode/" + name, new ui.item({ + type: "radio", + value: name.toLowerCase(), + onclick: function(e) { + settings.set("user/ace/@keyboardmode", name); + } + }), 10000 + Object.keys(customKeymaps).length, plugin); + + plugin.addOther(function(){ delete customKeymaps[name]; }); + + if (plugin.visible) + updateKeymaps(); + } + + function updateKeymaps(){ + var items = [ + { caption: "Default", value: "default" }, + { caption: "Vim", value: "vim" }, + { caption: "Emacs", value: "emacs" }, + { caption: "Sublime", value: "sublime" } + ]; + + for (var name in customKeymaps) { + items.push({ caption: name, value: name }); + } + + plugin.form.update([{ + id: "kbmode", + items: items + }]) + } + /***** Lifecycle *****/ plugin.on("load", function() { @@ -504,7 +561,10 @@ define(function(require, exports, module) { draw(e); }); plugin.on("activate", function(e) { - datagrid && datagrid.resize(); + if (!drawn) return; + + datagrid.resize(); + updateKeymaps(); }); plugin.on("resize", function(e) { datagrid && datagrid.resize(); @@ -532,7 +592,12 @@ define(function(require, exports, module) { /** * */ - editUserKeys: editUserKeys + editUserKeys: editUserKeys, + + /** + * + */ + addCustomKeymap: addCustomKeymap }); register(null, { diff --git a/plugins/c9.ide.plugins/debug.js b/plugins/c9.ide.plugins/debug.js index f2b6ff30..2d1216b5 100644 --- a/plugins/c9.ide.plugins/debug.js +++ b/plugins/c9.ide.plugins/debug.js @@ -2,7 +2,8 @@ define(function(require, exports, module) { main.consumes = [ "Plugin", "vfs", "fs", "plugin.loader", "c9", "ext", "watcher", - "dialog.notification", "ui", "menus", "commands", "settings", "auth" + "dialog.notification", "ui", "menus", "commands", "settings", "auth", + "installer", "find", "util" ]; main.provides = ["plugin.debug"]; return main; @@ -12,8 +13,11 @@ define(function(require, exports, module) { var vfs = imports.vfs; var watcher = imports.watcher; var ext = imports.ext; + var util = imports.util; + var find = imports.find; var ui = imports.ui; var menus = imports.menus; + var installer = imports.installer; var settings = imports.settings; var commands = imports.commands; var fs = imports.fs; @@ -23,7 +27,9 @@ define(function(require, exports, module) { var notify = imports["dialog.notification"].show; var dirname = require("path").dirname; + var basename = require("path").basename; var join = require("path").join; + var async = require("async"); var architect; @@ -35,6 +41,9 @@ define(function(require, exports, module) { var ENABLED = c9.location.indexOf("debug=2") > -1; var HASSDK = c9.location.indexOf("sdk=0") === -1; + var reParts = /^(builders|keymaps|modes|outline|runners|snippets|themes)\/(.*)/ + var reModule = /(?:_highlight_rules|_test|_worker|_fold|_behaviou?r).js$/ + var loaded = false; function load() { if (loaded) return false; @@ -115,49 +124,124 @@ define(function(require, exports, module) { return; } - // Fetch package.json - fs.readFile("~/.c9/plugins/" + name + "/package.json", function(err, data){ - if (err) { - console.error(err); - return next(); - } - - try{ - var options = JSON.parse(data); - if (!options.plugins) - throw new Error("Missing plugins property in package.json of " + name); - } - catch(e){ - console.error(err); - return next(); - } - - Object.keys(options.plugins).forEach(function(path){ - var pluginPath = name + "/" + path + ".js"; - - // Watch project path - watch("~/.c9/plugins/" + pluginPath); - - var cfg = options.plugins[path]; - var host = vfs.baseUrl + "/"; - var base = join(String(c9.projectId), - "plugins", auth.accessToken); - - cfg.packagePath = host + join(base, pluginPath.replace(/^plugins\//, "")); - cfg.staticPrefix = host + join(base, name); - cfg.apikey = "0000000000000000000000000000="; - - config.push(cfg); - }); - - next(); + var resourceHolder = new Plugin(); + var resourceVersion = ""; + + resourceHolder.on("load", function(){ load(); }); + + resourceHolder.freezePublicAPI({ + get version(){ return resourceVersion }, + set version(v){ resourceVersion = v; } }); + + var inited = false; + function load(){ + async.parallel([ + function(next){ + // Fetch package.json + fs.readFile("~/.c9/plugins/" + name + "/package.json", function(err, data){ + if (err) + return next(err); + + try { + var options = JSON.parse(data); + if (!options.plugins) + throw new Error("Missing plugins property in package.json of " + name); + } + catch(e){ + return next(err); + } + + var host = vfs.baseUrl + "/"; + var base = join(String(c9.projectId), + "plugins", auth.accessToken); + + var pathConfig = {}; + + pathConfig["plugins/" + name] = host + join(base, name); + // Add the plugin to the config + Object.keys(options.plugins).forEach(function(path){ + var pluginPath = name + "/" + path; + + // Watch project path + watch("~/.c9/plugins/" + pluginPath); + var cfg = options.plugins[path]; + cfg.packagePath = "plugins/" + name + "/" + path; + cfg.staticPrefix = host + join(base, name); + cfg.apikey = "0000000000000000000000000000="; + + config.push(cfg); + }); + + requirejs.config({paths: pathConfig}); + + resourceHolder.version = options.version; + + // Start the installer if one is included + if (options.installer) { + addStaticPlugin("installer", name, options.installer, + null, resourceHolder); + } + + next(); + }); + }, + function(next){ + var path = join("~/.c9/plugins", name); + var rePath = new RegExp("^" + util.escapeRegExp(path.replace(/^~/, c9.home) + "/"), "gm"); + find.getFileList({ + path: path, + nocache: true, + buffer: true + }, function(err, data){ + if (err) + return next(err); + + // Remove the base path + data = data.replace(rePath, ""); + + if (data.match(/^__installed__.js/)) + return next("installed"); + + // Process all the submodules + var parallel = processModules(path, data, resourceHolder); + async.parallel(parallel, function(err, data){ + if (err) + return next(err); + + if (!inited) + resourceHolder.load(name + ".bundle"); + + // Done + next(); + }); + }); + } + ], function(err, results){ + if (err) console.error(err); + + if (!inited) { + next(); + inited = true; + } + }); + } + load(); } function finish(){ if (!config.length) return; // Load config + if (installer.sessions.length) { + installer.on("stop", function(err){ + if (err) + return console.error(err); + finish(); + }); + return; + } + architect.loadAdditionalPlugins(config, function(err){ if (err) console.error(err); }); @@ -166,6 +250,126 @@ define(function(require, exports, module) { list.forEach(next); } + function processModules(path, data, plugin){ + var parallel = []; + + data.split("\n").forEach(function(line){ + if (!line.match(reParts)) return; + + var type = RegExp.$1; + var filename = RegExp.$2; + if (filename.indexOf("/") > -1) return; + + if (type == "modes" && filename.match(reModule)) + return; + + parallel.push(function(next){ + fs.readFile(join(path, type, filename), function(err, data){ + if (err) { + console.error(err); + return next(err); + } + + addStaticPlugin(type, basename(path), filename, data, plugin); + + next(); + }); + }); + }); + + return parallel; + } + + function addStaticPlugin(type, pluginName, filename, data, plugin) { + var services = architect.services; + var path = "plugins/" + pluginName + "/" + + (type == "installer" ? "" : type + "/") + + filename.replace(/\.js$/, ""); + + var bundleName = pluginName + ".bundle"; + if (!services[bundleName] && type !== "installer") { + services[bundleName] = plugin; + architect.lut["~/.c9/plugins/" + pluginName] = { + provides: [] + }; + architect.pluginToPackage[bundleName] = { + path: "~/.c9/plugins/" + pluginName, + package: pluginName, + version: plugin.version, + isAdditionalMode: true + }; + if (!architect.packages[pluginName]) + architect.packages[pluginName] = []; + architect.packages[pluginName].push(name); + } + + switch (type) { + case "builders": + data = util.safeParseJson(data, function() {}); + if (!data) return; + + services.build.addBuilder(filename, data, plugin); + break; + case "keymaps": + data = util.safeParseJson(data, function() {}); + if (!data) return; + + services["preferences.keybindings"].addCustomKeymap(filename, data, plugin); + break; + case "modes": + var mode = {}; + var firstLine = data.split("\n", 1)[0].replace(/\/\*|\*\//g, "").trim(); + firstLine.split(";").forEach(function(n){ + if (!n) return; + var info = n.split(":"); + mode[info[0].trim()] = info[1].trim(); + }); + + services.ace.defineSyntax({ + name: join(pluginName, "modes", path), + caption: mode.caption, + extensions: (mode.extensions || "").trim() + .replace(/\s*,\s*/g, "|") + }); + break; + case "outline": + if (!data) return; + + services.outline.addOutlinePlugin(path, data, plugin); + break; + case "runners": + data = util.safeParseJson(data, function() {}); + if (!data) return; + + services.run.addRunner(filename, data, plugin); + break; + case "snippets": + services["language.complete"].addSnippet(data, plugin); + break; + case "themes": + services.ace.addTheme(data, plugin); + break; + case "templates": + services.newresource.addFileTemplate(data, plugin); + break; + case "installer": + if (data) { + installer.createSession(pluginName, data, function(v, o){ + require([path], function(fn){ + fn(v, o); + }); + }); + } + else { + require([path], function(fn){ + installer.createSession(pluginName, fn.version, function(v, o){ + fn(v, o); + }); + }); + } + } + } + // Check if require.s.contexts._ can help watching all dependencies function watch(path){ watcher.watch(path); @@ -266,12 +470,6 @@ define(function(require, exports, module) { plugin.on("load", function() { load(); - }); - plugin.on("enable", function() { - - }); - plugin.on("disable", function() { - }); plugin.on("unload", function() { loaded = false; @@ -289,6 +487,10 @@ define(function(require, exports, module) { get architect(){ throw new Error(); }, set architect(v){ architect = v; }, + /** + * + */ + addStaticPlugin: addStaticPlugin, /** * */ diff --git a/plugins/c9.ide.plugins/installer.js b/plugins/c9.ide.plugins/installer.js index dbe02907..2e102bae 100644 --- a/plugins/c9.ide.plugins/installer.js +++ b/plugins/c9.ide.plugins/installer.js @@ -1,6 +1,6 @@ define(function(require, exports, module) { main.consumes = [ - "Plugin", "proc", "c9", "pubsub", "auth" + "Plugin", "proc", "c9", "pubsub", "auth", "util" ]; main.provides = ["plugin.installer"]; return main; @@ -8,10 +8,12 @@ define(function(require, exports, module) { function main(options, imports, register) { var Plugin = imports.Plugin; var c9 = imports.c9; + var util = imports.util; var proc = imports.proc; var auth = imports.auth; var pubsub = imports.pubsub; + var escapeShell = util.escapeShell; var updates = options.updates; var architect; @@ -103,7 +105,7 @@ define(function(require, exports, module) { function installPlugin(name, version, callback){ proc.spawn("bash", { - args: ["-c", ["c9", "install", "--local", "--force", "--accessToken=" + auth.accessToken, name + "@" + version].join(" ")] + args: ["-c", ["c9", "install", "--local", "--force", "--accessToken=" + auth.accessToken, escapeShell(name) + "@" + escapeShell(version)].join(" ")] }, function(err, process){ if (err) return callback(err); @@ -127,7 +129,7 @@ define(function(require, exports, module) { function uninstallPlugin(name, callback){ proc.spawn("c9", { - args: ["remove", "--local", "--force", "--accessToken=" + auth.accessToken, name] + args: ["remove", "--local", "--force", "--accessToken=" + auth.accessToken, escapeShell(name)] }, function(err, process){ if (err) return callback(err); @@ -154,12 +156,6 @@ define(function(require, exports, module) { plugin.on("load", function() { load(); - }); - plugin.on("enable", function() { - - }); - plugin.on("disable", function() { - }); plugin.on("unload", function() { loaded = false; diff --git a/plugins/c9.ide.plugins/loader.js b/plugins/c9.ide.plugins/loader.js index 78455b7f..9b0910ce 100644 --- a/plugins/c9.ide.plugins/loader.js +++ b/plugins/c9.ide.plugins/loader.js @@ -1,3 +1,4 @@ +/*global requirejs*/ define(function(require, exports, module) { main.consumes = [ "Plugin", "vfs", "c9", "plugin.installer", "fs", "auth" @@ -26,6 +27,7 @@ define(function(require, exports, module) { var HASSDK = c9.location.indexOf("sdk=0") === -1; var plugins = options.plugins; + var loadFromDisk = options.loadFromDisk var names = []; var loaded = false; @@ -36,18 +38,6 @@ define(function(require, exports, module) { if (!HASSDK) return; if (!ENABLED) return; - for (var i = 0; i < plugins.length; i++) { - try { - if (plugins[i].setup) - plugins[i].setup = eval(plugins[i].setup); - } - catch(e) { - console.error("Could not load plugin from cache: " + plugins[i].name); - delete plugins[i].setup; - continue; - } - } - loadPlugins(plugins); } @@ -60,47 +50,72 @@ define(function(require, exports, module) { } var wait = 0; + var host = vfs.baseUrl + "/"; + var base = join(String(c9.projectId), "plugins", auth.accessToken); + var install = []; + if (loadFromDisk) { + fs.readdir("~/.c9/plugins", function(error, files){ + files.forEach(function(f) { + if (!/^[_.]/.test(f.name)) + loadOne({packageName: f.name}, false); + }); + }); + } + + var packages = {}; config.forEach(function(options){ var name = options.packagePath.replace(/^plugins\/([^\/]*?)\/.*$/, "$1"); - names.push(name); - - var path = options.packagePath + ".js"; - var host = vfs.baseUrl + "/"; - var base = join(String(c9.projectId), "plugins", auth.accessToken); - - options.packagePath = host + join(base, path.replace(/^plugins\//, "")); - options.staticPrefix = host + join(base, name); - - if (!options.setup) { - wait++; - - var install = []; - fs.exists("~/.c9/" + path, function(exists){ - if (!exists) { - install.push(options); - names.remove(name); - } - - if (!--wait) - done(install); - }); + if (!packages[name]) { + packages[name] = { + packageName: name, + apiKey: options.apiKey + }; } + names.push(name); }); - if (!wait) - done([]); + Object.keys(packages).forEach(function(key) { + loadOne(packages[key], false); + }); - function done(install){ - if (install.length) - installer.installPlugins(install, function(err){ - if (err) console.error(err); - }); + function loadOne(packageConfig, forceInstall) { + wait++; - if (names.length) + var packageName = packageConfig.packageName; + var root = "plugins/" + packageName; + var paths = {}; + paths[root] = host + base + "/" + packageName; + requirejs.config({paths: paths}); + requirejs.undef(root + "/__installed__.js"); + require([root + "/__installed__"], function(plugins) { + var config = plugins.map(function(p) { + return { + staticPrefix: host + join(base, paths[root]), + packagePath: p + }; + }); + architect.loadAdditionalPlugins(config, function(err){ if (err) console.error(err); }); + + done(); + }, function(err) { + if (err && forceInstall) { + install.push(packageName); + } + done(); + }); + } + + function done(){ + if (!--wait) return; + if (install.length) { + installer.installPlugins(install, function(err){ + if (err) console.error(err); + }); + } } } @@ -108,12 +123,6 @@ define(function(require, exports, module) { plugin.on("load", function() { load(); - }); - plugin.on("enable", function() { - - }); - plugin.on("disable", function() { - }); plugin.on("unload", function() { loaded = false; diff --git a/plugins/c9.ide.plugins/manager.js b/plugins/c9.ide.plugins/manager.js index 9058bfbc..77294880 100644 --- a/plugins/c9.ide.plugins/manager.js +++ b/plugins/c9.ide.plugins/manager.js @@ -134,6 +134,10 @@ define(function(require, exports, module) { } }), 210, plugin); }); + + ext.on("register", function(){ + setTimeout(reloadModel); + }); } } @@ -580,14 +584,18 @@ define(function(require, exports, module) { // Download tar file with template for plugin proc.execFile("bash", { - args: ["-c", ["curl", "-L", url, "--create-dirs", "-o", tarPathAbsolute].join(" ")] + args: ["-c", [ + // using mkdirp since "--create-dirs" is broken on windows + "mkdir", "-p", util.escapeShell(dirname(tarPathAbsolute)), ";", + "curl", "-L", util.escapeShell(url), "-o", util.escapeShell(tarPathAbsolute)].join(" ") + ] }, function(err, stderr, stdout){ if (err) return handleError(err); // Untar tar file proc.execFile("bash", { - args: ["-c", ["tar", "-zxvf", tarPath, "-C", pluginsDirAbsolute].join(" ")] + args: ["-c", ["tar", "-zxvf", util.escapeShell(tarPath), "-C", util.escapeShell(pluginsDirAbsolute)].join(" ")] }, function(err, stderr, stdout){ if (err) return handleError(err); diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/builders/example.build b/plugins/c9.ide.plugins/mock/c9.ide.example3/builders/example.build new file mode 100644 index 00000000..8986f199 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/builders/example.build @@ -0,0 +1,8 @@ +// Create a custom Cloud9 build system - similar to the Sublime build system +// For more information see https://docs.c9.io/custom_runners.html +{ + "cmd" : ["ls", "$file", "$args"], + "env" : {}, + "info" : "Building $project_path/$file_name", + "selector": "source.ext" +} \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/install.js b/plugins/c9.ide.plugins/mock/c9.ide.example3/install.js new file mode 100644 index 00000000..f87bdec5 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/install.js @@ -0,0 +1,57 @@ +define(function(require, exports, module) { + +module.exports = function(session, options){ + // Dependencies for the collaboration features of Cloud9 + + session.install({ + "name": "SQLite", + "description": "SQLite Database and NPM module", + "cwd": "~/.c9", + "optional": true + }, [ + { + "npm": ["sqlite3@3.0.5"] + }, + { + "tar.gz": { + "url": "https://raw.githubusercontent.com/c9/install/master/packages/sqlite3/linux/sqlite3.tar.gz", + "target": "~/.c9/lib/sqlite3", + "dir": "sqlite3" + } + }, + { + "symlink": { + "source": "~/.c9/lib/sqlite3/sqlite3", + "target": "~/.c9/bin/sqlite3" + } + } + ]); + + session.install({ + "name": "Sequalize", + "description": "Sequalize NPM module", + "cwd": "~/.c9", + "optional": true + }, { + "npm": ["sequelize@2.0.0-beta.0"] + }); + + session.install({ + "name": "Collab Server", + "description": "A small Node.js collaboration server", + "cwd": "~/.c9", + "optional": true + }, { + "tar.gz": { + "url": "https://raw.githubusercontent.com/c9/install/master/packages/extend/c9-vfs-extend.tar.gz", + "target": "~/.c9" + } + }); + + // Show the installation screen + session.start(); +}; + +module.exports.version = 1; + +}); \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/keymaps/eclipse b/plugins/c9.ide.plugins/mock/c9.ide.example3/keymaps/eclipse new file mode 100644 index 00000000..566c1775 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/keymaps/eclipse @@ -0,0 +1,28 @@ +// demostene.ro - Eclipse keymap for Cloud 9 +// http://demostene.ro/2014/11/eclipse-keymap-for-cloud9-ide-c9-io.html +[ + { + "command": "gotoline", + "keys": ["Ctrl-L"] + }, + { + "command": "formatcode", + "keys": ["Ctrl-Shift-F"] + }, + { + "command": "renameVar", + "keys": ["Alt-Shift-R"] + }, + { + "command": "searchinfiles", + "keys": ["Ctrl-H"] + }, + { + "command": "navigate", + "keys": ["Ctrl-Shift-R"] + }, + { + "command": "redo", + "keys": ["Ctrl-Y"] + } +] \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript.js b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript.js new file mode 100644 index 00000000..018d0a5a --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript.js @@ -0,0 +1,117 @@ +/* caption: Javascript; extensions: .js, .javascript */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("ace/lib/oop"); +var TextMode = require("ace/mode/text").Mode; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; +var WorkerClient = require("ace/worker/worker_client").WorkerClient; +var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("ace/mode/folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = JavaScriptHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start" || state == "no_regex") { + var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start" || endState == "no_regex") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "./javascript_worker", "JavaScriptWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(results) { + session.setAnnotations(results.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/javascript"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_highlight_rules.js b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_highlight_rules.js new file mode 100644 index 00000000..6d6b1294 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_highlight_rules.js @@ -0,0 +1,405 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("ace/lib/oop"); +var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; + +var JavaScriptHighlightRules = function(options) { + // see: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects + var keywordMapper = this.createKeywordMapper({ + "variable.language": + "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors + "Namespace|QName|XML|XMLList|" + // E4X + "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + + "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + + "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors + "SyntaxError|TypeError|URIError|" + + "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions + "isNaN|parseFloat|parseInt|" + + "JSON|Math|" + // Other + "this|arguments|prototype|window|document" , // Pseudo + "keyword": + "const|yield|import|get|set|" + + "break|case|catch|continue|default|delete|do|else|finally|for|function|" + + "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" + + // invalid or reserved + "__parent__|__count__|escape|unescape|with|__proto__|" + + "class|enum|extends|super|export|implements|private|public|interface|package|protected|static", + "storage.type": + "const|let|var|function", + "constant.language": + "null|Infinity|NaN|undefined", + "support.function": + "alert", + "constant.language.boolean": "true|false" + }, "identifier"); + + // keywords which can be followed by regular expressions + var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void"; + + // TODO: Unicode escape sequences + var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; + + var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex + "u[0-9a-fA-F]{4}|" + // unicode + "[0-2][0-7]{0,2}|" + // oct + "3[0-6][0-7]?|" + // oct + "37[0-7]?|" + // oct + "[4-7][0-7]?|" + //oct + ".)"; + + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { + "no_regex" : [ + { + token : "comment", + regex : "\\/\\/", + next : "line_comment" + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : /\/\*/, + next : "comment" + }, { + token : "string", + regex : "'(?=.)", + next : "qstring" + }, { + token : "string", + regex : '"(?=.)', + next : "qqstring" + }, { + token : "constant.numeric", // hex + regex : /0[xX][0-9a-fA-F]+\b/ + }, { + token : "constant.numeric", // float + regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { + // Sound.prototype.play = + token : [ + "storage.type", "punctuation.operator", "support.function", + "punctuation.operator", "entity.name.function", "text","keyword.operator" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", + next: "function_arguments" + }, { + // Sound.play = function() { } + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + // play = function() { } + token : [ + "entity.name.function", "text", "keyword.operator", "text", "storage.type", + "text", "paren.lparen" + ], + regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + // Sound.play = function play() { } + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", + next: "function_arguments" + }, { + // function myFunc(arg) { } + token : [ + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", + next: "function_arguments" + }, { + // foobar: function() { } + token : [ + "entity.name.function", "text", "punctuation.operator", + "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + // : function() { } (this is for issues with 'foo': function() { }) + token : [ + "text", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : "keyword", + regex : "(?:" + kwBeforeRe + ")\\b", + next : "start" + }, { + token : ["punctuation.operator", "support.function"], + regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ + }, { + token : ["punctuation.operator", "support.function.dom"], + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + }, { + token : ["punctuation.operator", "support.constant"], + regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ + }, { + token : ["support.constant"], + regex : /that\b/ + }, { + token : ["storage.type", "punctuation.operator", "support.function.firebug"], + regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/ + }, { + token : keywordMapper, + regex : identifierRe + }, { + token : "keyword.operator", + regex : /--|\+\+|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/, + next : "start" + }, { + token : "punctuation.operator", + regex : /[?:,;.]/, + next : "start" + }, { + token : "paren.lparen", + regex : /[\[({]/, + next : "start" + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token: "comment", + regex: /^#!.*$/ + } + ], + // regular expressions are only allowed after certain tokens. This + // makes sure we don't mix up regexps with the divison operator + "start": [ + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : "\\/\\*", + next : "comment_regex_allowed" + }, { + token : "comment", + regex : "\\/\\/", + next : "line_comment_regex_allowed" + }, { + token: "string.regexp", + regex: "\\/", + next: "regex" + }, { + token : "text", + regex : "\\s+|^$", + next : "start" + }, { + // immediately return to the start mode without matching + // anything + token: "empty", + regex: "", + next: "no_regex" + } + ], + "regex": [ + { + // escapes + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + // flag + token: "string.regexp", + regex: "/[sxngimy]*", + next: "no_regex" + }, { + // invalid operators + token : "invalid", + regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ + }, { + // operators + token : "constant.language.escape", + regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/ + }, { + token : "constant.language.delimiter", + regex: /\|/ + }, { + token: "constant.language.escape", + regex: /\[\^?/, + next: "regex_character_class" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp" + } + ], + "regex_character_class": [ + { + token: "regexp.charclass.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "constant.language.escape", + regex: "]", + next: "regex" + }, { + token: "constant.language.escape", + regex: "-" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp.charachterclass" + } + ], + "function_arguments": [ + { + token: "variable.parameter", + regex: identifierRe + }, { + token: "punctuation.operator", + regex: "[, ]+" + }, { + token: "punctuation.operator", + regex: "$" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "qqstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qqstring" + }, { + token : "string", + regex : '"|$', + next : "no_regex" + }, { + defaultToken: "string" + } + ], + "qstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qstring" + }, { + token : "string", + regex : "'|$", + next : "no_regex" + }, { + defaultToken: "string" + } + ] + }; + + + if (!options || !options.noES6) { + this.$rules.no_regex.unshift({ + regex: "[{}]", onMatch: function(val, state, stack) { + this.next = val == "{" ? this.nextState : ""; + if (val == "{" && stack.length) { + stack.unshift("start", state); + return "paren"; + } + if (val == "}" && stack.length) { + stack.shift(); + this.next = stack.shift(); + if (this.next.indexOf("string") != -1) + return "paren.quasi.end"; + } + return val == "{" ? "paren.lparen" : "paren.rparen"; + }, + nextState: "start" + }, { + token : "string.quasi.start", + regex : /`/, + push : [{ + token : "constant.language.escape", + regex : escapedRe + }, { + token : "paren.quasi.start", + regex : /\${/, + push : "start" + }, { + token : "string.quasi.end", + regex : /`/, + next : "pop" + }, { + defaultToken: "string.quasi" + }] + }); + } + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("no_regex") ]); + + this.normalizeRules(); +}; + +oop.inherits(JavaScriptHighlightRules, TextHighlightRules); + +exports.JavaScriptHighlightRules = JavaScriptHighlightRules; +}); diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_test.js b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_test.js new file mode 100644 index 00000000..b413765a --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_test.js @@ -0,0 +1,213 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); +} + +define(function(require, exports, module) { +"use strict"; + +var EditSession = require("../edit_session").EditSession; +var Tokenizer = require("../tokenizer").Tokenizer; +var JavaScriptMode = require("./javascript").Mode; +var assert = require("../test/assertions"); + +module.exports = { + setUp : function() { + this.mode = new JavaScriptMode(); + }, + + "test: getTokenizer() (smoke test)" : function() { + var tokenizer = this.mode.getTokenizer(); + + assert.ok(tokenizer instanceof Tokenizer); + + var tokens = tokenizer.getLineTokens("'juhu'", "start").tokens; + assert.equal("string", tokens[0].type); + }, + + "test: toggle comment lines should prepend '//' to each line" : function() { + var session = new EditSession([" abc", "cde", "fg"]); + session.setTabSize(1); + + this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal(["// abc", "// cde", "fg"].join("\n"), session.toString()); + }, + + "test: toggle comment on commented lines should remove leading '//' chars" : function() { + var session = new EditSession(["// abc", "//cde", "fg"]); + session.setTabSize(1); + + this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); + }, + + "test: toggle comment on all empty lines" : function() { + var session = new EditSession([" ", " ", " "]); + session.setTabSize(1); + + this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal([" // ", " // ", " "].join("\n"), session.toString()); + }, + + "test: toggle comment with empty lines" : function() { + var session = new EditSession([ + " abc", + "", + " cde", + " fg"]); + + var initial = session.toString(); + this.mode.toggleCommentLines("start", session, 0, 3); + assert.equal([ + " // abc", + "", + " // cde", + " // fg"].join("\n"), + session.toString() + ); + this.mode.toggleCommentLines("start", session, 0, 3); + assert.equal(initial, session.toString()); + }, + + "test: toggle comment lines twice should return the original text" : function() { + var session = new EditSession([" abc", "cde", "fg"]); + + this.mode.toggleCommentLines("start", session, 0, 2); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); + }, + + "test: toggle comment on multiple lines with one commented line prepend '//' to each line" : function() { + var session = new EditSession([" // abc", " //cde", " fg"]); + session.setTabSize(1); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal([" // // abc", " // //cde", " // fg"].join("\n"), session.toString()); + }, + + "test: toggle comment on a comment line with leading white space": function() { + var session = new EditSession(["//cde", " //fg"]); + + this.mode.toggleCommentLines("start", session, 0, 1); + assert.equal(["cde", " fg"].join("\n"), session.toString()); + }, + + "test: toggle comment lines should take tabsize into account" : function() { + var session = new EditSession([" // abc", " // cde", "// fg"]); + session.setTabSize(2); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal([" abc", " cde", " fg"].join("\n"), session.toString()); + session.setTabSize(4); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal(["// abc", "// cde", "// fg"].join("\n"), session.toString()); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal([" abc", " cde", " fg"].join("\n"), session.toString()); + + session.insert({row: 0, column: 0}, " "); + this.mode.toggleCommentLines("start", session, 0, 2); + assert.equal(["// abc", "// cde", "// fg"].join("\n"), session.toString()); + }, + //there doesn't seem to be any way to make this work + "!test: togglecomment on line with one space" : function() { + var session = new EditSession([" abc", " // cde", "// fg"]); + var initialValue = session + ""; + session.setTabSize(4); + this.mode.toggleCommentLines("start", session, 0, 0); + this.mode.toggleCommentLines("start", session, 0, 0); + assert.equal(initialValue, session.toString()); + }, + + "test: auto indent after opening brace" : function() { + assert.equal(" ", this.mode.getNextLineIndent("start", "if () {", " ")); + }, + + "test: auto indent after case" : function() { + assert.equal(" ", this.mode.getNextLineIndent("start", "case 'juhu':", " ")); + }, + + "test: no auto indent in object literal" : function() { + assert.equal("", this.mode.getNextLineIndent("start", "{ 'juhu':", " ")); + }, + + "test: no auto indent after opening brace in multi line comment" : function() { + assert.equal("", this.mode.getNextLineIndent("start", "/*if () {", " ")); + assert.equal(" ", this.mode.getNextLineIndent("comment", " abcd", " ")); + }, + + "test: no auto indent after opening brace in single line comment" : function() { + assert.equal("", this.mode.getNextLineIndent("start", "//if () {", " ")); + assert.equal(" ", this.mode.getNextLineIndent("start", " //if () {", " ")); + }, + + "test: no auto indent should add to existing indent" : function() { + assert.equal(" ", this.mode.getNextLineIndent("start", " if () {", " ")); + assert.equal(" ", this.mode.getNextLineIndent("start", " cde", " ")); + assert.equal(" ", this.mode.getNextLineIndent("start", "function foo(items) {", " ")); + }, + + "test: special indent in doc comments" : function() { + assert.equal(" * ", this.mode.getNextLineIndent("doc-start", "/**", " ")); + assert.equal(" * ", this.mode.getNextLineIndent("doc-start", " /**", " ")); + assert.equal(" * ", this.mode.getNextLineIndent("doc-start", " *", " ")); + assert.equal(" * ", this.mode.getNextLineIndent("doc-start", " *", " ")); + assert.equal(" ", this.mode.getNextLineIndent("doc-start", " abc", " ")); + }, + + "test: no indent after doc comments" : function() { + assert.equal("", this.mode.getNextLineIndent("doc-start", " */", " ")); + }, + + "test: trigger outdent if line is space and new text starts with closing brace" : function() { + assert.ok(this.mode.checkOutdent("start", " ", " }")); + assert.ok(!this.mode.checkOutdent("start", " a ", " }")); + assert.ok(!this.mode.checkOutdent("start", "", "}")); + assert.ok(!this.mode.checkOutdent("start", " ", "a }")); + assert.ok(!this.mode.checkOutdent("start", " }", "}")); + }, + + "test: auto outdent should indent the line with the same indent as the line with the matching opening brace" : function() { + var session = new EditSession([" function foo() {", " bla", " }"], new JavaScriptMode()); + this.mode.autoOutdent("start", session, 2); + assert.equal(" }", session.getLine(2)); + }, + + "test: no auto outdent if no matching brace is found" : function() { + var session = new EditSession([" function foo()", " bla", " }"]); + this.mode.autoOutdent("start", session, 2); + assert.equal(" }", session.getLine(2)); + } +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec() +} diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker.js b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker.js new file mode 100644 index 00000000..fd5788e7 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker.js @@ -0,0 +1,185 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var Mirror = require("../worker/mirror").Mirror; +var lint = require("./javascript/jshint").JSHINT; + +function startRegex(arr) { + return RegExp("^(" + arr.join("|") + ")"); +} + +var disabledWarningsRe = startRegex([ + "Bad for in variable '(.+)'.", + 'Missing "use strict"' +]); +var errorsRe = startRegex([ + "Unexpected", + "Expected ", + "Confusing (plus|minus)", + "\\{a\\} unterminated regular expression", + "Unclosed ", + "Unmatched ", + "Unbegun comment", + "Bad invocation", + "Missing space after", + "Missing operator at" +]); +var infoRe = startRegex([ + "Expected an assignment", + "Bad escapement of EOL", + "Unexpected comma", + "Unexpected space", + "Missing radix parameter.", + "A leading decimal point can", + "\\['{a}'\\] is better written in dot notation.", + "'{a}' used out of scope" +]); + +var JavaScriptWorker = exports.JavaScriptWorker = function(sender) { + Mirror.call(this, sender); + this.setTimeout(500); + this.setOptions(); +}; + +oop.inherits(JavaScriptWorker, Mirror); + +(function() { + this.setOptions = function(options) { + this.options = options || { + // undef: true, + // unused: true, + esnext: true, + moz: true, + devel: true, + browser: true, + node: true, + laxcomma: true, + laxbreak: true, + lastsemic: true, + onevar: false, + passfail: false, + maxerr: 100, + expr: true, + multistr: true, + globalstrict: true + }; + this.doc.getValue() && this.deferredUpdate.schedule(100); + }; + + this.changeOptions = function(newOptions) { + oop.mixin(this.options, newOptions); + this.doc.getValue() && this.deferredUpdate.schedule(100); + }; + + this.isValidJS = function(str) { + try { + // evaluated code can only create variables in this function + eval("throw 0;" + str); + } catch(e) { + if (e === 0) + return true; + } + return false + }; + + this.onUpdate = function() { + var value = this.doc.getValue(); + value = value.replace(/^#!.*\n/, "\n"); + if (!value) + return this.sender.emit("annotate", []); + + var errors = []; + // jshint reports many false errors + // report them as error only if code is actually invalid + var maxErrorLevel = this.isValidJS(value) ? "warning" : "error"; + + // var start = new Date(); + lint(value, this.options); + var results = lint.errors; + + var errorAdded = false + for (var i = 0; i < results.length; i++) { + var error = results[i]; + if (!error) + continue; + var raw = error.raw; + var type = "warning"; + + if (raw == "Missing semicolon.") { + var str = error.evidence.substr(error.character); + str = str.charAt(str.search(/\S/)); + if (maxErrorLevel == "error" && str && /[\w\d{(['"]/.test(str)) { + error.reason = 'Missing ";" before statement'; + type = "error"; + } else { + type = "info"; + } + } + else if (disabledWarningsRe.test(raw)) { + continue; + } + else if (infoRe.test(raw)) { + type = "info" + } + else if (errorsRe.test(raw)) { + errorAdded = true; + type = maxErrorLevel; + } + else if (raw == "'{a}' is not defined.") { + type = "warning"; + } + else if (raw == "'{a}' is defined but never used.") { + type = "info"; + } + + errors.push({ + row: error.line-1, + column: error.character-1, + text: error.reason, + type: type, + raw: raw + }); + + if (errorAdded) { + // break; + } + } + // console.log("lint time: " + (new Date() - start)); + + this.sender.emit("annotate", errors); + }; + +}).call(JavaScriptWorker.prototype); + +}); diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker_test.js b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker_test.js new file mode 100644 index 00000000..5d61fc89 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/modes/javascript_worker_test.js @@ -0,0 +1,106 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); +} + +define(function(require, exports, module) { +"use strict"; + +var assert = require("../test/assertions"); +var JavaScriptWorker = require("./javascript_worker").JavaScriptWorker; + + +module.exports = { + setUp : function() { + this.sender = { + on: function() {}, + callback: function(data, id) { + this.data = data; + }, + events: [], + emit: function(type, e) { + this.events.push([type, e]); + } + }; + }, + + "test check for syntax error": function() { + var worker = new JavaScriptWorker(this.sender); + worker.setValue("Juhu Kinners"); + worker.deferredUpdate.call(); + + var error = this.sender.events[0][1][0]; + assert.equal(error.text, 'Missing ";" before statement'); + assert.equal(error.type, "error"); + assert.equal(error.row, 0); + assert.equal(error.column, 4); + }, + + "test invalid multi line string": function() { + var worker = new JavaScriptWorker(this.sender); + worker.setValue('"a\n\\nn"'); + worker.deferredUpdate.call(); + + var error = this.sender.events[0][1][0]; + assert.equal(error.text, "Unclosed string."); + assert.equal(error.type, "error"); + assert.equal(error.row, 0); + assert.equal(error.column, 2); + }, + + "test another invalid string": function() { + var worker = new JavaScriptWorker(this.sender); + worker.setValue("if('"); + worker.deferredUpdate.call(); + + var error = this.sender.events[0][1][0]; + assert.equal(error.text, "Unclosed string."); + assert.equal(error.type, "error"); + assert.equal(error.row, 0); + assert.equal(error.column, 4); + }, + + "test for each": function() { + var worker = new JavaScriptWorker(this.sender); + worker.setValue("for each(var i in x)"); + worker.deferredUpdate.call(); + + var error = this.sender.events[0][1][0]; + assert.equal(error.text, "Unexpected early end of program."); + } +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec(); +} diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/outline/python.outline b/plugins/c9.ide.plugins/mock/c9.ide.example3/outline/python.outline new file mode 100644 index 00000000..92672fd6 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/outline/python.outline @@ -0,0 +1,20 @@ +{ + languages: ["py"], + extensions: ["py"], + + guess_fargs: true, + extract_docs: true, + + tags: [ + { regex: /(?:^|\n)\s*class\s+([^ \(:]+)/g, kind: "package" }, + { regex: /(?:^|\n)\s*def\s+(?!_)([^ \(:]+)/g, kind: "method" }, + { regex: /(?:^|\n)\s*def\s+(?!__[^ \(:]+__)(_[^ \(]*)/g, kind: "method2" }, + { regex: /(?:^|\n)\s*def\s+(__[^ \(:]+__)/g, kind: "property" }, + { + regex: new RegExp( + "(?:^|\\n)\\s*import\\s+([^ \\(]+)" + ), + kind: "import" + } + ] +} \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/package.json b/plugins/c9.ide.plugins/mock/c9.ide.example3/package.json new file mode 100644 index 00000000..324c2714 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/package.json @@ -0,0 +1,22 @@ +{ + "name": "c9.ide.example3", + "description": "Cloud9 Custom Example Plguin", + "version": "1.3.0", + "author": "Ajax.org B.V. ", + "contributors": [ + { + "name": "Ruben Daniels", + "email": "ruben@c9.io" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/c9/newclient.git" + }, + "plugins": {}, + "installer": "install.js", + "categories": [ + "misc" + ], + "licenses": [] +} \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/runners/example.run b/plugins/c9.ide.plugins/mock/c9.ide.example3/runners/example.run new file mode 100644 index 00000000..b1bbae70 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/runners/example.run @@ -0,0 +1,8 @@ +// Create a custom Cloud9 runner - similar to the Sublime build system +// For more information see https://docs.c9.io/custom_runners.html +{ + "cmd" : ["ls", "$file", "$args"], + "info" : "Started $project_path$file_name", + "env" : {}, + "selector" : "source.ext" +} \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/snippets/mako.snippets b/plugins/c9.ide.plugins/mock/c9.ide.example3/snippets/mako.snippets new file mode 100644 index 00000000..c9c7b698 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/snippets/mako.snippets @@ -0,0 +1,56 @@ +# scope: mako; include: html, javascript + +snippet def + <%def name="${1:name}"> + ${2:} + +snippet call + <%call expr="${1:name}"> + ${2:} + +snippet doc + <%doc> + ${1:} + +snippet text + <%text> + ${1:} + +snippet for + % for ${1:i} in ${2:iter}: + ${3:} + % endfor +snippet if if + % if ${1:condition}: + ${2:} + % endif +snippet if if/else + % if ${1:condition}: + ${2:} + % else: + ${3:} + % endif +snippet try + % try: + ${1:} + % except${2:}: + ${3:pass} + % endtry +snippet wh + % while ${1:}: + ${2:} + % endwhile +snippet $ + ${ ${1:} } +snippet <% + <% ${1:} %> +snippet +snippet inherit + <%inherit file="${1:filename}" /> +snippet include + <%include file="${1:filename}" /> +snippet namespace + <%namespace file="${1:name}" /> +snippet page + <%page args="${1:}" /> diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/templates/example.templates b/plugins/c9.ide.plugins/mock/c9.ide.example3/templates/example.templates new file mode 100644 index 00000000..65246099 --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/templates/example.templates @@ -0,0 +1,98 @@ +# Cloud9 Plugin +filename plugin.js +caption Cloud9 Plugin +section General + define(function(require, exports, module) { + main.consumes = [ + "Plugin", "ui", "layout", "commands" + ]; + main.provides = ["myplugin"]; + return main; + + function main(options, imports, register) { + var Plugin = imports.Plugin; + var ui = imports.ui; + var commands = imports.commands; + var layout = imports.layout; + + /***** Initialization *****/ + + var plugin = new Plugin("Ajax.org", main.consumes); + var emit = plugin.getEmitter(); + + function load() { + commands.addCommand({ + name: "mycommand", + bindKey: { mac: "Command-I", win: "Ctrl-I" }, + exec: function() { + show(); + } + }, plugin); + } + + var drawn = false; + function draw() { + if (drawn) return; + drawn = true; + + // Import Skin + ui.insertSkin({ + name: "c9statusbar", + data: require("text!./skin.xml"), + "media-path" : options.staticPrefix + "/images/", + "icon-path" : options.staticPrefix + "/icons/" + }, plugin); + + // Create UI elements + var markup = require("text!./markup.xml"); + ui.insertMarkup(layout.findParent(plugin), markup, plugin); + + // Insert CSS + ui.insertCss(require("text!./style.css"), plugin); + + emit("draw"); + } + + /***** Methods *****/ + + function show() { + draw(); + } + + /***** Lifecycle *****/ + + plugin.on("load", function() { + load(); + }); + plugin.on("unload", function() { + drawn = false; + }); + + /***** Register and define API *****/ + + /** + * This is an example of an implementation of a plugin. + * + * @class Template + * @extends Plugin + * @singleton + */ + plugin.freezePublicAPI({ + /** + * + */ + show: show, + + _events: [ + /** + * @event draw + */ + "draw" + ] + }); + + register(null, { + myplugin: plugin + }); + } + }); \ No newline at end of file diff --git a/plugins/c9.ide.plugins/mock/c9.ide.example3/themes/cloud9_day.css b/plugins/c9.ide.plugins/mock/c9.ide.example3/themes/cloud9_day.css new file mode 100644 index 00000000..5bb7c66a --- /dev/null +++ b/plugins/c9.ide.plugins/mock/c9.ide.example3/themes/cloud9_day.css @@ -0,0 +1,157 @@ +/* name: Cloud9 Day; isDark: false; cssClass: ace-cloud9-day; */ + +.ace-cloud9-day .ace_gutter { + background: #ECECEC; + color: #333; +} + +.ace-cloud9-day .ace_print-margin { + width: 1px; + background: #e8e8e8; +} + +.ace-cloud9-day .ace_fold { + background-color: #6B72E6; +} + +.ace-cloud9-day { + background-color: #FBFBFB; + color: black; +} + +.ace-cloud9-day .ace_cursor { + color: black; +} + +.ace-cloud9-day .ace_invisible { + color: rgb(191, 191, 191); +} + +.ace-cloud9-day .ace_storage, +.ace-cloud9-day .ace_keyword { + color: rgb(24, 122, 234); +} + +.ace-cloud9-day .ace_constant { + color: rgb(197, 6, 11); +} + +.ace-cloud9-day .ace_constant.ace_buildin { + color: rgb(88, 72, 246); +} + +.ace-cloud9-day .ace_constant.ace_language { + color: rgb(88, 92, 246); +} + +.ace-cloud9-day .ace_constant.ace_library { + color: rgb(6, 150, 14); +} + +.ace-cloud9-day .ace_invalid { + background-color: rgba(255, 0, 0, 0.1); + color: red; +} + +.ace-cloud9-day .ace_support.ace_function { + color: rgb(60, 76, 114); +} + +.ace-cloud9-day .ace_support.ace_constant { + color: rgb(6, 150, 14); +} + +.ace-cloud9-day .ace_support.ace_type, +.ace-cloud9-day .ace_support.ace_class { + color: rgb(109, 121, 222); +} + +.ace-cloud9-day .ace_keyword.ace_operator { + color: rgb(104, 118, 135); +} + +.ace-cloud9-day .ace_string { + color: rgb(3, 106, 7); +} + +.ace-cloud9-day .ace_comment { + color: rgb(76, 136, 107); +} + +.ace-cloud9-day .ace_comment.ace_doc { + color: rgb(0, 102, 255); +} + +.ace-cloud9-day .ace_comment.ace_doc.ace_tag { + color: rgb(128, 159, 191); +} + +.ace-cloud9-day .ace_constant.ace_numeric { + color: rgb(0, 0, 205); +} + +.ace-cloud9-day .ace_variable { + color: rgb(49, 132, 149); +} + +.ace-cloud9-day .ace_xml-pe { + color: rgb(104, 104, 91); +} + +.ace-cloud9-day .ace_entity.ace_name.ace_function { + color: #0000A2; +} + + +.ace-cloud9-day .ace_heading { + color: rgb(12, 7, 255); +} + +.ace-cloud9-day .ace_list { + color:rgb(185, 6, 144); +} + +.ace-cloud9-day .ace_meta.ace_tag { + color:rgb(0, 22, 142); +} + +.ace-cloud9-day .ace_string.ace_regex { + color: rgb(255, 0, 0) +} + +.ace-cloud9-day .ace_marker-layer .ace_selection { + background: rgb(181, 213, 255); +} +.ace-cloud9-day.ace_multiselect .ace_selection.ace_start { + box-shadow: 0 0 3px 0px white; + border-radius: 2px; +} +.ace-cloud9-day .ace_marker-layer .ace_step { + background: rgb(247, 237, 137); +} + +.ace-cloud9-day .ace_marker-layer .ace_stack { + background: #BAE0A0; +} + +.ace-cloud9-day .ace_marker-layer .ace_bracket { + margin: -1px 0 0 -1px; + border: 1px solid rgb(192, 192, 192); +} + +.ace-cloud9-day .ace_marker-layer .ace_active-line { + background: rgba(0, 0, 0, 0.07); +} + +.ace-cloud9-day .ace_gutter-active-line { + background-color : #E5E5E5; +} + +.ace-cloud9-day .ace_marker-layer .ace_selected-word { + background: rgb(250, 250, 255); + border: 1px solid rgb(200, 200, 250); +} + +.ace-cloud9-day .ace_indent-guide { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y; +} diff --git a/plugins/c9.ide.preferences/preferencepanel.js b/plugins/c9.ide.preferences/preferencepanel.js index 66acbaa4..d6917fd1 100644 --- a/plugins/c9.ide.preferences/preferencepanel.js +++ b/plugins/c9.ide.preferences/preferencepanel.js @@ -352,6 +352,13 @@ define(function(require, module, exports) { */ get form(){ return form }, + /** + * Whether this panel is active + * @property {Boolean} active + * @readonly + */ + get active(){ return amlBar.visible; }, + _events: [ /** * Fired when the panel container is drawn. @@ -361,7 +368,19 @@ define(function(require, module, exports) { * @param {AMLElement} e.aml The aml container. * @param {AMLElement} e.navHtml The html element that represents the navigation. */ - "draw" + "draw", + /** + * @event activate + */ + "activate", + /** + * @event deactivate + */ + "deactivate", + /** + * @event resize + */ + "resize" ], /** diff --git a/plugins/c9.ide.terminal/aceterm/aceterm.js b/plugins/c9.ide.terminal/aceterm/aceterm.js index 333bc28b..8462648c 100644 --- a/plugins/c9.ide.terminal/aceterm/aceterm.js +++ b/plugins/c9.ide.terminal/aceterm/aceterm.js @@ -518,7 +518,7 @@ define(function(require, exports, module) { flags = data >> 18; if (flags & 1) { - if (this.allowBoldFonts) + if (this.$fontMetrics.allowBoldFonts) out += 'font-weight:bold;'; // see: XTerm*boldColors if (fgColor < 8) diff --git a/plugins/c9.ide.terminal/link_handler.js b/plugins/c9.ide.terminal/link_handler.js index 4569d8b0..9435a794 100644 --- a/plugins/c9.ide.terminal/link_handler.js +++ b/plugins/c9.ide.terminal/link_handler.js @@ -232,14 +232,18 @@ define(function(require, exports, module) { abs = true; } - if (path.lastIndexOf(VFSROOT, 0) === 0) { + if (path.toLowerCase().lastIndexOf(VFSROOT.toLowerCase(), 0) === 0) { path = path.substr(VFSROOT.length); abs = false; } + else if (path.toLowerCase().lastIndexOf(c9.home.toLowerCase(), 0) === 0) { + path = c9.home + "/" + path.substr(c9.home.length); + abs = true; + } else abs = true; - if (path[0] != "/") + if (path[0] != "/" && !abs) path = "/" + path; return { diff --git a/plugins/c9.ide.ui/forms.js b/plugins/c9.ide.ui/forms.js index 354a32cf..20503017 100644 --- a/plugins/c9.ide.ui/forms.js +++ b/plugins/c9.ide.ui/forms.js @@ -21,6 +21,7 @@ define(function(require, exports, module) { var maxwidth = options.colmaxwidth || 300; var widths = options.widths || {}; var skins = options.skins || {}; + var elements = {}; var container, meta = {}; var debug = location.href.indexOf('menus=1') > -1; @@ -388,8 +389,10 @@ define(function(require, exports, module) { }); } - if (options.name) + if (options.name) { node.setAttribute("id", options.name); + elements[node.name] = node; + } ui.insertByIndex(heading.container, node, position, foreign); @@ -400,7 +403,7 @@ define(function(require, exports, module) { function update(items) { items.forEach(function(item) { - var el = plugin.getElement(item.id); + var el = elements[item.id]; switch (el.type) { case "dropdown": var dropdown = el.lastChild; @@ -409,10 +412,17 @@ define(function(require, exports, module) { return ""; }).join(""); - if (data) - dropdown.$model.load("" + data + ""); - if (item.value) - dropdown.setAttribute("value", item.value); + if (data) { + setTimeout(function(){ + dropdown.$model.load("" + data + ""); + + setTimeout(function(){ + var value = item.value || dropdown.value; + dropdown.value = -999; + dropdown.setAttribute("value", value); + }); + }); + } break; default: if ("value" in item) diff --git a/plugins/c9.vfs.standalone/standalone.js b/plugins/c9.vfs.standalone/standalone.js index 44dbb35c..83ddbf60 100644 --- a/plugins/c9.vfs.standalone/standalone.js +++ b/plugins/c9.vfs.standalone/standalone.js @@ -34,6 +34,11 @@ function plugin(options, imports, register) { mount: "/" }]); + statics.addStatics([{ + path: __dirname + "/../../node_modules/architect-build/build_support", + mount: "/" + }]); + statics.addStatics([{ path: __dirname + "/../../configs", mount: "/configs" @@ -101,8 +106,7 @@ function plugin(options, imports, register) { var cdn = options.options.cdn; options.options.themePrefix = "/static/" + cdn.version + "/skin/" + configName; options.options.workerPrefix = "/static/" + cdn.version + "/worker"; - if (req.params.packed == 1) - options.options.CORSWorkerPrefix = "/static/" + cdn.version + "/worker"; + options.options.CORSWorkerPrefix = req.params.packed ? "/static/" + cdn.version + "/worker" : ""; var collab = options.collab && req.params.collab !== 0 && req.params.nocollab != 1; var opts = extend({}, options); @@ -115,7 +119,7 @@ function plugin(options, imports, register) { token: req.params.token }); - opts.options.debug = req.params.debug; + opts.options.debug = req.params.debug == 1; res.setHeader("Cache-Control", "no-cache, no-store"); res.render(__dirname + "/views/standalone.html.ejs", { architectConfig: getConfig(configType, opts), diff --git a/plugins/c9.vfs.standalone/views/standalone.html.ejs b/plugins/c9.vfs.standalone/views/standalone.html.ejs index 47426afe..c1162d09 100644 --- a/plugins/c9.vfs.standalone/views/standalone.html.ejs +++ b/plugins/c9.vfs.standalone/views/standalone.html.ejs @@ -53,7 +53,7 @@ <% if (packed) { %> <% } else { %> - + <% } %>