kopia lustrzana https://github.com/c9/core
Merge remote-tracking branch 'origin/master' into api-ide-profile-add-sshprvkey
commit
747e923550
|
@ -0,0 +1,5 @@
|
|||
This product includes software developed by:
|
||||
|
||||
The `appendFile` functionality in `node_modules/vfs-local` is open source
|
||||
software, developed by Andrew Faulring, copyright (c) 2016 Carnegie Mellon University
|
||||
and licensed under the MIT license.
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = function(options) {
|
||||
var plugins = require("./client-default")(options);
|
||||
|
||||
// TODO: cleanup unneeded plugins?
|
||||
var includes = [];
|
||||
var excludes = {};
|
||||
|
||||
plugins.forEach(function(p) {
|
||||
if (p.packagePath && p.packagePath.indexOf("c9.core/settings") >= 0) {
|
||||
p.settings = "defaults";
|
||||
p.template = {
|
||||
user: {},
|
||||
project: {},
|
||||
state: {
|
||||
console: {
|
||||
"@maximized": true,
|
||||
type: "pane",
|
||||
nodes: []
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (p.packagePath == "plugins/c9.ide.console/console") {
|
||||
p.defaultState = {
|
||||
type: "pane",
|
||||
nodes: [{
|
||||
type: "tab",
|
||||
editorType: "terminal",
|
||||
active: "true"
|
||||
}]
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
plugins = plugins
|
||||
.concat(includes)
|
||||
.filter(function (p) {
|
||||
return !excludes[p] && !excludes[p.packagePath];
|
||||
});
|
||||
|
||||
return plugins;
|
||||
};
|
||||
|
|
@ -563,19 +563,6 @@ module.exports = function(options) {
|
|||
realRoot: true,
|
||||
home: options.local ? options.home : "~"
|
||||
},
|
||||
"plugins/c9.ide.mount/mount",
|
||||
{
|
||||
packagePath: "plugins/c9.ide.mount/ftp",
|
||||
curlftpfsBin: options.mount.curlftpfsBin,
|
||||
fusermountBin: options.mount.fusermountBin,
|
||||
ssh: options.ssh
|
||||
},
|
||||
{
|
||||
packagePath: "plugins/c9.ide.mount/sftp",
|
||||
sshfsBin: options.mount.sshfsBin,
|
||||
fusermountBin: options.mount.fusermountBin,
|
||||
ssh: options.ssh
|
||||
},
|
||||
{
|
||||
packagePath: "plugins/c9.ide.upload/dragdrop",
|
||||
treeAsPane: options.local
|
||||
|
|
|
@ -100,12 +100,12 @@ module.exports = function(config, optimist) {
|
|||
console.log("and suppress this message.\n");
|
||||
host = config.host = "127.0.0.1";
|
||||
}
|
||||
if (/:/.test(argv.auth) && !isLocalhost && !process.env.C9_HOSTNAME) {
|
||||
var auth = (argv.auth + "").split(":");
|
||||
if (!auth[1] && !isLocalhost && !process.env.C9_HOSTNAME) {
|
||||
console.log("Warning: running Cloud9 without using HTTP authentication.");
|
||||
console.log("Run using --listen localhost instead to only expose Cloud9 to localhost,");
|
||||
console.log("or use -a username:password to setup HTTP authentication\n");
|
||||
}
|
||||
var auth = (argv.auth + "").split(":");
|
||||
|
||||
var plugins = [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
module.exports = function(options, optimist) {
|
||||
var config = require("./standalone")(options, optimist);
|
||||
|
||||
// TODO: cleanup unneeded plugins?
|
||||
|
||||
options.client_config = "default-terminal";
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
if (!module.parent) require("../server")([__filename].concat(process.argv.slice(2)));
|
|
@ -2,13 +2,34 @@
|
|||
set -e
|
||||
cd `dirname $0`/..
|
||||
|
||||
# set -x
|
||||
NAME=$1
|
||||
URL=$2
|
||||
shift
|
||||
BRANCH=
|
||||
URL=
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
-b=*|--branch=*)
|
||||
BRANCH="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
-u=*|--url=*)
|
||||
URL="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$NAME" == "" ]; then
|
||||
echo "add name [url]"
|
||||
echo "add name [--url=git@github.com:c9/NAME.git] [--branch=master]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo adding name=$NAME url=$URL branch=refs/remotes/origin/$BRANCH
|
||||
|
||||
if [ "$URL" == "" ]; then
|
||||
URL=git@github.com:c9/$NAME.git
|
||||
fi
|
||||
|
@ -28,7 +49,7 @@ else
|
|||
fi
|
||||
|
||||
pushd $NAME
|
||||
HASH=$(git rev-parse --revs-only refs/remotes/origin/master)
|
||||
HASH=$(git rev-parse --revs-only refs/remotes/origin/$BRANCH)
|
||||
popd
|
||||
|
||||
[ -f ./config.json ] || echo "{}" > ./config.json
|
||||
|
|
|
@ -75,19 +75,20 @@ var supportedModes = {
|
|||
Elixir: ["ex|exs"],
|
||||
Elm: ["elm"],
|
||||
Erlang: ["erl|hrl"],
|
||||
Forth: ["frt|fs|ldr"],
|
||||
Forth: ["frt|fs|ldr|fth|4th"],
|
||||
Fortran: ["f|f90"],
|
||||
FTL: ["ftl"],
|
||||
Gcode: ["gcode"],
|
||||
Gherkin: ["feature"],
|
||||
Gitignore: ["^.gitignore"],
|
||||
Glsl: ["glsl|frag|vert"],
|
||||
Gobstones: ["gbs"],
|
||||
Gobstones: ["gbs"],
|
||||
golang: ["go"],
|
||||
Groovy: ["groovy"],
|
||||
HAML: ["haml"],
|
||||
Handlebars: ["hbs|handlebars|tpl|mustache"],
|
||||
Haskell: ["hs"],
|
||||
Haskell_Cabal: ["cabal"],
|
||||
haXe: ["hx"],
|
||||
HTML: ["html|htm|xhtml"],
|
||||
HTML_Elixir: ["eex|html.eex"],
|
||||
|
@ -104,7 +105,6 @@ var supportedModes = {
|
|||
JSX: ["jsx"],
|
||||
Julia: ["jl"],
|
||||
LaTeX: ["tex|latex|ltx|bib"],
|
||||
Lean: ["lean|hlean"],
|
||||
LESS: ["less"],
|
||||
Liquid: ["liquid"],
|
||||
Lisp: ["lisp"],
|
||||
|
@ -206,4 +206,5 @@ module.exports = {
|
|||
modesByName: modesByName
|
||||
};
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -4993,7 +4993,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
}
|
||||
}
|
||||
throw Error('No such mapping.');
|
||||
// throw Error('No such mapping.');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ function testVim(name, run, opts, expectedFail) {
|
|||
// Record for insert mode.
|
||||
if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') {
|
||||
var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
|
||||
if (lastChange) {
|
||||
if (lastChange && (key.indexOf('Delete') != -1 || key.indexOf('Backspace') != -1)) {
|
||||
lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
|
||||
}
|
||||
}
|
||||
|
@ -2905,6 +2905,14 @@ testVim('._insert', function(cm, vim, helpers) {
|
|||
helpers.doKeys('.');
|
||||
eq('testestt', cm.getValue());
|
||||
helpers.assertCursorAt(0, 6);
|
||||
helpers.doKeys('O');
|
||||
cm.replaceRange('xyz', cm.getCursor());
|
||||
helpers.doInsertModeKeys('Backspace');
|
||||
helpers.doInsertModeKeys('Down');
|
||||
helpers.doKeys('<Esc>');
|
||||
helpers.doKeys('.');
|
||||
eq('xy\nxy\ntestestt', cm.getValue());
|
||||
helpers.assertCursorAt(1, 1);
|
||||
}, { value: ''});
|
||||
testVim('._insert_repeat', function(cm, vim, helpers) {
|
||||
helpers.doKeys('i');
|
||||
|
|
|
@ -94,7 +94,9 @@
|
|||
["keyword.operator","-"],
|
||||
["identifier","o"],
|
||||
["text"," "],
|
||||
["string","\"git@github.com:[^ ]*\""],
|
||||
["string.start","\""],
|
||||
["string","git@github.com:[^ ]*"],
|
||||
["string.end","\""],
|
||||
["keyword.operator","`"],
|
||||
["punctuation.operator",";"],
|
||||
["text"," "],
|
||||
|
@ -113,12 +115,16 @@
|
|||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s/^git@github\\.com://\""],
|
||||
["string.start","\""],
|
||||
["string","s/^git@github\\.com://"],
|
||||
["string.end","\""],
|
||||
["text"," "],
|
||||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s/\\.git$//\""]
|
||||
["string.start","\""],
|
||||
["string","s/\\.git$//"],
|
||||
["string.end","\""]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
|
@ -150,7 +156,9 @@
|
|||
["keyword.operator","-"],
|
||||
["identifier","o"],
|
||||
["text"," "],
|
||||
["string","\"https?://([^@]*@)?github.com/[^ ]*\\.git\""],
|
||||
["string.start","\""],
|
||||
["string","https?://([^@]*@)?github.com/[^ ]*\\.git"],
|
||||
["string.end","\""],
|
||||
["keyword.operator","`"],
|
||||
["punctuation.operator",";"],
|
||||
["text"," "],
|
||||
|
@ -169,17 +177,23 @@
|
|||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s|^https?://||\""],
|
||||
["string.start","\""],
|
||||
["string","s|^https?://||"],
|
||||
["string.end","\""],
|
||||
["text"," "],
|
||||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s/^.*github\\.com\\///\""],
|
||||
["string.start","\""],
|
||||
["string","s/^.*github\\.com\\///"],
|
||||
["string.end","\""],
|
||||
["text"," "],
|
||||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s/\\.git$//\""]
|
||||
["string.start","\""],
|
||||
["string","s/\\.git$//"],
|
||||
["string.end","\""]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
|
@ -211,7 +225,9 @@
|
|||
["keyword.operator","-"],
|
||||
["identifier","o"],
|
||||
["text"," "],
|
||||
["string","\"git://github.com/[^ ]*\\.git\""],
|
||||
["string.start","\""],
|
||||
["string","git://github.com/[^ ]*\\.git"],
|
||||
["string.end","\""],
|
||||
["keyword.operator","`"],
|
||||
["punctuation.operator",";"],
|
||||
["text"," "],
|
||||
|
@ -230,12 +246,16 @@
|
|||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s|^git://github.com/||\""],
|
||||
["string.start","\""],
|
||||
["string","s|^git://github.com/||"],
|
||||
["string.end","\""],
|
||||
["text"," "],
|
||||
["keyword.operator","-"],
|
||||
["identifier","e"],
|
||||
["text"," "],
|
||||
["string","\"s/\\.git$//\""]
|
||||
["string.start","\""],
|
||||
["string","s/\\.git$//"],
|
||||
["string.end","\""]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
|
@ -275,7 +295,9 @@
|
|||
["text"," "],
|
||||
["support.function.builtin","echo"],
|
||||
["text"," "],
|
||||
["string","\"Couldn't find a valid remote\""],
|
||||
["string.start","\""],
|
||||
["string","Couldn't find a valid remote"],
|
||||
["string.end","\""],
|
||||
["text"," "],
|
||||
["keyword.operator",">"],
|
||||
["support.function","&2"]
|
||||
|
@ -344,7 +366,8 @@
|
|||
["text"," "],
|
||||
["support.function.builtin","echo"],
|
||||
["text"," "],
|
||||
["string","\"http://github.com/"],
|
||||
["string.start","\""],
|
||||
["string","http://github.com/"],
|
||||
["variable","$repo"],
|
||||
["string","/pull/new/"],
|
||||
["variable","$"],
|
||||
|
@ -356,7 +379,7 @@
|
|||
["identifier","heads"],
|
||||
["keyword.operator","/"],
|
||||
["paren.rparen","}"],
|
||||
["string","\""]
|
||||
["string.end","\""]
|
||||
],[
|
||||
"start",
|
||||
["keyword","else"]
|
||||
|
|
|
@ -77,9 +77,8 @@
|
|||
],[
|
||||
"start",
|
||||
["text"," x="],
|
||||
["keyword","\\left\\"],
|
||||
["paren.keyword.operator","{"],
|
||||
["text"," "],
|
||||
["keyword","\\left"],
|
||||
["text", "\\{ "],
|
||||
["keyword","\\begin"],
|
||||
["paren.keyword.operator","{"],
|
||||
["nospell.text","array"],
|
||||
|
@ -127,4 +126,4 @@
|
|||
["paren.keyword.operator","{"],
|
||||
["nospell.text","equation"],
|
||||
["paren.keyword.operator","}"]
|
||||
]]
|
||||
]]
|
||||
|
|
|
@ -100,14 +100,18 @@
|
|||
["string","'button'"],
|
||||
["paren.rparen",")"]
|
||||
],[
|
||||
"no_regex",
|
||||
"start",
|
||||
["identifier","button"],
|
||||
["punctuation.operator","."],
|
||||
["identifier","innerText"],
|
||||
["text"," "],
|
||||
["keyword.operator","="],
|
||||
["text"," "],
|
||||
["string","\"Say Hello\""]
|
||||
["keyword.operator","<"],
|
||||
["storage.type.variable.ts","string"],
|
||||
["keyword.operator",">"],
|
||||
["string","\"Say Hello\""],
|
||||
["punctuation.operator",";"]
|
||||
],[
|
||||
"start",
|
||||
["storage.type","button"],
|
||||
|
|
|
@ -69,7 +69,7 @@ var c_cppHighlightRules = function() {
|
|||
next : "comment"
|
||||
}, {
|
||||
token : "string", // character
|
||||
regex : "'(?:" + escapeRe + "|.)'"
|
||||
regex : "'(?:" + escapeRe + "|.)?'"
|
||||
}, {
|
||||
token : "string.start",
|
||||
regex : '"',
|
||||
|
|
|
@ -52,8 +52,7 @@ define(function(require, exports, module) {
|
|||
|
||||
var illegal = (
|
||||
"case|const|default|function|var|void|with|enum|export|implements|" +
|
||||
"interface|let|package|private|protected|public|static|yield|" +
|
||||
"__hasProp|slice|bind|indexOf"
|
||||
"interface|let|package|private|protected|public|static|yield"
|
||||
);
|
||||
|
||||
var supportClass = (
|
||||
|
|
|
@ -28,7 +28,7 @@ var CSharpHighlightRules = function() {
|
|||
next : "comment"
|
||||
}, {
|
||||
token : "string", // character
|
||||
regex : /'(?:.|\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n]))'/
|
||||
regex : /'(?:.|\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n]))?'/
|
||||
}, {
|
||||
token : "string", start : '"', end : '"|$', next: [
|
||||
{token: "constant.language.escape", regex: /\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n])/},
|
||||
|
|
|
@ -52,7 +52,7 @@ var EjsHighlightRules = function(start, end) {
|
|||
});
|
||||
}
|
||||
|
||||
this.embedRules(JavaScriptHighlightRules, "ejs-", [{
|
||||
this.embedRules(new JavaScriptHighlightRules({jsx: false}).getRules(), "ejs-", [{
|
||||
token : "markup.list.meta.tag",
|
||||
regex : "-?" + end,
|
||||
next : "pop"
|
||||
|
|
|
@ -45,7 +45,7 @@ var ForthHighlightRules = function() {
|
|||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = { start: [ { include: '#forth' } ],
|
||||
'#comment':
|
||||
'#comment':
|
||||
[ { token: 'comment.line.double-dash.forth',
|
||||
regex: '(?:^|\\s)--\\s.*$',
|
||||
comment: 'line comments for iForth' },
|
||||
|
@ -57,7 +57,7 @@ var ForthHighlightRules = function() {
|
|||
comment: 'gForth line comment' },
|
||||
{ token: 'comment.block.forth',
|
||||
regex: '(?:^|\\s)\\(\\*(?=\\s|$)',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'comment.block.forth',
|
||||
regex: '(?:^|\\s)\\*\\)(?=\\s|$)',
|
||||
next: 'pop' },
|
||||
|
@ -66,7 +66,7 @@ var ForthHighlightRules = function() {
|
|||
{ token: 'comment.block.documentation.forth',
|
||||
regex: '\\bDOC\\b',
|
||||
caseInsensitive: true,
|
||||
push:
|
||||
push:
|
||||
[ { token: 'comment.block.documentation.forth',
|
||||
regex: '\\bENDDOC\\b',
|
||||
caseInsensitive: true,
|
||||
|
@ -76,7 +76,7 @@ var ForthHighlightRules = function() {
|
|||
{ token: 'comment.line.parentheses.forth',
|
||||
regex: '(?:^|\\s)\\.?\\( [^)]*\\)',
|
||||
comment: 'ANSI line comment' } ],
|
||||
'#constant':
|
||||
'#constant':
|
||||
[ { token: 'constant.language.forth',
|
||||
regex: '(?:^|\\s)(?:TRUE|FALSE|BL|PI|CELL|C/L|R/O|W/O|R/W)(?=\\s|$)',
|
||||
caseInsensitive: true},
|
||||
|
@ -84,7 +84,7 @@ var ForthHighlightRules = function() {
|
|||
regex: '(?:^|\\s)[$#%]?[-+]?[0-9]+(?:\\.[0-9]*e-?[0-9]+|\\.?[0-9a-fA-F]*)(?=\\s|$)'},
|
||||
{ token: 'constant.character.forth',
|
||||
regex: '(?:^|\\s)(?:[&^]\\S|(?:"|\')\\S(?:"|\'))(?=\\s|$)'}],
|
||||
'#forth':
|
||||
'#forth':
|
||||
[ { include: '#constant' },
|
||||
{ include: '#comment' },
|
||||
{ include: '#string' },
|
||||
|
@ -92,22 +92,22 @@ var ForthHighlightRules = function() {
|
|||
{ include: '#variable' },
|
||||
{ include: '#storage' },
|
||||
{ include: '#word-def' } ],
|
||||
'#storage':
|
||||
'#storage':
|
||||
[ { token: 'storage.type.forth',
|
||||
regex: '(?:^|\\s)(?:2CONSTANT|2VARIABLE|ALIAS|CONSTANT|CREATE-INTERPRET/COMPILE[:]?|CREATE|DEFER|FCONSTANT|FIELD|FVARIABLE|USER|VALUE|VARIABLE|VOCABULARY)(?=\\s|$)',
|
||||
caseInsensitive: true}],
|
||||
'#string':
|
||||
'#string':
|
||||
[ { token: 'string.quoted.double.forth',
|
||||
regex: '(ABORT" |BREAK" |\\." |C" |0"|S\\\\?" )([^"]+")',
|
||||
caseInsensitive: true},
|
||||
{ token: 'string.unquoted.forth',
|
||||
regex: '(?:INCLUDE|NEEDS|REQUIRE|USE)[ ]\\S+(?=\\s|$)',
|
||||
caseInsensitive: true}],
|
||||
'#variable':
|
||||
'#variable':
|
||||
[ { token: 'variable.language.forth',
|
||||
regex: '\\b(?:I|J)\\b',
|
||||
caseInsensitive: true } ],
|
||||
'#word':
|
||||
'#word':
|
||||
[ { token: 'keyword.control.immediate.forth',
|
||||
regex: '(?:^|\\s)\\[(?:\\?DO|\\+LOOP|AGAIN|BEGIN|DEFINED|DO|ELSE|ENDIF|FOR|IF|IFDEF|IFUNDEF|LOOP|NEXT|REPEAT|THEN|UNTIL|WHILE)\\](?=\\s|$)',
|
||||
caseInsensitive: true},
|
||||
|
@ -126,15 +126,15 @@ var ForthHighlightRules = function() {
|
|||
{ token: 'keyword.other.warning.forth',
|
||||
regex: '(?:^|\\s)(?:~~|BREAK:|BREAK"|DBG)(?=\\s|$)',
|
||||
caseInsensitive: true}],
|
||||
'#word-def':
|
||||
[ { token:
|
||||
'#word-def':
|
||||
[ { token:
|
||||
[ 'keyword.other.compile-only.forth',
|
||||
'keyword.other.compile-only.forth',
|
||||
'meta.block.forth',
|
||||
'entity.name.function.forth' ],
|
||||
regex: '(:NONAME)|(^:|\\s:)(\\s)(\\S+)(?=\\s|$)',
|
||||
caseInsensitive: true,
|
||||
push:
|
||||
push:
|
||||
[ { token: 'keyword.other.compile-only.forth',
|
||||
regex: ';(?:CODE)?',
|
||||
caseInsensitive: true,
|
||||
|
@ -150,7 +150,7 @@ var ForthHighlightRules = function() {
|
|||
this.normalizeRules();
|
||||
};
|
||||
|
||||
ForthHighlightRules.metaData = { fileTypes: [ 'frt', 'fs', 'ldr' ],
|
||||
ForthHighlightRules.metaData = { fileTypes: [ 'frt', 'fs', 'ldr', 'fth', '4th' ],
|
||||
foldingStartMarker: '/\\*\\*|\\{\\s*$',
|
||||
foldingStopMarker: '\\*\\*/|^\\s*\\}',
|
||||
keyEquivalent: '^~F',
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2012, 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.
|
||||
*
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/**
|
||||
* Haskell Cabal files mode (https://www.haskell.org/cabal/users-guide/developing-packages.html)
|
||||
**/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var CabalHighlightRules = require("./haskell_cabal_highlight_rules").CabalHighlightRules;
|
||||
var FoldMode = require("./folding/haskell_cabal").FoldMode;
|
||||
|
||||
var Mode = function() {
|
||||
this.HighlightRules = CabalHighlightRules;
|
||||
this.foldingRules = new FoldMode();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
this.lineCommentStart = "--";
|
||||
this.blockComment = null;
|
||||
this.$id = "ace/mode/haskell_cabal";
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
|
@ -0,0 +1,68 @@
|
|||
/* ***** 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 ***** */
|
||||
/**
|
||||
* Haskell Cabal files highlighter (https://www.haskell.org/cabal/users-guide/developing-packages.html)
|
||||
**/
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var CabalHighlightRules = function() {
|
||||
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment",
|
||||
regex : "^\\s*--.*$"
|
||||
}, {
|
||||
token: ["keyword"],
|
||||
regex: /^(\s*\w.*?)(\:(?:\s+|$))/
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : /[\d_]+(?:(?:[\.\d_]*)?)/
|
||||
}, {
|
||||
token : "constant.language.boolean",
|
||||
regex : "(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"
|
||||
}, {
|
||||
token : "markup.heading",
|
||||
regex : /^(\w.*)$/
|
||||
}
|
||||
]};
|
||||
|
||||
};
|
||||
|
||||
oop.inherits(CabalHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.CabalHighlightRules = CabalHighlightRules;
|
||||
});
|
|
@ -44,8 +44,8 @@ var HaskellHighlightRules = function() {
|
|||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = { start:
|
||||
[ { token:
|
||||
this.$rules = { start:
|
||||
[ { token:
|
||||
[ 'punctuation.definition.entity.haskell',
|
||||
'keyword.operator.function.infix.haskell',
|
||||
'punctuation.definition.entity.haskell' ],
|
||||
|
@ -56,7 +56,7 @@ var HaskellHighlightRules = function() {
|
|||
regex: '\\[\\]' },
|
||||
{ token: 'keyword.other.haskell',
|
||||
regex: '\\bmodule\\b',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'keyword.other.haskell', regex: '\\bwhere\\b', next: 'pop' },
|
||||
{ include: '#module_name' },
|
||||
{ include: '#module_exports' },
|
||||
|
@ -64,7 +64,7 @@ var HaskellHighlightRules = function() {
|
|||
{ defaultToken: 'meta.declaration.module.haskell' } ] },
|
||||
{ token: 'keyword.other.haskell',
|
||||
regex: '\\bclass\\b',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'keyword.other.haskell',
|
||||
regex: '\\bwhere\\b',
|
||||
next: 'pop' },
|
||||
|
@ -77,7 +77,7 @@ var HaskellHighlightRules = function() {
|
|||
{ defaultToken: 'meta.declaration.class.haskell' } ] },
|
||||
{ token: 'keyword.other.haskell',
|
||||
regex: '\\binstance\\b',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'keyword.other.haskell',
|
||||
regex: '\\bwhere\\b|$',
|
||||
next: 'pop' },
|
||||
|
@ -85,15 +85,15 @@ var HaskellHighlightRules = function() {
|
|||
{ defaultToken: 'meta.declaration.instance.haskell' } ] },
|
||||
{ token: 'keyword.other.haskell',
|
||||
regex: 'import',
|
||||
push:
|
||||
[ { token: 'meta.import.haskell', regex: '$|;', next: 'pop' },
|
||||
push:
|
||||
[ { token: 'meta.import.haskell', regex: '$|;|^', next: 'pop' },
|
||||
{ token: 'keyword.other.haskell', regex: 'qualified|as|hiding' },
|
||||
{ include: '#module_name' },
|
||||
{ include: '#module_exports' },
|
||||
{ defaultToken: 'meta.import.haskell' } ] },
|
||||
{ token: [ 'keyword.other.haskell', 'meta.deriving.haskell' ],
|
||||
regex: '(deriving)(\\s*\\()',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'meta.deriving.haskell', regex: '\\)', next: 'pop' },
|
||||
{ token: 'entity.other.inherited-class.haskell',
|
||||
regex: '\\b[A-Z][a-zA-Z_\']*' },
|
||||
|
@ -108,7 +108,7 @@ var HaskellHighlightRules = function() {
|
|||
comment: 'Floats are always decimal' },
|
||||
{ token: 'constant.numeric.haskell',
|
||||
regex: '\\b(?:[0-9]+|0(?:[xX][0-9a-fA-F]+|[oO][0-7]+))\\b' },
|
||||
{ token:
|
||||
{ token:
|
||||
[ 'meta.preprocessor.c',
|
||||
'punctuation.definition.preprocessor.c',
|
||||
'meta.preprocessor.c' ],
|
||||
|
@ -117,7 +117,7 @@ var HaskellHighlightRules = function() {
|
|||
{ include: '#pragma' },
|
||||
{ token: 'punctuation.definition.string.begin.haskell',
|
||||
regex: '"',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'punctuation.definition.string.end.haskell',
|
||||
regex: '"',
|
||||
next: 'pop' },
|
||||
|
@ -128,7 +128,7 @@ var HaskellHighlightRules = function() {
|
|||
{ token: 'constant.character.escape.control.haskell',
|
||||
regex: '\\^[A-Z@\\[\\]\\\\\\^_]' },
|
||||
{ defaultToken: 'string.quoted.double.haskell' } ] },
|
||||
{ token:
|
||||
{ token:
|
||||
[ 'punctuation.definition.string.begin.haskell',
|
||||
'string.quoted.single.haskell',
|
||||
'constant.character.escape.haskell',
|
||||
|
@ -137,13 +137,13 @@ var HaskellHighlightRules = function() {
|
|||
'constant.character.escape.control.haskell',
|
||||
'punctuation.definition.string.end.haskell' ],
|
||||
regex: '(\')(?:([\\ -\\[\\]-~])|(\\\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\"\'\\&]))|(\\\\o[0-7]+)|(\\\\x[0-9A-Fa-f]+)|(\\^[A-Z@\\[\\]\\\\\\^_]))(\')' },
|
||||
{ token:
|
||||
{ token:
|
||||
[ 'meta.function.type-declaration.haskell',
|
||||
'entity.name.function.haskell',
|
||||
'meta.function.type-declaration.haskell',
|
||||
'keyword.other.double-colon.haskell' ],
|
||||
regex: '^(\\s*)([a-z_][a-zA-Z0-9_\']*|\\([|!%$+\\-.,=</>]+\\))(\\s*)(::)',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'meta.function.type-declaration.haskell',
|
||||
regex: '$',
|
||||
next: 'pop' },
|
||||
|
@ -160,32 +160,32 @@ var HaskellHighlightRules = function() {
|
|||
regex: '[|!%$?~+:\\-.=</>\\\\]+',
|
||||
comment: 'In case this regex seems overly general, note that Haskell permits the definition of new operators which can be nearly any string of punctuation characters, such as $%^&*.' },
|
||||
{ token: 'punctuation.separator.comma.haskell', regex: ',' } ],
|
||||
'#block_comment':
|
||||
'#block_comment':
|
||||
[ { token: 'punctuation.definition.comment.haskell',
|
||||
regex: '\\{-(?!#)',
|
||||
push:
|
||||
push:
|
||||
[ { include: '#block_comment' },
|
||||
{ token: 'punctuation.definition.comment.haskell',
|
||||
regex: '-\\}',
|
||||
next: 'pop' },
|
||||
{ defaultToken: 'comment.block.haskell' } ] } ],
|
||||
'#comments':
|
||||
'#comments':
|
||||
[ { token: 'punctuation.definition.comment.haskell',
|
||||
regex: '--.*',
|
||||
push_:
|
||||
push_:
|
||||
[ { token: 'comment.line.double-dash.haskell',
|
||||
regex: '$',
|
||||
next: 'pop' },
|
||||
{ defaultToken: 'comment.line.double-dash.haskell' } ] },
|
||||
{ include: '#block_comment' } ],
|
||||
'#infix_op':
|
||||
'#infix_op':
|
||||
[ { token: 'entity.name.function.infix.haskell',
|
||||
regex: '\\([|!%$+:\\-.=</>]+\\)|\\(,+\\)' } ],
|
||||
'#module_exports':
|
||||
'#module_exports':
|
||||
[ { token: 'meta.declaration.exports.haskell',
|
||||
regex: '\\(',
|
||||
push:
|
||||
[ { token: 'meta.declaration.exports.haskell',
|
||||
push:
|
||||
[ { token: 'meta.declaration.exports.haskell.end',
|
||||
regex: '\\)',
|
||||
next: 'pop' },
|
||||
{ token: 'entity.name.function.haskell',
|
||||
|
@ -196,22 +196,22 @@ var HaskellHighlightRules = function() {
|
|||
{ token: 'meta.other.unknown.haskell',
|
||||
regex: '\\(.*?\\)',
|
||||
comment: 'So named because I don\'t know what to call this.' },
|
||||
{ defaultToken: 'meta.declaration.exports.haskell' } ] } ],
|
||||
'#module_name':
|
||||
{ defaultToken: 'meta.declaration.exports.haskell.end' } ] } ],
|
||||
'#module_name':
|
||||
[ { token: 'support.other.module.haskell',
|
||||
regex: '[A-Z][A-Za-z._\']*' } ],
|
||||
'#pragma':
|
||||
'#pragma':
|
||||
[ { token: 'meta.preprocessor.haskell',
|
||||
regex: '\\{-#',
|
||||
push:
|
||||
push:
|
||||
[ { token: 'meta.preprocessor.haskell',
|
||||
regex: '#-\\}',
|
||||
next: 'pop' },
|
||||
{ token: 'keyword.other.preprocessor.haskell',
|
||||
regex: '\\b(?:LANGUAGE|UNPACK|INLINE)\\b' },
|
||||
{ defaultToken: 'meta.preprocessor.haskell' } ] } ],
|
||||
'#type_signature':
|
||||
[ { token:
|
||||
'#type_signature':
|
||||
[ { token:
|
||||
[ 'meta.class-constraint.haskell',
|
||||
'entity.other.inherited-class.haskell',
|
||||
'meta.class-constraint.haskell',
|
||||
|
@ -230,7 +230,7 @@ var HaskellHighlightRules = function() {
|
|||
regex: '\\b[A-Z][a-zA-Z0-9_\']*\\b' },
|
||||
{ token: 'support.constant.unit.haskell', regex: '\\(\\)' },
|
||||
{ include: '#comments' } ] }
|
||||
|
||||
|
||||
this.normalizeRules();
|
||||
};
|
||||
|
||||
|
@ -243,4 +243,4 @@ HaskellHighlightRules.metaData = { fileTypes: [ 'hs' ],
|
|||
oop.inherits(HaskellHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.HaskellHighlightRules = HaskellHighlightRules;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -506,11 +506,26 @@ var PhpLangHighlightRules = function() {
|
|||
'mysql_field_name|mysql_field_seek|mysql_field_table|mysql_field_type|mysql_free_result|mysql_get_client_info|mysql_get_host_info|' +
|
||||
'mysql_get_proto_info|mysql_get_server_info|mysql_info|mysql_insert_id|mysql_list_dbs|mysql_list_fields|mysql_list_processes|' +
|
||||
'mysql_list_tables|mysql_num_fields|mysql_num_rows|mysql_pconnect|mysql_ping|mysql_query|mysql_real_escape_string|mysql_result|' +
|
||||
'mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_bind_param|' +
|
||||
'mysqli_bind_result|mysqli_client_encoding|mysqli_connect|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|' +
|
||||
'mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_escape_string|mysqli_execute|mysqli_fetch|mysqli_get_metadata|' +
|
||||
'mysqli_master_query|mysqli_param_count|mysqli_report|mysqli_result|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|' +
|
||||
'mysqli_send_long_data|mysqli_send_query|mysqli_set_opt|mysqli_slave_query|mysqli_stmt|mysqli_warning|mysqlnd_ms_get_stats|' +
|
||||
'mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_affected_rows|' +
|
||||
'mysqli_autocommit|mysqli_bind_param|mysqli_bind_result|mysqli_cache_stats|mysqli_change_user|mysqli_character_set_name|' +
|
||||
'mysqli_client_encoding|mysqli_close|mysqli_commit|mysqli_connect|mysqli_connect_errno|mysqli_connect_error|mysqli_data_seek|' +
|
||||
'mysqli_debug|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|mysqli_dump_debug_info|mysqli_embedded_server_end|' +
|
||||
'mysqli_embedded_server_start|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_errno|mysqli_error|mysqli_escape_string|' +
|
||||
'mysqli_execute|mysqli_fetch|mysqli_fetch_all|mysqli_fetch_array|mysqli_fetch_assoc|mysqli_fetch_field|mysqli_fetch_field_direct|' +
|
||||
'mysqli_fetch_fields|mysqli_fetch_lengths|mysqli_fetch_object|mysqli_fetch_row|mysqli_field_count|mysqli_field_seek|mysqli_field_tell|' +
|
||||
'mysqli_free_result|mysqli_get_charset|mysqli_get_client_info|mysqli_get_client_stats|mysqli_get_client_version|mysqli_get_connection_stats|' +
|
||||
'mysqli_get_host_info|mysqli_get_metadata|mysqli_get_proto_info|mysqli_get_server_info|mysqli_get_server_version|mysqli_get_warnings|' +
|
||||
'mysqli_info|mysqli_init|mysqli_insert_id|mysqli_kill|mysqli_link_construct|mysqli_master_query|mysqli_more_results|mysqli_multi_query|' +
|
||||
'mysqli_next_result|mysqli_num_fields|mysqli_num_rows|mysqli_options|mysqli_param_count|mysqli_ping|mysqli_poll|mysqli_prepare|' +
|
||||
'mysqli_query|mysqli_real_connect|mysqli_real_escape_string|mysqli_real_query|mysqli_reap_async_query|mysqli_refresh|mysqli_report|' +
|
||||
'mysqli_result|mysqli_rollback|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_select_db|mysqli_send_long_data|' +
|
||||
'mysqli_send_query|mysqli_set_charset|mysqli_set_local_infile_default|mysqli_set_local_infile_handler|mysqli_set_opt|mysqli_slave_query|' +
|
||||
'mysqli_sqlstate|mysqli_ssl_set|mysqli_stat|mysqli_stmt|mysqli_stmt_affected_rows|mysqli_stmt_attr_get|mysqli_stmt_attr_set|' +
|
||||
'mysqli_stmt_bind_param|mysqli_stmt_bind_result|mysqli_stmt_close|mysqli_stmt_data_seek|mysqli_stmt_errno|mysqli_stmt_error|' +
|
||||
'mysqli_stmt_execute|mysqli_stmt_fetch|mysqli_stmt_field_count|mysqli_stmt_free_result|mysqli_stmt_get_result|mysqli_stmt_get_warnings|' +
|
||||
'mysqli_stmt_init|mysqli_stmt_insert_id|mysqli_stmt_next_result|mysqli_stmt_num_rows|mysqli_stmt_param_count|mysqli_stmt_prepare|' +
|
||||
'mysqli_stmt_reset|mysqli_stmt_result_metadata|mysqli_stmt_send_long_data|mysqli_stmt_sqlstate|mysqli_stmt_store_result|mysqli_store_result|' +
|
||||
'mysqli_thread_id|mysqli_thread_safe|mysqli_use_result|mysqli_warning|mysqli_warning_count|mysqlnd_ms_get_stats|' +
|
||||
'mysqlnd_ms_query_is_select|mysqlnd_ms_set_user_pick_server|mysqlnd_qc_change_handler|mysqlnd_qc_clear_cache|mysqlnd_qc_get_cache_info|' +
|
||||
'mysqlnd_qc_get_core_stats|mysqlnd_qc_get_handler|mysqlnd_qc_get_query_trace_log|mysqlnd_qc_set_user_handlers|natcasesort|natsort|' +
|
||||
'ncurses_addch|ncurses_addchnstr|ncurses_addchstr|ncurses_addnstr|ncurses_addstr|ncurses_assume_default_colors|ncurses_attroff|' +
|
||||
|
|
|
@ -64,7 +64,7 @@ var TexHighlightRules = function(textClass) {
|
|||
next : "nospell"
|
||||
}, {
|
||||
token : "keyword", // command
|
||||
regex : "\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])"
|
||||
regex : "\\\\(?:[a-zA-Z0-9]+|[^a-zA-Z0-9])"
|
||||
}, {
|
||||
// Obviously these are neither keywords nor operators, but
|
||||
// labelling them as such was the easiest way to get them
|
||||
|
@ -98,7 +98,7 @@ var TexHighlightRules = function(textClass) {
|
|||
regex : "\\\\(?:documentclass|usepackage|newcounter|setcounter|addtocounter|value|arabic|stepcounter|newenvironment|renewenvironment|ref|vref|eqref|pageref|label|cite[a-zA-Z]*|tag|begin|end|bibitem)\\b"
|
||||
}, {
|
||||
token : "keyword", // command
|
||||
regex : "\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])",
|
||||
regex : "\\\\(?:[a-zA-Z0-9]+|[^a-zA-Z0-9])",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "paren.keyword.operator",
|
||||
|
|
|
@ -35,6 +35,9 @@ var oop = require("./lib/oop");
|
|||
var dom = require("./lib/dom");
|
||||
var event = require("./lib/event");
|
||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
||||
// on ie maximal element height is smaller than what we get from 4-5K line document
|
||||
// so scrollbar doesn't work, as a workaround we do not set height higher than MAX_SCROLL_H
|
||||
// and rescale scrolltop
|
||||
var MAX_SCROLL_H = 0x8000;
|
||||
|
||||
/**
|
||||
|
@ -90,6 +93,7 @@ var ScrollBar = function(parent) {
|
|||
var VScrollBar = function(parent, renderer) {
|
||||
ScrollBar.call(this, parent);
|
||||
this.scrollTop = 0;
|
||||
this.scrollHeight = 0;
|
||||
|
||||
// in OSX lion the scrollbars appear to have no width. In this case resize the
|
||||
// element to show the scrollbar but still pretend that the scrollbar has a width
|
||||
|
@ -116,7 +120,11 @@ oop.inherits(VScrollBar, ScrollBar);
|
|||
**/
|
||||
this.onScroll = function() {
|
||||
if (!this.skipEvent) {
|
||||
this.scrollTop = this.element.scrollTop / this.coeff;
|
||||
this.scrollTop = this.element.scrollTop;
|
||||
if (this.coeff != 1) {
|
||||
var h = this.element.clientHeight / this.scrollHeight;
|
||||
this.scrollTop = this.scrollTop * (1 - h) / (this.coeff - h);
|
||||
}
|
||||
this._emit("scroll", {data: this.scrollTop});
|
||||
}
|
||||
this.skipEvent = false;
|
||||
|
@ -149,6 +157,7 @@ oop.inherits(VScrollBar, ScrollBar);
|
|||
* @param {Number} height The new scroll height
|
||||
**/
|
||||
this.setScrollHeight = function(height) {
|
||||
this.scrollHeight = height;
|
||||
if (height > MAX_SCROLL_H) {
|
||||
this.coeff = MAX_SCROLL_H / height;
|
||||
height = MAX_SCROLL_H;
|
||||
|
|
|
@ -277,6 +277,7 @@ var SnippetManager = function() {
|
|||
if (cursor.column < indentString.length)
|
||||
indentString = indentString.slice(0, cursor.column);
|
||||
|
||||
snippetText = snippetText.replace(/\r/g, "");
|
||||
var tokens = this.tokenizeTmSnippet(snippetText);
|
||||
tokens = this.resolveVariables(tokens, editor);
|
||||
// indent
|
||||
|
@ -362,9 +363,10 @@ var SnippetManager = function() {
|
|||
var text = "";
|
||||
tokens.forEach(function(t) {
|
||||
if (typeof t === "string") {
|
||||
if (t[0] === "\n"){
|
||||
column = t.length - 1;
|
||||
row ++;
|
||||
var lines = t.split("\n");
|
||||
if (lines.length > 1){
|
||||
column = lines[lines.length - 1].length;
|
||||
row += lines.length - 1;
|
||||
} else
|
||||
column += t.length;
|
||||
text += t;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
exports.snippetText = require("../requirejs/text!./.snippets");
|
||||
exports.scope = "";
|
||||
|
||||
});
|
|
@ -97,18 +97,25 @@ module.exports = {
|
|||
assert.equal(tokens[1].flag, "g");
|
||||
},
|
||||
"test: expand snippet with nested tabstops": function() {
|
||||
var content = "-${1}-${1:1}--${2:2 ${3} 2}-${3:3 $1 3}-${4:4 $2 4}";
|
||||
var content = "-${1}-${1:t\n1}--${2:2 ${3} 2}-${3:3 $1 3}-${4:4 $2 4}";
|
||||
this.editor.setValue("");
|
||||
snippetManager.insertSnippet(this.editor, content);
|
||||
assert.equal(this.editor.getValue(), "-1-1--2 3 1 3 2-3 1 3-4 2 3 1 3 2 4");
|
||||
assert.equal(this.editor.getValue(), [
|
||||
"-t",
|
||||
"1-t",
|
||||
"1--2 3 t",
|
||||
"1 3 2-3 t",
|
||||
"1 3-4 2 3 t",
|
||||
"1 3 2 4"
|
||||
].join("\n"));
|
||||
|
||||
assert.equal(this.editor.getSelectedText(), "1\n1\n1\n1\n1");
|
||||
assert.equal(this.editor.getSelectedText(), "t\n1\nt\n1\nt\n1\nt\n1\nt\n1");
|
||||
this.editor.tabstopManager.tabNext();
|
||||
assert.equal(this.editor.getSelectedText(), "2 3 1 3 2\n2 3 1 3 2");
|
||||
assert.equal(this.editor.getSelectedText(), "2 3 t\n1 3 2\n2 3 t\n1 3 2");
|
||||
this.editor.tabstopManager.tabNext();
|
||||
assert.equal(this.editor.getSelectedText(), "3 1 3\n3 1 3\n3 1 3");
|
||||
assert.equal(this.editor.getSelectedText(), "3 t\n1 3\n3 t\n1 3\n3 t\n1 3");
|
||||
this.editor.tabstopManager.tabNext();
|
||||
assert.equal(this.editor.getSelectedText(), "4 2 3 1 3 2 4");
|
||||
assert.equal(this.editor.getSelectedText(), "4 2 3 t\n1 3 2 4");
|
||||
this.editor.tabstopManager.tabNext();
|
||||
assert.equal(this.editor.getSelectedText(), "");
|
||||
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
var dom = require('node-jsdom/lib/jsdom/living');
|
||||
var browser = require('node-jsdom/lib/jsdom/browser/index').browserAugmentation(dom);
|
||||
var doc = new browser.HTMLDocument({parsingMode: 'html'});
|
||||
doc.write("<html><head></head><body></body></html>");
|
||||
browser.document = doc;
|
||||
browser.window = doc.defaultView;
|
||||
var jsdom = require('jsdom/').jsdom;
|
||||
var doc = jsdom("<html><head></head><body></body></html>")
|
||||
|
||||
global.document = browser.document;
|
||||
global.window = browser.window;
|
||||
global.self = browser.self;
|
||||
global.navigator = browser.navigator;
|
||||
global.location = browser.location;
|
||||
global.document = doc;
|
||||
global.window = doc.defaultView;
|
||||
global.self = doc.self;
|
||||
global.navigator = doc.navigator;
|
||||
global.location = doc.location;
|
||||
|
|
|
@ -393,8 +393,6 @@ var loadScriptWithTag = function(path, id, callback) {
|
|||
if (path.lastIndexOf(require.MODULE_LOAD_URL, 0) == 0 && path[0] != "/")
|
||||
s.crossOrigin = true;
|
||||
|
||||
head.appendChild(s);
|
||||
|
||||
s.onload = s.onreadystatechange = function(_, isAbort) {
|
||||
if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") {
|
||||
s = s.onload = s.onreadystatechange = null;
|
||||
|
@ -409,6 +407,7 @@ var loadScriptWithTag = function(path, id, callback) {
|
|||
path: path
|
||||
});
|
||||
};
|
||||
head.appendChild(s);
|
||||
};
|
||||
|
||||
function loadText(path, cb) {
|
||||
|
@ -468,6 +467,9 @@ var loadCached = function(path, cb) {
|
|||
}
|
||||
});
|
||||
}
|
||||
if (!ideCache && !ideCachePromiss) {
|
||||
checkCache();
|
||||
}
|
||||
if (ideCachePromiss) {
|
||||
return ideCachePromiss.then(function(i) {
|
||||
if (i) ideCache = i;
|
||||
|
@ -494,7 +496,10 @@ var ideCache;
|
|||
var ideCachePromiss;
|
||||
function checkCache() {
|
||||
var baseUrl;
|
||||
ideCachePromiss = config.useCache && window.caches.open("ide").then(function(ideCache_) {
|
||||
ideCachePromiss = config.useCache && window.caches.open("ide").catch(function(e) {
|
||||
console.error(e);
|
||||
config.useCache = ideCachePromiss = ideCache = null;
|
||||
}).then(function(ideCache_) {
|
||||
ideCache = ideCache_;
|
||||
return ideCache.keys();
|
||||
}).then(function(keys) {
|
||||
|
@ -557,7 +562,7 @@ require.clearCache = function(callback) {
|
|||
callback && callback(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function post(path, val, progress, cb) {
|
||||
var xhr = new window.XMLHttpRequest();
|
||||
|
|
|
@ -64,6 +64,8 @@ describe("docker-helpers", function() {
|
|||
assert.equal(dockerHelpers.getProjectIdFromContainerName("container-stefko-demo-project-884917"), "884917");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("container-scollins-booking_admin-1667108-yORDDrjnsOiiLveG"), "1667108");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("jakrawczt-test-3-jkr-1633955"), "1633955");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("jakrawczt-test-489552-1633956"), "1633956");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("/container-jan1365-ide50-2380083-XoEYNkUIDRuLqvBZ"), "2380083");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("thn85-p18-1016460"), "1016460");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("thn85-proj-18239823-1016490"), "1016490");
|
||||
assert.equal(dockerHelpers.getProjectIdFromContainerName("artawil-etutor_11plus-wp-1422098"), "1422098");
|
||||
|
|
|
@ -6,15 +6,21 @@
|
|||
|
||||
var hashing = require('./hashing');
|
||||
var bcrypt;
|
||||
try {
|
||||
bcrypt = require('bcrypt');
|
||||
} catch (e) {
|
||||
console.error("Failed to load brcrypt - binary version mismatch?", e.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
var SALT_LENGTH = 8;
|
||||
|
||||
function loadBcrypt() {
|
||||
if (bcrypt) return;
|
||||
|
||||
try {
|
||||
bcrypt = require('bcrypt');
|
||||
} catch (e) {
|
||||
console.error("Failed to load bcrypt - binary version mismatch?", e.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
exports.encrypt = function(password, callback) {
|
||||
loadBcrypt();
|
||||
var passwordHashed = hashing.md5(password);
|
||||
bcrypt.hash(passwordHashed, SALT_LENGTH, function(err, passwordEncrypted) {
|
||||
if (err) return callback(err);
|
||||
|
@ -23,6 +29,7 @@ exports.encrypt = function(password, callback) {
|
|||
};
|
||||
|
||||
exports.compare = function(password, encrypted, callback) {
|
||||
loadBcrypt();
|
||||
var passwordHashed = hashing.md5(password);
|
||||
if (passwordHashed == encrypted) { // Some passwords may still only be hashed, not bcrypted, so see if that worked first.
|
||||
return callback(null, true);
|
||||
|
|
|
@ -30,15 +30,6 @@ module.exports = function startup(options, imports, register) {
|
|||
var sessionRoutes = connectModule();
|
||||
connect.useSession(sessionRoutes);
|
||||
|
||||
|
||||
sessionRoutes.use(
|
||||
function(req, res, next) {
|
||||
if (/^\/geckolala\//.test(req.url))
|
||||
return next(new error.TooManyRequests("Rate limit exceeded"));
|
||||
next();
|
||||
}
|
||||
);
|
||||
|
||||
sessionRoutes.use(Session(sessionOptions, cookie));
|
||||
|
||||
register(null, {
|
||||
|
|
|
@ -2,6 +2,6 @@ define(function(require, exports, module) {
|
|||
|
||||
// on each backwards incompatible protocol change the version number must be
|
||||
// increased
|
||||
exports.protocol = 12;
|
||||
exports.protocol = 13;
|
||||
|
||||
});
|
|
@ -17,7 +17,7 @@ module.exports = function setup(mount, vfs, mountOptions) {
|
|||
}
|
||||
|
||||
if (code) res.statusCode = code;
|
||||
else if (typeof err.code == "number") res.statusCode = err.code;
|
||||
else if (typeof err.code == "number" && isValidStatusCode(err.code)) res.statusCode = err.code;
|
||||
else if (err.code === "EBADREQUEST") res.statusCode = 400;
|
||||
else if (err.code === "EACCES") res.statusCode = 403;
|
||||
else if (err.code === "ENOENT") res.statusCode = 404;
|
||||
|
@ -29,6 +29,10 @@ module.exports = function setup(mount, vfs, mountOptions) {
|
|||
res.setHeader("Content-Length", Buffer.byteLength(message));
|
||||
res.end(message);
|
||||
};
|
||||
|
||||
function isValidStatusCode(statusCode) {
|
||||
return statusCode >= 100 && statusCode <= 999;
|
||||
}
|
||||
|
||||
// Returns a json stream that wraps input object stream
|
||||
function jsonEncoder(input, path) {
|
||||
|
|
|
@ -128,7 +128,7 @@ module.exports = function setup(fsOptions) {
|
|||
_execFile(TMUX, ["-V"], function(err, stdout) {
|
||||
if (err) stdout = "tmux 1.9";
|
||||
noTmux = err && err.code === "ENOENT";
|
||||
TMUXNAME = "cloud9" + parseFloat(stdout.replace(/tmux /, ""), 10);
|
||||
TMUXNAME = "cloud9" + parseFloat(stdout.replace(/tmux([-\d.]*) /, ""), 10);
|
||||
});
|
||||
|
||||
if (fsOptions.hasOwnProperty('defaultEnv')) {
|
||||
|
@ -379,6 +379,7 @@ module.exports = function setup(fsOptions) {
|
|||
} else {
|
||||
entry.size = stat.size;
|
||||
entry.mtime = stat.mtime.valueOf();
|
||||
entry.ctime = stat.ctime.valueOf();
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
entry.mime = "inode/directory";
|
||||
|
@ -429,8 +430,17 @@ module.exports = function setup(fsOptions) {
|
|||
var meta = {};
|
||||
resolvePath(path, options, function (err, realpath) {
|
||||
if (err) return callback(err);
|
||||
fn(realpath, function (err) {
|
||||
if (err) return callback(err);
|
||||
fn(realpath, function done(err) {
|
||||
if (err) {
|
||||
if (err.code == "ENOENT") {
|
||||
return fs.exists(realpath, function(exists) {
|
||||
if (exists) err.code = "EACCES";
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
return callback(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove metadata
|
||||
resolvePath(WSMETAPATH + path, options, function (err, realpath) {
|
||||
|
@ -1003,7 +1013,17 @@ module.exports = function setup(fsOptions) {
|
|||
function rmdir(path, options, callback) {
|
||||
if (options.recursive) {
|
||||
remove(path, function(path, callback) {
|
||||
execFile("rm", {args: ["-rf", path]}, callback);
|
||||
spawn("rm", {args: ["-rf", path], stdio: 'ignore'}, function(err, child) {
|
||||
if (err) return callback(err);
|
||||
child.process.on("close", function(code) {
|
||||
if (code) {
|
||||
var err = new Error("Permission denied.");
|
||||
err.code = "EACCES";
|
||||
return callback(err);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}, options, callback);
|
||||
}
|
||||
else {
|
||||
|
@ -1926,10 +1946,18 @@ module.exports = function setup(fsOptions) {
|
|||
|
||||
function run(err){
|
||||
if (err) return callback(err);
|
||||
_setDefaultEnv(options);
|
||||
delete options.env.TMUX;
|
||||
|
||||
// HACK: workaround for tmux 2.2 bug:
|
||||
// tmux passes PATH to new sessions breaking rvm
|
||||
var sep = isWin ? ";" : ":";
|
||||
options.env.PATH = options.env.PATH.split(sep).filter(function(p) {
|
||||
return !/\/rvm\//.test(p);
|
||||
}).join(sep);
|
||||
// ENDHACK
|
||||
|
||||
if (options.detach && options.output) {
|
||||
_setDefaultEnv(options);
|
||||
delete options.env.TMUX;
|
||||
|
||||
return _execFile(TMUX, args, {
|
||||
args: args,
|
||||
|
|
30
package.json
30
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "c9",
|
||||
"description": "New Cloud9 Client",
|
||||
"version": "3.1.2758",
|
||||
"version": "3.1.2968",
|
||||
"author": "Ajax.org B.V. <info@ajax.org>",
|
||||
"private": true,
|
||||
"main": "bin/c9",
|
||||
|
@ -26,18 +26,18 @@
|
|||
"mkdirp": "~0.3.5",
|
||||
"msgpack-js": "~0.1.1",
|
||||
"msgpack-js-browser": "~0.1.4",
|
||||
"nak": "git://github.com/cloud9ide/nak.git#6deef931594",
|
||||
"nak": "https://github.com/cloud9ide/nak.git#6deef931594",
|
||||
"netutil": "~0.0.2",
|
||||
"optimist": "~0.6.0",
|
||||
"qs": "0.6.6",
|
||||
"rusha": "^0.8.3",
|
||||
"send": "~0.1.4",
|
||||
"simple-mime": "~0.0.8",
|
||||
"tern": "git://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
|
||||
"tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#84d51dcb9b16b126a206789d4d4237cde2801fe4",
|
||||
"tern": "https://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
|
||||
"tern_from_ts": "https://github.com/cloud9ide/tern_from_ts.git#84d51dcb9b16b126a206789d4d4237cde2801fe4",
|
||||
"through": "2.2.0",
|
||||
"tmp": "~0.0.20",
|
||||
"uglify-js": "^2.6.2",
|
||||
"uglify-js": "~2.6.2",
|
||||
"ws": "0.4.31",
|
||||
"read": "~1.0.5",
|
||||
"form-data": "~0.2.0",
|
||||
|
@ -58,7 +58,7 @@
|
|||
"c9"
|
||||
],
|
||||
"c9plugins": {
|
||||
"c9.ide.language": "#0e86345d39",
|
||||
"c9.ide.language": "#0426ee345b",
|
||||
"c9.ide.language.core": "#bfb5dd2acc",
|
||||
"c9.ide.language.css": "#46ad561506",
|
||||
"c9.ide.language.generic": "#b47cbe58f9",
|
||||
|
@ -71,12 +71,12 @@
|
|||
"c9.ide.language.javascript.infer": "#b9c2e4bdb8",
|
||||
"c9.ide.language.jsonalyzer": "#a0549e14ff",
|
||||
"c9.ide.language.codeintel": "#4e0a272229",
|
||||
"c9.ide.collab": "#e015881720",
|
||||
"c9.ide.collab": "#d149eae786",
|
||||
"c9.ide.local": "#9169fec157",
|
||||
"c9.ide.find": "#a2dfc3e306",
|
||||
"c9.ide.find.infiles": "#488db22ee1",
|
||||
"c9.ide.find.replace": "#47a84af707",
|
||||
"c9.ide.run.debug": "#08249419c5",
|
||||
"c9.ide.find": "#e632ecf4be",
|
||||
"c9.ide.find.infiles": "#ad9ff74638",
|
||||
"c9.ide.find.replace": "#8468067976",
|
||||
"c9.ide.run.debug": "#651451a7c2",
|
||||
"c9.automate": "#47e2c429c9",
|
||||
"c9.ide.ace.emmet": "#6dc4585e02",
|
||||
"c9.ide.ace.gotoline": "#d33220b1e0",
|
||||
|
@ -93,8 +93,8 @@
|
|||
"c9.ide.format": "#f99082ff4c",
|
||||
"c9.ide.help.support": "#fbe8eb5c36",
|
||||
"c9.ide.imgeditor": "#612e75ef4f",
|
||||
"c9.ide.immediate": "#b279c69c73",
|
||||
"c9.ide.installer": "#b2e4ba0a92",
|
||||
"c9.ide.immediate": "#0b0ee744f9",
|
||||
"c9.ide.installer": "#2921efaf6d",
|
||||
"c9.ide.language.python": "#9fba572b1a",
|
||||
"c9.ide.language.go": "#6ce1c7a7ef",
|
||||
"c9.ide.navigate": "#5d5707058c",
|
||||
|
@ -108,7 +108,7 @@
|
|||
"c9.ide.recentfiles": "#7c099abf40",
|
||||
"c9.ide.remote": "#301d2ab519",
|
||||
"c9.ide.processlist": "#2b12cd1bdd",
|
||||
"c9.ide.run": "#d661a7b847",
|
||||
"c9.ide.run": "#bf68394c6f",
|
||||
"c9.ide.run.build": "#0598fff697",
|
||||
"c9.ide.run.debug.xdebug": "#054367574c",
|
||||
"c9.ide.save": "#25a63f31e2",
|
||||
|
@ -121,6 +121,6 @@
|
|||
"c9.ide.undo": "#b028bcb4d5",
|
||||
"c9.ide.upload": "#e4351f5a2b",
|
||||
"c9.ide.welcome": "#5b86c44e92",
|
||||
"c9.ide.guide": "#df7c89e449"
|
||||
"c9.ide.guide": "#19f6087429"
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ module.exports = function (vfs, options, register) {
|
|||
|
||||
var net = require("net");
|
||||
var Stream = require('stream');
|
||||
var path = require("path");
|
||||
|
||||
var SOCKET = process.platform == "win32"
|
||||
? "\\\\.\\pipe\\.c9\\bridge.socket"
|
||||
|
@ -74,7 +75,6 @@ module.exports = function (vfs, options, register) {
|
|||
clients.push(client);
|
||||
}
|
||||
|
||||
api
|
||||
var clients = [];
|
||||
var stream = new Stream();
|
||||
stream.readable = true;
|
||||
|
@ -89,10 +89,17 @@ module.exports = function (vfs, options, register) {
|
|||
var unixServer = net.createServer(registerClient);
|
||||
unixServer.listen(SOCKET);
|
||||
|
||||
var socketDirExists = false;
|
||||
unixServer.on("error", function(err){
|
||||
if (err.code == "EADDRINUSE") {
|
||||
createListenClient(api);
|
||||
}
|
||||
else if (err.code == "EACCES" && !socketDirExists) {
|
||||
vfs.mkdirP(path.dirname(SOCKET), {}, function() {
|
||||
socketDirExists = true;
|
||||
unixServer.listen(SOCKET);
|
||||
});
|
||||
}
|
||||
else
|
||||
api.onError(err);
|
||||
});
|
||||
|
|
|
@ -40,14 +40,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "/vfs-home"],
|
|||
},
|
||||
"plugins/c9.cli.bridge/bridge-client",
|
||||
|
||||
// Mock plugins
|
||||
{
|
||||
consumes: [],
|
||||
provides: [
|
||||
"preferences", "ui"
|
||||
],
|
||||
setup: expect.html.mocked
|
||||
},
|
||||
{
|
||||
consumes: ["bridge", "bridge.client"],
|
||||
provides: [],
|
||||
|
|
|
@ -122,9 +122,9 @@ define(function(require, module, exports) {
|
|||
emit("quit");
|
||||
}
|
||||
|
||||
function toExternalPath(path) {
|
||||
function toExternalPath(path, sep) {
|
||||
if (plugin.platform == "win32")
|
||||
path = path.replace(/^[/]+/, "").replace(/[/]+/g, "\\");
|
||||
path = path.replace(/^[/]+/, "").replace(/[/]+/g, sep || "\\");
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,20 +208,21 @@ define(function(require, exports, module) {
|
|||
|
||||
var reHome, reWorkspace, homeSub;
|
||||
plugin.$initPaths = function(home, workspaceDir) {
|
||||
reHome = new RegExp("^" + plugin.escapeRegExp(home) + "(/|/?$)");
|
||||
var pre = c9.platform == "win32" ? "/?" : "";
|
||||
reHome = new RegExp("^" + pre + plugin.escapeRegExp(home) + "(/|/?$)");
|
||||
var wd = workspaceDir.replace(/\/?$/, "");
|
||||
reWorkspace = new RegExp("^" + plugin.escapeRegExp(wd) + "(/|/?$)");
|
||||
reWorkspace = new RegExp("^" + pre + plugin.escapeRegExp(wd) + "(/|/?$)");
|
||||
homeSub = "~/";
|
||||
if (home == workspaceDir) {
|
||||
reHome = new RegExp("^(" + plugin.escapeRegExp(home) + "|~)(/|/?$)");
|
||||
reHome = new RegExp("^(" + pre + plugin.escapeRegExp(home) + "|~)(/|/?$)");
|
||||
homeSub = "/";
|
||||
reWorkspace = null;
|
||||
} else if (reHome.test(workspaceDir)) {
|
||||
reWorkspace = new RegExp("^" +
|
||||
reWorkspace = new RegExp("^" + pre +
|
||||
plugin.escapeRegExp(workspaceDir.replace(reHome, "~/")) + "(/|/?$)"
|
||||
);
|
||||
} else if (reWorkspace.test(home)) {
|
||||
reHome = new RegExp("^(" + plugin.escapeRegExp(home) + "|~)(/|/?$)");
|
||||
reHome = new RegExp("^(" + pre + plugin.escapeRegExp(home) + "|~)(/|/?$)");
|
||||
homeSub = home.replace(reWorkspace, "/").replace(/\/?$/, "/");
|
||||
reWorkspace = null;
|
||||
}
|
||||
|
|
|
@ -746,7 +746,7 @@ define(function(require, exports, module) {
|
|||
} else if (node.status == "loading") {
|
||||
plugin.on("readdir", function listener(e) {
|
||||
if (e.path == subPath) {
|
||||
plugin.on("readdir", listener);
|
||||
plugin.off("readdir", listener);
|
||||
recur();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -462,8 +462,9 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
|
|||
|
||||
fs.writeFile(before, text, function(err) {
|
||||
expect(fsCache.findNode(before), "start").to.exist;
|
||||
expect(fsCache.findNode(after), "start").to.not.exist;
|
||||
fs.rename(before, after, function() {
|
||||
expect(fsCache.findNode(after), "afer").to.exist;
|
||||
expect(fsCache.findNode(after), "after").to.exist;
|
||||
expect(fsCache.findNode(before), "before").to.not.exist;
|
||||
fs.rmfile(after, function(){
|
||||
fsCache.off("update", c1);
|
||||
|
@ -486,6 +487,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
|
|||
fsCache.on("update", c1);
|
||||
|
||||
fs.writeFile(before, text, function(err) {
|
||||
expect(err).to.not.ok;
|
||||
expect(fsCache.findNode(before), "start").to.exist;
|
||||
|
||||
fs.rename(before, after, function() {
|
||||
|
@ -500,11 +502,10 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
|
|||
throw new Error("Wrong Event Count: "
|
||||
+ count + " of 2");
|
||||
});
|
||||
// Disabled: test fails only on CI server...
|
||||
});
|
||||
});
|
||||
});
|
||||
it.skip("should recursively update the nodes in cache when a dir is renamed", function(done) {
|
||||
it("should recursively update the nodes in cache when a dir is renamed", function(done) {
|
||||
fs.rmdir("/rdir", {recursive:true}, function(){
|
||||
fs.copy("/dir", "/dir2", {recursive: true}, function(err) {
|
||||
if (err) throw err.message;
|
||||
|
@ -535,7 +536,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
|
|||
+ count + " of 3");
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,12 +18,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
"plugins/c9.vfs.client/endpoint",
|
||||
"plugins/c9.ide.auth/auth",
|
||||
|
||||
//Mock Plugins
|
||||
{
|
||||
consumes: ["Plugin"],
|
||||
provides: ["auth.bootstrap", "info", "dialog.error"],
|
||||
setup: expect.html.mocked
|
||||
},
|
||||
{
|
||||
consumes: ["fs"],
|
||||
provides: [],
|
||||
|
@ -285,6 +279,8 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
expect(exists).ok;
|
||||
|
||||
fs.rmdir(vpath, {}, function(err, meta) {
|
||||
if (err.code == "EACCES") // node sends EACCES on windows
|
||||
err.code = "ENOTDIR";
|
||||
expect(err).property("code").equal("ENOTDIR");
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
"use client";
|
||||
|
||||
require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai) {
|
||||
require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function (architect, chai, vfsRoot) {
|
||||
var expect = chai.expect;
|
||||
|
||||
expect.setupArchitectTest([
|
||||
|
@ -11,7 +11,8 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
startdate: new Date(),
|
||||
debug: true,
|
||||
hosted: true,
|
||||
local: false
|
||||
local: false,
|
||||
platform: vfsRoot.indexOf(":") == -1 ? "linux" : "win32"
|
||||
},
|
||||
"plugins/c9.core/http-xhr",
|
||||
"plugins/c9.core/ext",
|
||||
|
@ -19,14 +20,8 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
"plugins/c9.vfs.client/vfs_client",
|
||||
"plugins/c9.vfs.client/endpoint",
|
||||
"plugins/c9.ide.auth/auth",
|
||||
// Mock plugins
|
||||
{
|
||||
consumes: [],
|
||||
provides: ["auth.bootstrap", "info", "dialog.error"],
|
||||
setup: expect.html.mocked
|
||||
},
|
||||
{
|
||||
consumes: ["proc"],
|
||||
consumes: ["proc", "c9"],
|
||||
provides: [],
|
||||
setup: main
|
||||
}
|
||||
|
@ -34,6 +29,7 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
|
||||
function main(options, imports, register) {
|
||||
var proc = imports.proc;
|
||||
var c9 = imports.c9;
|
||||
|
||||
describe('proc', function() {
|
||||
describe('spawn()', function() {
|
||||
|
@ -117,10 +113,15 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
|
|||
});
|
||||
describe('pty()', function() {
|
||||
this.timeout(30000);
|
||||
if (c9.platform == "win32")
|
||||
return it.skip("Terminal Test", function(done) { done(); });
|
||||
|
||||
it("Terminal Test", function(done) {
|
||||
var look = "--color=auto";
|
||||
|
||||
if (c9.platform == "win32")
|
||||
return done;
|
||||
|
||||
var args = ["-is"];
|
||||
proc.pty("bash", {
|
||||
args: args,
|
||||
|
|
|
@ -14,8 +14,8 @@ define(function(require, module, exports) {
|
|||
allowClose: false,
|
||||
modal: true,
|
||||
elements: [
|
||||
{ type: "button", id: "cancel", caption: "Cancel", hotkey: "ESC", onclick: function(){ plugin.hide() } },
|
||||
{ type: "button", id: "ok", caption: "OK", color: "green", "default": true, onclick: function(){ plugin.hide() } }
|
||||
{ type: "button", id: "ok", caption: "OK", color: "green", "default": true, onclick: function(){ plugin.hide() } },
|
||||
{ type: "button", id: "cancel", caption: "Cancel", hotkey: "ESC", onclick: function(){ plugin.hide() } }
|
||||
]
|
||||
});
|
||||
|
||||
|
|
|
@ -67,13 +67,6 @@
|
|||
Show files in tree
|
||||
</a:checkbox>
|
||||
<a:filler />
|
||||
<a:button
|
||||
id = "btnCancel"
|
||||
class = "btn-red"
|
||||
skin = "btn-default-css3"
|
||||
width = "120"
|
||||
caption = "Cancel"
|
||||
/>
|
||||
<a:button
|
||||
id = "btnChoose"
|
||||
class = "btn-green"
|
||||
|
@ -81,6 +74,13 @@
|
|||
caption = "Save"
|
||||
skin = "btn-default-css3"
|
||||
/>
|
||||
<a:button
|
||||
id = "btnCancel"
|
||||
class = "btn-red"
|
||||
skin = "btn-default-css3"
|
||||
width = "120"
|
||||
caption = "Cancel"
|
||||
/>
|
||||
</a:hbox>
|
||||
</a:vbox>
|
||||
</a:window>
|
||||
|
|
|
@ -47,17 +47,17 @@
|
|||
</div>
|
||||
|
||||
<a:hbox edge="23 0 10" pack="end" padding="8">
|
||||
<a:button
|
||||
id = "btnCancel"
|
||||
skin = "btn-default-css3"
|
||||
caption = "Cancel"
|
||||
/>
|
||||
<a:button
|
||||
id = "btnChoose"
|
||||
class = "btn-green"
|
||||
caption = "OK"
|
||||
skin = "btn-default-css3"
|
||||
/>
|
||||
<a:button
|
||||
id = "btnCancel"
|
||||
skin = "btn-default-css3"
|
||||
caption = "Cancel"
|
||||
/>
|
||||
</a:hbox>
|
||||
</a:vbox>
|
||||
</a:window>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
define(function(require, module, exports) {
|
||||
main.consumes = [
|
||||
"Plugin", "menus", "ui"
|
||||
"Plugin", "menus", "ui", "settings"
|
||||
];
|
||||
main.provides = ["editors"];
|
||||
return main;
|
||||
|
@ -9,6 +9,7 @@ define(function(require, module, exports) {
|
|||
var ui = imports.ui;
|
||||
var Plugin = imports.Plugin;
|
||||
var menus = imports.menus;
|
||||
var settings = imports.settings;
|
||||
|
||||
var extname = require("path").extname;
|
||||
var basename = require("path").basename;
|
||||
|
@ -69,6 +70,11 @@ define(function(require, module, exports) {
|
|||
function findEditorByFilename(fn) {
|
||||
var ext = extname(fn).substr(1).toLowerCase();
|
||||
var filename = basename(fn).toLowerCase();
|
||||
|
||||
// Check custom user settings first for preferred editor
|
||||
var customEditor = settings.get("user/tabs/editorTypes/@" + ext);
|
||||
if (customEditor) return customEditor;
|
||||
|
||||
var editor = fileExtensions[fn] && fileExtensions[fn][0]
|
||||
|| fileExtensions[filename] && fileExtensions[filename][0]
|
||||
|| fileExtensions[ext] && fileExtensions[ext][0]
|
||||
|
|
|
@ -385,6 +385,7 @@ define(function(require, module, exports) {
|
|||
|
||||
open({
|
||||
path: name,
|
||||
focus: true,
|
||||
active: true,
|
||||
pane: e.pane,
|
||||
value: "",
|
||||
|
@ -1077,6 +1078,12 @@ define(function(require, module, exports) {
|
|||
// options.document.filter = true;
|
||||
options.editorType = type;
|
||||
|
||||
// Don't proceed if findEditorByFilename returned "none"
|
||||
if (editor === "none") {
|
||||
alert("Can't open " + basename(path) + ": file format unsupported");
|
||||
return callback(new Error("File not supported"));
|
||||
}
|
||||
|
||||
// Create the tab
|
||||
tab = createTab(options);
|
||||
|
||||
|
|
|
@ -730,7 +730,7 @@
|
|||
@breakpoint-list-item-border-top: transparent;
|
||||
@breakpoint-list-item-padding: 1px 10px 0 7px;
|
||||
@breakpoint-list-item-hover-color: darken(#e0e3e8, @darken-chrome);
|
||||
@breakpoint-list-item-hover-background: darken(#F6F6F6, @darken-chrome);
|
||||
@breakpoint-list-item-hover-background: darken(#252525, @darken-chrome);
|
||||
@breakpoint-list-item-hover-border-top: transparent;
|
||||
|
||||
// Breakpoint Condition Dialog
|
||||
|
@ -774,7 +774,7 @@
|
|||
@immediate-font-smoothing: false;
|
||||
|
||||
@immediate-dark-row-border-color: darken(rgb(29, 28, 28), @darken-chrome);
|
||||
@immediate-dark-return: darken(#252525, @darken-chrome);
|
||||
@immediate-dark-return: darken(#FFFFFF, @darken-chrome);
|
||||
@immediate-dark-warn: yellow;
|
||||
@immediate-dark-error: red;
|
||||
@immediate-dark-property: darken(#BEDB18, @darken-chrome);
|
||||
|
@ -1658,12 +1658,12 @@
|
|||
@stats-button-width: 100px;
|
||||
@stats-button-margin-left: 0;
|
||||
@stats-button-padding: 2px 5px 2px 7px;
|
||||
@stats-button-border-left: 1px solid #e0e0e0;
|
||||
@stats-button-border-right: 1px solid #e0e0e0;
|
||||
@stats-button-border-left: 1px solid #1c1c1c;
|
||||
@stats-button-border-right: 1px solid #1c1c1c;
|
||||
@stats-button-box-shadow: none;
|
||||
@stats-button-color: #666666;
|
||||
@stats-button-hover-background: #E9E9E9;
|
||||
@stats-button-active-background: white;
|
||||
@stats-button-hover-background: #494949;
|
||||
@stats-button-active-background: #494949;
|
||||
@stats-button-active-box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.09);
|
||||
|
||||
@stats-button-item-padding: 4px 0 0 0;
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
}
|
||||
|
||||
.bartools .c9-toolbarbutton-glossymenuDown{
|
||||
background-color: #ffffff;
|
||||
background-color: #494949;
|
||||
box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.29);
|
||||
border: 1px solid #dedede;
|
||||
border-left: 1px solid #252525;
|
||||
border-right: 1px solid #252525;
|
||||
}
|
||||
|
||||
.output .toolbar .c9-toolbarbutton-glossyOver{
|
||||
|
|
|
@ -120,6 +120,11 @@ define(function(require, exports, module) {
|
|||
* @return {Object}
|
||||
*/
|
||||
getLastPing: apiFunction.bind(null, "getLastPing"),
|
||||
|
||||
/**
|
||||
* Add a hook for ping.complete
|
||||
*/
|
||||
onPingComplete: apiFunction.bind(null, "onPingComplete"),
|
||||
});
|
||||
|
||||
register(null, { metrics: plugin });
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
#c9_ide_restore {
|
||||
display: none;
|
||||
z-index: 1000000;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#c9_ide_restore .timeout a {
|
||||
color: #FFDE75;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#c9_ide_restore .timeout {
|
||||
position: relative;
|
||||
background: #DA7A30;
|
||||
z-index: 10000000;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
margin: 10px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* progress 3C7B0D*/
|
||||
#restoring {
|
||||
font-style: normal;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
z-index: 100000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
.font-smoothing(~"antialiased !important");
|
||||
background: white url("@{image-path}/loadingbgrepeat.png");
|
||||
background-size: 1px 8px;
|
||||
}
|
||||
.dark #restoring{
|
||||
background: black url("@{image-path}/loadingbgrepeat_dark.png");
|
||||
background-size: 1px 8px;
|
||||
}
|
||||
|
||||
#restoring .loading-progress {
|
||||
font-size: 31px;
|
||||
color: #4A8532;
|
||||
height: 37px;
|
||||
position: relative;
|
||||
margin: 252px 0 0 0;
|
||||
top: 30%;
|
||||
}
|
||||
#restoring .loading-msg {
|
||||
color: #717171;
|
||||
.font-smoothing(true);
|
||||
margin: 58px 0 10px;
|
||||
}
|
||||
#restoring .loading-details{
|
||||
margin: 3px 0 0 0;
|
||||
font-size: 14px;
|
||||
color: #858E91;
|
||||
.font-smoothing(true);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.stickynote {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
left: 50%;
|
||||
margin: 0px -261px;
|
||||
z-index : 10000000;
|
||||
.transform(~"rotate(2deg)");
|
||||
}
|
||||
.stickynote.casual{
|
||||
bottom: 50px;
|
||||
right: 50px;
|
||||
left: auto;
|
||||
top: auto;
|
||||
margin: 0;
|
||||
}
|
||||
.stickynote .paper {
|
||||
color: black;
|
||||
width: 284px;
|
||||
/*color: #f1f1f1;*/
|
||||
background: #FFDE75;
|
||||
padding: 25px 20px 10px 20px;
|
||||
box-shadow: 1px 1px 15px rgba(0,0,0,0.12);
|
||||
// font-family : Tahoma;
|
||||
font-size : 15px;
|
||||
text-align : left;
|
||||
.font-smoothing(true);
|
||||
}
|
||||
.stickynote strong {
|
||||
font-size: 17px;
|
||||
}
|
||||
.stickynote a.restore-upsell {
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
padding: 5px 10px 8px 10px;
|
||||
background: #39A6D7;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
.stickynote a.restore-upsell:hover {
|
||||
background: #0FB6FF;
|
||||
}
|
||||
.stickynote .tape {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
right: 80px;
|
||||
width: 130px;
|
||||
height: 35px;
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
border-left: 1px dashed rgba(0, 0, 0, 0.1);
|
||||
border-right: 1px dashed rgba(0, 0, 0, 0.1);
|
||||
|
||||
.box-shadow(~"0px 0px 1px 0px rgba(204, 204, 204, 0.28)");
|
||||
.transform(~"rotate(-2deg) skew(0,0) translate(0%,-5px)");
|
||||
}
|
||||
.stickynote .left-shadow {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
bottom: -5px;
|
||||
left: -12px;
|
||||
position: absolute;
|
||||
z-index: -6;
|
||||
display: inline-block;
|
||||
.box-shadow(~"-10px -10px 10px rgba(0, 0, 0, 0.12)");
|
||||
.transform(~"scale(1) rotate(274deg) translate(20px, 25px) skew(9deg, 0deg)");
|
||||
}
|
||||
.stickynote .right-shadow {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
bottom: -13px;
|
||||
right: -4px;
|
||||
position: absolute;
|
||||
z-index: -6;
|
||||
display: inline-block;
|
||||
.box-shadow(~"-10px -10px 10px rgba(0, 0, 0, 0.12)");
|
||||
.transform(~"scale(1) rotate(184deg) translate(20px, 25px) skew(9deg, 0deg)");
|
||||
}
|
||||
|
||||
/*
|
||||
Copyright (c) 2010-2012 Ivan Vanderbyl
|
||||
Originally found at http://ivan.ly/ui
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
/* Webkit animation keyframes */
|
||||
@-webkit-keyframes animate-stripes {
|
||||
to {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
from {
|
||||
background-position: 44px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes animate-stripes {
|
||||
to {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
from {
|
||||
background-position: 36px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bar which is placed behind the progress */
|
||||
.ui-progress-bar {
|
||||
/* Usual setup stuff */
|
||||
position: relative;
|
||||
width: 240px;
|
||||
margin: 15px auto 10px;
|
||||
height: 8px;
|
||||
/* Pad right so we don't cover the borders when fully progressed */
|
||||
/* For browser that don't support gradients, we'll set a blanket background colour */
|
||||
background-color: rgba(157, 167, 171, 0.42);
|
||||
.border-radius(~"10px");
|
||||
}
|
||||
.ui-progress-bar.blue .ui-progress {
|
||||
background-color: #339BB9!important;
|
||||
border: 1px solid #287a91;
|
||||
}
|
||||
.ui-progress-bar.error .ui-progress {
|
||||
background-color: #C43C35 !important;
|
||||
border: 1px solid #9c302a;
|
||||
}
|
||||
.ui-progress-bar.warning .ui-progress {
|
||||
background-color: #D9B31A!important;
|
||||
border: 1px solid #ab8d15;
|
||||
}
|
||||
.ui-progress-bar.success .ui-progress {
|
||||
background-color: #57A957!important;
|
||||
border: 1px solid #458845;
|
||||
}
|
||||
.ui-progress-bar.transition .ui-progress {
|
||||
.transition(~"background-color 0.5s ease-in, border-color 1.5s ease-out, box-shadow 1.5s ease-out")
|
||||
}
|
||||
.ui-progress-bar .ui-progress {
|
||||
/* Usual setup stuff */
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
/* Height should be 2px less than .ui-progress-bar so as to not cover borders and give it a look of being inset */
|
||||
height: 8px;
|
||||
/* Rounds the ends, we specify an excessive amount to make sure they are completely rounded */
|
||||
/* Adjust to your liking, and don't forget to adjust to the same amount in .ui-progress-bar */
|
||||
.border-radius(~"10px");
|
||||
/* Webkit background stripes and gradient */
|
||||
background: -webkit-gradient(linear, 0 0, 44 44, color-stop(0, rgba(0, 0, 0, 0.17)), color-stop(0.25, rgba(0, 0, 0, 0.17)), color-stop(0.26, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.51, rgba(0, 0, 0, 0.17)), color-stop(0.75, rgba(0, 0, 0, 0.17)), color-stop(0.76, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0))), -webkit-gradient(linear, left bottom, left top, color-stop(0, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0.35))), #EAF9FF;
|
||||
background: -moz-repeating-linear-gradient(top left -30deg, rgba(0, 0, 0, 0.17), rgba(0, 0, 0, 0.17) 15px, rgba(0, 0, 0, 0) 15px, rgba(0, 0, 0, 0) 30px), -moz-linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 100%), #EAF9FF;
|
||||
|
||||
/* Set the background size so the stripes work correctly */
|
||||
-webkit-background-size: 44px 44px;
|
||||
-moz-background-size: 36px 36px;
|
||||
|
||||
/* Animate */
|
||||
-moz-animation: animate-stripes 2s linear infinite;
|
||||
-webkit-animation: animate-stripes 2s linear infinite;
|
||||
-o-animation: animate-stripes 2s linear infinite;
|
||||
-ms-animation: animate-stripes 2s linear infinite;
|
||||
-khtml-animation: animate-stripes 2s linear infinite;
|
||||
animation: animate-stripes 2s linear infinite;
|
||||
|
||||
/* Style status label */
|
||||
top:0px;
|
||||
left:0px;
|
||||
}
|
||||
.dark .ui-progress-bar .ui-progress {
|
||||
background: -webkit-gradient(linear, 0 0, 44 44, color-stop(0, rgba(0, 0, 0, 0.17)), color-stop(0.25, rgba(0, 0, 0, 0.17)), color-stop(0.26, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.51, rgba(0, 0, 0, 0.17)), color-stop(0.75, rgba(0, 0, 0, 0.17)), color-stop(0.76, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0))), -webkit-gradient(linear, left bottom, left top, color-stop(0, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0.35))), #4ACBFD;
|
||||
background: -moz-repeating-linear-gradient(top left -30deg, rgba(0, 0, 0, 0.17), rgba(0, 0, 0, 0.17) 15px, rgba(0, 0, 0, 0) 15px, rgba(0, 0, 0, 0) 30px), -moz-linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 100%), #4ACBFD;
|
||||
|
||||
/* Set the background size so the stripes work correctly */
|
||||
-webkit-background-size: 44px 44px;
|
||||
-moz-background-size: 36px 36px;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<div id="c9_ide_restore">
|
||||
<div class="timeout">This is taking longer than expected. If you think there might be an issue please contact <a href="https://c9.io/support">support</a>.</div>
|
||||
<div id="loadingide"></div>
|
||||
<div class="stickynote">
|
||||
<div class="tape"></div>
|
||||
<div class="left-shadow"></div>
|
||||
<div class="right-shadow"></div>
|
||||
|
||||
<div class="paper">
|
||||
<strong>What's going on here?</strong>
|
||||
<p>
|
||||
We create a separate virtual machine for each workspace.
|
||||
In order to provide a free
|
||||
service for everyone, we hibernate workspaces of
|
||||
<nobr>non-premium</nobr> users after about one week of inactivity.
|
||||
This is because the virtual machines constantly use resources even if
|
||||
the workspace is not actively used.
|
||||
<p>
|
||||
Please wait a moment while we wake up your workspace. It will
|
||||
be just as you left it.
|
||||
<p>
|
||||
<a href="/upgrade/webide" target="_blank">Upgrade to premium</a> to make sure your workspace never
|
||||
goes into hibernate.
|
||||
</div>
|
||||
</div>
|
||||
<div id="restoring">
|
||||
<div id="content" class="loading-progress">
|
||||
<div class="loading-details"></div>
|
||||
<div class="ui-progress-bar ui-container" id="progress_bar">
|
||||
<div class="ui-progress" style="width: 100%;">
|
||||
<!--<span class="ui-label" style="display:none;"></span>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="loading-msg">Waking up your workspace from hibernation.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,298 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
main.consumes = [
|
||||
"Plugin", "ui", "vfs.endpoint", "vfs", "layout", "anims", "c9",
|
||||
"c9.analytics", "layout"
|
||||
];
|
||||
main.provides = ["restore"];
|
||||
return main;
|
||||
|
||||
function main(options, imports, register) {
|
||||
var Plugin = imports.Plugin;
|
||||
var ui = imports.ui;
|
||||
var vfs = imports.vfs;
|
||||
var c9 = imports.c9;
|
||||
var anims = imports.anims;
|
||||
var layout = imports.layout;
|
||||
var endpoint = imports["vfs.endpoint"];
|
||||
var analytics = imports["c9.analytics"];
|
||||
|
||||
/***** Initialization *****/
|
||||
|
||||
var plugin = new Plugin("Ajax.org", main.consumes);
|
||||
var el, msgEl, detailsEl, descriptionEl, stickynoteEl, uiProgress;
|
||||
var timeoutTimer, timeoutEl;
|
||||
|
||||
var MAX_HOT_WORKSPACES = "three";
|
||||
var TIMEOUT_TIME = 15 * 60 * 1000;
|
||||
|
||||
var STATE_CREATED = 1;
|
||||
var STATE_READY = 2;
|
||||
var STATE_MIGRATING = 4;
|
||||
var STATE_MARKED_FOR_ARCHIVE = 20;
|
||||
var STATE_ARCHIVING = 21;
|
||||
var STATE_ARCHIVED = 22;
|
||||
var STATE_MARKED_FOR_RESTORE = 23;
|
||||
var STATE_RESTORING = 24;
|
||||
var STATE_RESIZING = 31;
|
||||
|
||||
var stateMessages = {};
|
||||
stateMessages[STATE_CREATED] = "Creating your new workspace";
|
||||
stateMessages[STATE_READY] = "Starting your workspace";
|
||||
stateMessages[STATE_MIGRATING] = "Migrating your workspace to our new backend";
|
||||
stateMessages[STATE_MARKED_FOR_ARCHIVE] =
|
||||
stateMessages[STATE_ARCHIVING] = "Archiving your workspace";
|
||||
stateMessages[STATE_ARCHIVED] =
|
||||
stateMessages[STATE_MARKED_FOR_RESTORE] =
|
||||
stateMessages[STATE_RESTORING] = "Waking up your workspace from hibernation.";
|
||||
stateMessages[STATE_RESIZING] = "Resizing your workspace";
|
||||
var defaultStateMessage = "Opening your workspace";
|
||||
|
||||
var description =
|
||||
"<strong>You could be coding right now</strong>\n" +
|
||||
"<p>\n" +
|
||||
"In order to provide a free\n" +
|
||||
"service for everyone, we stop workspaces after a while.\n" +
|
||||
"<p>\n" +
|
||||
"Premium plans offer active workspaces, which ensure that the " + MAX_HOT_WORKSPACES + "\n" +
|
||||
"most recently used workspaces are never stopped.\n" +
|
||||
"<p>\n" +
|
||||
"<a class='restore-upsell' data-link-id='upsell-webide-migrate' href='" + options.ideBaseUrl + "/account/upgrade/webide' target='_blank'>Upgrade to premium now</a>";
|
||||
|
||||
var premiumStoppedDescription =
|
||||
"<strong>Swapping in Workspace</strong>\n" +
|
||||
"<p>\n" +
|
||||
"This workspace is not one of your active workspaces and has been stopped.\n" +
|
||||
"<p>\n" +
|
||||
"The " + MAX_HOT_WORKSPACES + " most recently used workspaces are never stopped.\n" +
|
||||
"<p>\n" +
|
||||
"As part of a team plan you have more active workspaces.\n" +
|
||||
"<p>\n" +
|
||||
"<a class='restore-upsell' data-link-id='upsell-teams-migrate' href='" + options.ideBaseUrl + "/account/billing' target='_blank'>Upgrade to team plans now</a>";
|
||||
|
||||
var migrateDescription =
|
||||
"<strong>What's going on here?</strong>\n" +
|
||||
"<p>\n" +
|
||||
"We rolled out a completely new backend infrastructure with \n" +
|
||||
"improved performance and lots of new features.\n" +
|
||||
"<p>\n" +
|
||||
"With the new backend you get:\n" +
|
||||
"<ul>\n" +
|
||||
"<li>an Ubuntu VM</li>\n" +
|
||||
"<li>root access using sudo</li>\n" +
|
||||
"<li>ability to run services</li>\n" +
|
||||
"<li>ability to install packages</li>\n" +
|
||||
"</ul>\n" +
|
||||
"<p>\n" +
|
||||
"Please wait a moment while we move your workspace. It will\n" +
|
||||
"be just as you left it.\n";
|
||||
|
||||
var premiumDescription =
|
||||
"<strong>What's going on here?</strong>\n" +
|
||||
"<p>\n" +
|
||||
"We're migrating your premium workspace to a new server \n" +
|
||||
"to ensure optimal performance.\n" +
|
||||
"<p>\n" +
|
||||
"Please wait a moment while we move your workspace. It will\n" +
|
||||
"be just as you left it.\n";
|
||||
|
||||
var resizeDescription =
|
||||
"<strong>What's going on here?</strong>\n" +
|
||||
"<p>\n" +
|
||||
"We're resizing your workspace\n" +
|
||||
"to be exactly as you specified.\n" +
|
||||
"<p>\n" +
|
||||
"Please wait a moment while we resize your workspace.\n" +
|
||||
"It will be just as you left it.\n";
|
||||
|
||||
var stateDescriptions = {
|
||||
free: { casual: [STATE_MIGRATING, STATE_RESIZING] },
|
||||
premium: { casual: [STATE_MIGRATING, STATE_MARKED_FOR_ARCHIVE, STATE_ARCHIVING, STATE_ARCHIVED, STATE_MARKED_FOR_RESTORE, STATE_RESTORING, STATE_RESIZING] },
|
||||
};
|
||||
|
||||
stateDescriptions.free[STATE_CREATED] = "";
|
||||
stateDescriptions.free[STATE_READY] = description;
|
||||
stateDescriptions.free[STATE_MIGRATING] = migrateDescription; // different location
|
||||
stateDescriptions.free[STATE_MARKED_FOR_ARCHIVE] = description;
|
||||
stateDescriptions.free[STATE_ARCHIVING] = description;
|
||||
stateDescriptions.free[STATE_ARCHIVED] = description;
|
||||
stateDescriptions.free[STATE_MARKED_FOR_RESTORE] = description;
|
||||
stateDescriptions.free[STATE_RESTORING] = description;
|
||||
stateDescriptions.free[STATE_RESIZING] = resizeDescription; // different location
|
||||
|
||||
stateDescriptions.premium[STATE_CREATED] = "";
|
||||
stateDescriptions.premium[STATE_READY] = premiumStoppedDescription;
|
||||
stateDescriptions.premium[STATE_MIGRATING] = migrateDescription; // different location
|
||||
stateDescriptions.premium[STATE_MARKED_FOR_ARCHIVE] = premiumDescription; // different location
|
||||
stateDescriptions.premium[STATE_ARCHIVING] = premiumDescription; // different location
|
||||
stateDescriptions.premium[STATE_ARCHIVED] = premiumDescription; // different location
|
||||
stateDescriptions.premium[STATE_MARKED_FOR_RESTORE] = premiumDescription; // different location
|
||||
stateDescriptions.premium[STATE_RESTORING] = premiumDescription; // different location
|
||||
stateDescriptions.premium[STATE_RESIZING] = resizeDescription; // different location
|
||||
|
||||
var loaded = false;
|
||||
function load() {
|
||||
if (loaded) return false;
|
||||
loaded = true;
|
||||
|
||||
endpoint.on("restore", showRestore);
|
||||
vfs.on("connect", hideRestore);
|
||||
}
|
||||
|
||||
var drawn = false;
|
||||
function draw() {
|
||||
if (drawn) return false;
|
||||
drawn = true;
|
||||
|
||||
ui.insertCss(require("text!./restore.css"), plugin);
|
||||
ui.insertHtml(null, require("text!./restore.html"), plugin);
|
||||
|
||||
el = document.getElementById("c9_ide_restore");
|
||||
msgEl = document.querySelector("#c9_ide_restore .loading-msg");
|
||||
detailsEl = document.querySelector("#c9_ide_restore .loading-details");
|
||||
descriptionEl = document.querySelector("#c9_ide_restore .paper");
|
||||
stickynoteEl = document.querySelector("#c9_ide_restore .stickynote");
|
||||
uiProgress = document.querySelector("#progress_bar .ui-progress");
|
||||
timeoutEl = document.querySelector("#c9_ide_restore .timeout");
|
||||
}
|
||||
|
||||
/***** Methods *****/
|
||||
|
||||
var progress, maxProgress, run = 0, timer;
|
||||
|
||||
function animateProgress(progress, callback) {
|
||||
anims.animate(uiProgress, {
|
||||
width: progress + "%",
|
||||
timingFunction: "cubic-bezier(.02, .01, .47, 1)",
|
||||
duration: "1s"
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function walk(loopId) {
|
||||
if (loopId != run) return;
|
||||
|
||||
if (progress > 100)
|
||||
return;
|
||||
|
||||
if (progress > maxProgress)
|
||||
return (timer = setTimeout(walk.bind(null, loopId), 500));
|
||||
|
||||
animateProgress(progress++, function(){
|
||||
timer = setTimeout(walk.bind(null, loopId), 10);
|
||||
});
|
||||
}
|
||||
|
||||
function showTimeout(){
|
||||
timeoutEl.style.display = "block";
|
||||
}
|
||||
|
||||
function showRestore(state) {
|
||||
draw();
|
||||
|
||||
c9.startLoadTime = -1;
|
||||
|
||||
if (el.style.display != "block") {
|
||||
uiProgress.style.width = 0;
|
||||
progress = 6;
|
||||
maxProgress = 10;
|
||||
}
|
||||
|
||||
var isDark = layout.theme.indexOf("dark") > -1;
|
||||
if (isDark)
|
||||
el.classList.add("dark");
|
||||
else
|
||||
el.classList.remove("dark");
|
||||
|
||||
var descriptions = stateDescriptions[state.premium ? "premium" : "free"];
|
||||
var description = descriptions[state.projectState || STATE_ARCHIVED];
|
||||
msgEl.innerText = stateMessages[state.projectState || STATE_ARCHIVED] || defaultStateMessage;
|
||||
|
||||
if (description) {
|
||||
descriptionEl.innerHTML = description;
|
||||
var link = descriptionEl.querySelector("a.restore-upsell");
|
||||
if (link)
|
||||
link.addEventListener("click", trackLink, false);
|
||||
|
||||
stickynoteEl.style.display = "block";
|
||||
|
||||
if (~descriptions.casual.indexOf(state.projectState || STATE_ARCHIVED))
|
||||
stickynoteEl.classList.add("casual");
|
||||
else
|
||||
stickynoteEl.classList.remove("casual");
|
||||
}
|
||||
else {
|
||||
stickynoteEl.style.display = "none";
|
||||
}
|
||||
|
||||
// we did not receive JSON
|
||||
if (!state.progress || state.progress.nextProgress == 100)
|
||||
return hideRestore();
|
||||
|
||||
// Display Message to the User
|
||||
if (!/^Internal/.test(state.progress.message))
|
||||
detailsEl.innerText = state.progress.message || "";
|
||||
|
||||
// Update Progress Bar
|
||||
maxProgress = Math.max(maxProgress || 0, state.progress.nextProgress);
|
||||
progress = Math.max(progress || 0, state.progress.progress);
|
||||
|
||||
walk(++run);
|
||||
|
||||
// Show Restore Screen
|
||||
el.style.display = "block";
|
||||
|
||||
clearTimeout(timeoutTimer);
|
||||
timeoutTimer = setTimeout(function(){
|
||||
showTimeout();
|
||||
}, TIMEOUT_TIME)
|
||||
}
|
||||
|
||||
function trackLink(e) {
|
||||
var el = e.target;
|
||||
analytics.track("Clicked Internal Link", {
|
||||
href: el.href,
|
||||
linkId: el.dataset.linkId
|
||||
});
|
||||
}
|
||||
|
||||
function hideRestore() {
|
||||
if (!el) return;
|
||||
|
||||
clearTimeout(timer);
|
||||
|
||||
progress = 101;
|
||||
animateProgress(100, function(){
|
||||
setTimeout(function(){
|
||||
anims.animate(el, {
|
||||
opacity: 0
|
||||
}, function(){
|
||||
el.style.display = "none";
|
||||
el.style.opacity = 1;
|
||||
|
||||
timeoutEl.style.display = "";
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/***** Lifecycle *****/
|
||||
|
||||
plugin.on("load", function(){
|
||||
load();
|
||||
});
|
||||
|
||||
/***** Register and define API *****/
|
||||
|
||||
/**
|
||||
*
|
||||
**/
|
||||
plugin.freezePublicAPI({
|
||||
show: showRestore,
|
||||
hide: hideRestore
|
||||
});
|
||||
|
||||
register(null, { "restore" : plugin });
|
||||
}
|
||||
});
|
|
@ -205,8 +205,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
// Make sure home dir is marked correctly
|
||||
path = path.replace(reHome, "~");
|
||||
if (path[0] != "/") path = "/" + path;
|
||||
path = util.normalizePath(path);
|
||||
|
||||
fs.stat(path, function(err, stat) {
|
||||
if (err) {
|
||||
|
|
|
@ -251,7 +251,7 @@ define(function(require, exports, module) {
|
|||
|
||||
fsCache.model.getTooltipText = function(node) {
|
||||
var size = node.size;
|
||||
return node.label + (node.link ? " => " + node.link + "\n" : "")
|
||||
return (node.label || node.path) + (node.link ? " => " + node.link + "\n" : "")
|
||||
+ (size != undefined && !node.isFolder ? " | " + (
|
||||
size < 0x400 ? size + " bytes" :
|
||||
size < 0x100000 ? (size / 0x400).toFixed(2) + "KB" :
|
||||
|
|
|
@ -614,6 +614,8 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
|
|||
});
|
||||
});
|
||||
it('should copy a node', function(done) {
|
||||
expect(fsCache.findNode("/dir/test.html")).to.ok;
|
||||
expect(fsCache.findNode("/test.html")).to.not.ok;
|
||||
tree.copy(
|
||||
[fsCache.findNode("/dir/test.html")],
|
||||
fsCache.findNode("/"),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
define(function(require, exports, module) {
|
||||
main.consumes = [
|
||||
"Plugin", "fs", "settings", "preferences", "watcher", "tabManager",
|
||||
"save", "dialog.question", "dialog.filechange", "threewaymerge"
|
||||
"save", "dialog.question", "dialog.filechange", "threewaymerge", "collab"
|
||||
];
|
||||
main.provides = ["watcher.gui"];
|
||||
return main;
|
||||
|
@ -17,8 +17,15 @@ define(function(require, exports, module) {
|
|||
var question = imports["dialog.question"];
|
||||
var filechange = imports["dialog.filechange"];
|
||||
var threeWayMerge = imports.threewaymerge.merge;
|
||||
var collab = imports.collab;
|
||||
|
||||
var collabEnabled = options.collab;
|
||||
|
||||
var comparisonType = {
|
||||
TIMESTAMP_AND_CONTENTS: "TIMESTAMP_AND_CONTENTS",
|
||||
CONTENTS: "CONTENTS",
|
||||
NONE: "NONE"
|
||||
};
|
||||
|
||||
/***** Initialization *****/
|
||||
|
||||
|
@ -87,14 +94,14 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
if (tab.classList.contains("conflict")) {
|
||||
addChangedTab(tab, true);
|
||||
addChangedTab(tab, comparisonType.TIMESTAMP_AND_CONTENTS);
|
||||
}
|
||||
});
|
||||
|
||||
tabManager.on("open", function(e) {
|
||||
initializeDocument(e.tab.document);
|
||||
if (e.tab.classList.contains("conflict")) {
|
||||
addChangedTab(e.tab, true);
|
||||
addChangedTab(e.tab, comparisonType.TIMESTAMP_AND_CONTENTS);
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
|
@ -119,33 +126,42 @@ define(function(require, exports, module) {
|
|||
|
||||
// Hook watcher events
|
||||
|
||||
// Update a file
|
||||
// A change event sent from the watcher plugin
|
||||
watcher.on("change", function(e) {
|
||||
var tab = tabManager.findTab(e.path);
|
||||
if (tab) {
|
||||
// If collab picks this up and handles the change it will return false
|
||||
if (emit("docChange", {tab: tab}) === false)
|
||||
return;
|
||||
if (collabEnabled && tab.editorType == "ace") {
|
||||
/* If the lastChange (added by collab) was greater than 1 second ago set up a watch
|
||||
To ensure that collab makes this change, if not report an error. The lastChange
|
||||
check is to avoid a race condition if collab updates before this function runs */
|
||||
if (!tab.meta.$lastCollabChange || tab.meta.$lastCollabChange < (Date.now() - 1000)) {
|
||||
if (tab.meta.$collabChangeRegistered) {
|
||||
clearTimeout(tab.meta.$collabChangeRegistered);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
addChangedTab(tab, e.type === "change");
|
||||
addChangedTab(tab, comparisonType.TIMESTAMP_AND_CONTENTS);
|
||||
}
|
||||
});
|
||||
|
||||
// Directory watcher is not needed if the normal watcher works
|
||||
// watcher.on("directory", function(e) {
|
||||
// var base = e.path;
|
||||
// var files = e.files;
|
||||
//
|
||||
// // Rename all tabs
|
||||
// tabManager.getTabs().forEach(function(tab) {
|
||||
// if (tab.path && tab.path.indexOf(base) == 0) {
|
||||
// // If the file is gone, lets notify the user
|
||||
// if (files.indexOf(tab.path) == -1) {
|
||||
// resolveFileDelete(tab);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
collab.on("change", function (e) {
|
||||
var tab = tabManager.findTab(e.path);
|
||||
if (tab) {
|
||||
addChangedTab(tab, comparisonType.NONE);
|
||||
}
|
||||
});
|
||||
|
||||
collab.on("resolveConflict", function (e) {
|
||||
var tab = tabManager.findTab(e.path);
|
||||
if (tab) {
|
||||
var doc = tab.document;
|
||||
var path = tab.path
|
||||
resolveConflict(doc, path);
|
||||
}
|
||||
})
|
||||
|
||||
watcher.on("delete", function(e) {
|
||||
var tab = tabManager.findTab(e.path);
|
||||
|
@ -156,7 +172,13 @@ define(function(require, exports, module) {
|
|||
|
||||
/***** Methods *****/
|
||||
|
||||
function addChangedTab(tab, isSameFile) {
|
||||
function resolveConflict(doc, path) {
|
||||
doc.tab.classList.remove("conflict");
|
||||
delete doc.meta.$merge;
|
||||
delete changedPaths[path];
|
||||
}
|
||||
|
||||
function addChangedTab(tab, doubleCheckComparisonType) {
|
||||
// If we already have a dialog open, just update it, but mark the value dirty
|
||||
if (changedPaths[tab.path]) {
|
||||
if (changedPaths[tab.path].data)
|
||||
|
@ -171,6 +193,9 @@ define(function(require, exports, module) {
|
|||
return;
|
||||
}
|
||||
|
||||
var doc = tab.document;
|
||||
var path = tab.path;
|
||||
|
||||
changedPaths[tab.path] = { tab: tab, resolve: resolve };
|
||||
|
||||
// If the terminal is currently focussed, lets wait until
|
||||
|
@ -178,25 +203,28 @@ define(function(require, exports, module) {
|
|||
if (tabManager.focussedTab
|
||||
&& tabManager.focussedTab.editorType == "terminal") {
|
||||
tabManager.once("focus", function(){
|
||||
addChangedTab(tab, false);
|
||||
addChangedTab(tab, comparisonType.CONTENTS);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
function resolve() {
|
||||
console.log("[watchers] resolved change event without dialog", path);
|
||||
doc.tab.classList.remove("conflict");
|
||||
delete doc.meta.$merge;
|
||||
delete changedPaths[path];
|
||||
if (collabEnabled && collab.send)
|
||||
collab.send({type: "RESOLVE_CONFLICT", data: {docId: path}});
|
||||
resolveConflict(doc, path);
|
||||
}
|
||||
|
||||
var doc = tab.document;
|
||||
var path = tab.path;
|
||||
|
||||
if (isSameFile)
|
||||
checkByStatOrContents();
|
||||
else
|
||||
checkByContents();
|
||||
switch (doubleCheckComparisonType) {
|
||||
case comparisonType.TIMESTAMP_AND_CONTENTS:
|
||||
checkByStatOrContents();
|
||||
break;
|
||||
case comparisonType.CONTENTS:
|
||||
checkByContents();
|
||||
break;
|
||||
case comparisonType.NONE:
|
||||
dialog();
|
||||
break;
|
||||
}
|
||||
|
||||
function dialog(data) {
|
||||
if (!changedPaths[path])
|
||||
|
@ -293,7 +321,6 @@ define(function(require, exports, module) {
|
|||
function automerge(tab, data) {
|
||||
if (!settings.getBool("user/general/@automerge"))
|
||||
return false;
|
||||
|
||||
return merge(tab, data);
|
||||
}
|
||||
|
||||
|
@ -313,8 +340,10 @@ define(function(require, exports, module) {
|
|||
doc.meta.$mergeRoot = data;
|
||||
|
||||
// If the value on disk is the same as in the document, set the bookmark
|
||||
if (mergedValue == data)
|
||||
if (mergedValue == data) {
|
||||
doc.undoManager.bookmark();
|
||||
save.save(tab);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -339,6 +368,7 @@ define(function(require, exports, module) {
|
|||
var doc = tab.document;
|
||||
doc.setBookmarkedValue(data, true);
|
||||
doc.meta.timestamp = Date.now() - settings.timeOffset;
|
||||
save.save(tab);
|
||||
changedPaths[path].resolve();
|
||||
}
|
||||
|
||||
|
@ -579,9 +609,10 @@ define(function(require, exports, module) {
|
|||
question.show(
|
||||
"Always merge?",
|
||||
"Always merge on file changes?",
|
||||
"Enabling 'auto merge' makes it very easy to collaborate on "
|
||||
+ "files with other people, especially when combined with "
|
||||
+ "'auto save'. This setting can be controlled from the "
|
||||
"With 'auto merge' enabled, if a file changes "
|
||||
+ "on disk and you have unsaved changes in the IDE, "
|
||||
+ "it will automatically attempt to merge your changes with the new file. "
|
||||
+ "This setting can be controlled from the "
|
||||
+ "settings panel as well.",
|
||||
function() { // on yes
|
||||
if (question.dontAsk)
|
||||
|
|
|
@ -17,6 +17,7 @@ define(function(require, exports, module) {
|
|||
var https = require("https");
|
||||
var http = require("http");
|
||||
var mime = require("mime");
|
||||
var Cache = require("c9/cache");
|
||||
var metrics = imports.metrics;
|
||||
var parseUrl = require("url").parse;
|
||||
var debug = require("debug")("preview");
|
||||
|
@ -24,43 +25,25 @@ define(function(require, exports, module) {
|
|||
|
||||
var staticPrefix = imports["connect.static"].getStaticPrefix();
|
||||
|
||||
function getProjectSession() {
|
||||
function getRole(db) {
|
||||
var roleCache = new Cache(10000, 10000);
|
||||
|
||||
return function(req, res, next) {
|
||||
var session = req.session;
|
||||
|
||||
req.user = req.user || { id: -1 };
|
||||
|
||||
var username = req.params.username;
|
||||
var projectname = req.params.projectname;
|
||||
|
||||
var ws = req.ws = username + "/" + projectname;
|
||||
|
||||
if (!session.ws)
|
||||
session.ws = {};
|
||||
|
||||
req.projectSession = session.ws[ws];
|
||||
|
||||
if (
|
||||
!req.projectSession ||
|
||||
!req.projectSession.expires ||
|
||||
req.projectSession.expires <= Date.now() ||
|
||||
req.projectSession.uid != req.user.id
|
||||
) {
|
||||
req.projectSession = session.ws[ws] = {
|
||||
expires: Date.now() + 10000
|
||||
if (!req.user) {
|
||||
req.user = {
|
||||
id: -1
|
||||
};
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
function getRole(db) {
|
||||
return function(req, res, next) {
|
||||
if (req.projectSession.role) {
|
||||
req.session = {};
|
||||
|
||||
var key = req.params.username + "/" + req.params.projectname + ":" + req.user.id;
|
||||
|
||||
var wsSession = roleCache.get(key);
|
||||
if (wsSession) {
|
||||
req.session = wsSession;
|
||||
return next();
|
||||
}
|
||||
|
||||
|
||||
db.Project.findOne({
|
||||
username: req.params.username,
|
||||
name: req.params.projectname
|
||||
|
@ -70,25 +53,27 @@ define(function(require, exports, module) {
|
|||
|
||||
if (err) return next(err);
|
||||
|
||||
project.getRole(req.user, function(err, role) {
|
||||
project.getRole(req.user.id, function(err, role) {
|
||||
if (err) return next(err);
|
||||
|
||||
var wsSession = {
|
||||
role: role,
|
||||
pid: project.id,
|
||||
uid: req.user.id,
|
||||
type: project.scm
|
||||
};
|
||||
|
||||
roleCache.set(key, wsSession);
|
||||
req.session = wsSession;
|
||||
|
||||
if (role == db.Project.ROLE_NONE) {
|
||||
if (project.isPublicPreview())
|
||||
role = db.Project.ROLE_VISITOR;
|
||||
else if (req.user.id == -1)
|
||||
return next(new error.Unauthorized());
|
||||
else
|
||||
return next(new error.Forbidden("You don't have access rights to preview this workspace"));
|
||||
if (!project.isPublicPreview())
|
||||
return next();
|
||||
|
||||
wsSession.role = db.Project.ROLE_VISITOR;
|
||||
}
|
||||
req.projectSession.role = role;
|
||||
req.projectSession.pid = project.id;
|
||||
req.projectSession.uid = req.user.id;
|
||||
|
||||
var type = project.scm;
|
||||
req.projectSession.type = type;
|
||||
|
||||
if (type != "docker" || project.state != db.Project.STATE_READY)
|
||||
if (wsSession.type != "docker" || project.state != db.Project.STATE_READY)
|
||||
return next();
|
||||
|
||||
project.populate("remote", function(err) {
|
||||
|
@ -100,10 +85,8 @@ define(function(require, exports, module) {
|
|||
if (err) return next(err);
|
||||
|
||||
if (container.state == db.Container.STATE_RUNNING)
|
||||
req.projectSession.proxyUrl = "http://" + meta.host + ":9000/" + meta.cid + "/home/ubuntu/workspace";
|
||||
else
|
||||
req.projectSession.expires = Date.now() + 1000;
|
||||
|
||||
wsSession.proxyUrl = "http://" + meta.host + ":9000/" + meta.cid + "/home/ubuntu/workspace";
|
||||
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
|
@ -114,26 +97,41 @@ define(function(require, exports, module) {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
function checkRole(db) {
|
||||
return function(req, res, next) {
|
||||
var role = req.session.role;
|
||||
|
||||
if (role == db.Project.ROLE_NONE) {
|
||||
if (req.user.id == -1)
|
||||
return next(new error.Unauthorized());
|
||||
else
|
||||
return next(new error.Forbidden("You don't have access rights to preview this workspace"));
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
function getProxyUrl(getServer) {
|
||||
return function(req, res, next) {
|
||||
|
||||
if (req.projectSession.proxyUrl) {
|
||||
req.proxyUrl = req.projectSession.proxyUrl;
|
||||
|
||||
if (req.session.proxyUrl) {
|
||||
req.proxyUrl = req.session.proxyUrl;
|
||||
return next();
|
||||
}
|
||||
|
||||
var server = req.projectSession.vfsServer;
|
||||
var server = req.session.vfsServer;
|
||||
if (!server) {
|
||||
server = getServer();
|
||||
if (!server || !server.url)
|
||||
return next(new error.ServiceUnavailable("No VFS server found"));
|
||||
|
||||
server = req.projectSession.vfsServer = server.internalUrl || server.url;
|
||||
server = req.session.vfsServer = server.internalUrl || server.url;
|
||||
}
|
||||
|
||||
var url = server + "/" + req.projectSession.pid + "/preview";
|
||||
|
||||
var url = server + "/" + req.session.pid + "/preview";
|
||||
|
||||
req.proxyUrl = url;
|
||||
next();
|
||||
};
|
||||
|
@ -222,9 +220,6 @@ define(function(require, exports, module) {
|
|||
} else if (body.indexOf("ENOENT") !== -1 || statusCode == 404) {
|
||||
next(new error.NotFound("File '" + path + "' could not be found!"));
|
||||
} else {
|
||||
if (req.session.ws)
|
||||
delete req.session.ws[req.ws];
|
||||
|
||||
var json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
|
@ -365,8 +360,8 @@ define(function(require, exports, module) {
|
|||
|
||||
register(null, {
|
||||
"preview.handler": {
|
||||
getProjectSession: getProjectSession,
|
||||
getRole: getRole,
|
||||
checkRole: checkRole,
|
||||
getProxyUrl: getProxyUrl,
|
||||
proxyCall: proxyCall
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ define(function(require, exports, module) {
|
|||
"use strict";
|
||||
|
||||
main.consumes = [
|
||||
"session",
|
||||
"connect",
|
||||
"db",
|
||||
"c9.login",
|
||||
"preview.handler",
|
||||
|
@ -14,13 +14,12 @@ define(function(require, exports, module) {
|
|||
return main;
|
||||
|
||||
function main(options, imports, register) {
|
||||
var session = imports.session;
|
||||
var connect = imports.connect;
|
||||
var db = imports.db;
|
||||
var ensureLoggedIn = imports["c9.login"].ensureLoggedIn();
|
||||
var handler = imports["preview.handler"];
|
||||
var userContent = imports["user-content.redirect"];
|
||||
var getVfsServers = imports["vfs.serverlist"].getServers;
|
||||
var ratelimit = require("c9/ratelimit");
|
||||
|
||||
var frontdoor = require("frontdoor");
|
||||
var error = require("http-error");
|
||||
|
@ -38,7 +37,7 @@ define(function(require, exports, module) {
|
|||
|
||||
api.use(userContent.redirectPreview());
|
||||
|
||||
session.use(api);
|
||||
connect.use(api);
|
||||
|
||||
api.get("/:username/:projectname/:path*", {
|
||||
params: {
|
||||
|
@ -53,8 +52,8 @@ define(function(require, exports, module) {
|
|||
requestTimeout(15*60*1000),
|
||||
require("./lib/middleware/sanitize-path-param"),
|
||||
require("./lib/middleware/block-dot-files"),
|
||||
handler.getProjectSession(),
|
||||
handler.getRole(db),
|
||||
handler.checkRole(db),
|
||||
handler.getProxyUrl(function() {
|
||||
return getVfsServers()[0] || null;
|
||||
}),
|
||||
|
@ -63,8 +62,6 @@ define(function(require, exports, module) {
|
|||
|
||||
api.error(function(err, req, res, next) {
|
||||
if (err instanceof error.Unauthorized) {
|
||||
req.logout();
|
||||
delete req.session.token;
|
||||
return ensureLoggedIn(req, res, next);
|
||||
}
|
||||
return next(err);
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
#!/usr/bin/env node
|
||||
/*global describe it before after beforeEach afterEach */
|
||||
|
||||
"use strict";
|
||||
"use server";
|
||||
|
||||
require("c9/inline-mocha")(module);
|
||||
require("c9/setup_paths");
|
||||
|
||||
var async = require("async");
|
||||
var assert = require("assert");
|
||||
var nock = require("nock");
|
||||
|
||||
var RestClient = require("c9/rest_client");
|
||||
var baseTest = require('../c9.api/base_test');
|
||||
var testDb = require("../c9.db.redis/test_redis");
|
||||
var setupFixtures = require("test/lib/integration/setup");
|
||||
|
||||
describe(__filename, function() {
|
||||
|
||||
var db, serverList, client;
|
||||
var testUser, testProject, testRemote, testContainer;
|
||||
var loggedInUser = null;
|
||||
|
||||
before(function(next) {
|
||||
baseTest({
|
||||
config: "preview",
|
||||
}, function(err, services) {
|
||||
db = services.db;
|
||||
serverList = services["vfs.serverlist"];
|
||||
|
||||
services.connect.useSetup(function(req, res, next) {
|
||||
req.user = loggedInUser;
|
||||
next();
|
||||
});
|
||||
|
||||
client = new RestClient("localhost", services.apiPort, {
|
||||
debug: false
|
||||
});
|
||||
|
||||
testUser = require("test/lib/integration/db/user")(db);
|
||||
testProject = require("test/lib/integration/db/project")(db);
|
||||
testRemote = require("test/lib/integration/db/mock-remote")(db);
|
||||
testContainer = require("test/lib/integration/db/mock-container")(db);
|
||||
|
||||
next(err);
|
||||
});
|
||||
});
|
||||
|
||||
after(function(next) {
|
||||
testDb.stop(next);
|
||||
});
|
||||
|
||||
beforeEach(function(next) {
|
||||
serverList._testSetServerList([{
|
||||
url: "http://vfs.c9.dev",
|
||||
internalUrl: "http://vfs.c9.dev"
|
||||
}]);
|
||||
testDb.reset(next);
|
||||
});
|
||||
|
||||
describe("preview", function() {
|
||||
it("Should authorize users correctly", function(next) {
|
||||
var user1, user2;
|
||||
var public1, private1, private2;
|
||||
|
||||
// user1 user2
|
||||
// user2/public
|
||||
// user2/private1 user1 has no access
|
||||
// user2/private2 user1 is collaborator
|
||||
|
||||
setupFixtures(
|
||||
testUser.create(),
|
||||
testUser.create(),
|
||||
testProject.create(),
|
||||
testRemote.create({type: "docker"}),
|
||||
testContainer.create(),
|
||||
testProject.create(),
|
||||
testRemote.create({type: "docker"}),
|
||||
testContainer.create(),
|
||||
testProject.create(),
|
||||
testRemote.create({type: "docker"}),
|
||||
testContainer.create(),
|
||||
function(ctx, next) {
|
||||
user1 = ctx.users[0];
|
||||
user2 = ctx.users[1];
|
||||
public1 = ctx.projects[0];
|
||||
private1 = ctx.projects[1];
|
||||
private2 = ctx.projects[2];
|
||||
next();
|
||||
},
|
||||
function(ctx, next) {
|
||||
public1.owner = user2;
|
||||
public1.visibility = "public";
|
||||
public1.save(next);
|
||||
},
|
||||
function(ctx, next) {
|
||||
private1.owner = user2;
|
||||
private1.visibility = "private";
|
||||
private1.save(next);
|
||||
},
|
||||
function(ctx, next) {
|
||||
private2.owner = user2;
|
||||
private2.visibility = "private";
|
||||
private2.save(next);
|
||||
},
|
||||
function(ctx, next) {
|
||||
db.WorkspaceMember.create(
|
||||
private2,
|
||||
user1.id,
|
||||
db.WorkspaceMember.ACL_R,
|
||||
db.Project.ROLE_COLLABORATOR, null, next
|
||||
);
|
||||
},
|
||||
function(fixtures, teardown) {
|
||||
/*
|
||||
* Logged in Role Visibility ACTION
|
||||
* =================================================================
|
||||
* true none public view
|
||||
* false none public view
|
||||
* true none private forbidden
|
||||
* false none private unauthorized
|
||||
* true visitor/collaborator/admin public view
|
||||
* true visitor/collaborator/admin private view
|
||||
*/
|
||||
|
||||
var expect = [
|
||||
{ uid: user1.id, role: db.Project.ROLE_NONE, p: public1, code: 200 },
|
||||
{ uid: -1, role: db.Project.ROLE_NONE, p: public1, code: 200 },
|
||||
{ uid: user1.id, role: db.Project.ROLE_NONE, p: private1, code: 403 },
|
||||
{ uid: -1, role: db.Project.ROLE_NONE, p: private1, code: 302 }, // redirect to login page
|
||||
{ uid: user1.id, role: db.Project.ROLE_COLLABORATOR, p: public1, code: 200 },
|
||||
{ uid: user2.id, role: db.Project.ROLE_ADMIN, p: private2, code: 200 }
|
||||
];
|
||||
|
||||
async.eachSeries(expect, function(expect, next) {
|
||||
var path = "/" + expect.p.owner.name + "/" + expect.p.name + "/";
|
||||
|
||||
nock('http://vfs.c9.dev')
|
||||
.get("/" + expect.p.id + "/preview/")
|
||||
.reply(200, []);
|
||||
|
||||
loggedInUser = {
|
||||
id: expect.uid
|
||||
};
|
||||
|
||||
client.get(path, function (err, res) {
|
||||
assert((err && err.code) == expect.code || expect.code == 200, "Wrong return code");
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err) return next(err);
|
||||
teardown(next);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -149,16 +149,16 @@ function plugin(options, imports, register) {
|
|||
return next();
|
||||
|
||||
res.writeHead(200, {"Content-Type": "application/javascript"});
|
||||
res.end("define(function(require, exports, module) { return '"
|
||||
+ options.workspaceDir + "'; });");
|
||||
res.end("define(function(require, exports, module) { return "
|
||||
+ JSON.stringify(options.workspaceDir.replace(/\\/g, "/")) + "; });");
|
||||
});
|
||||
api.get("/vfs-home", function(req, res, next) {
|
||||
if (!options.options.testing)
|
||||
return next();
|
||||
|
||||
res.writeHead(200, {"Content-Type": "application/javascript"});
|
||||
res.end("define(function(require, exports, module) { return '"
|
||||
+ process.env.HOME + "'; });");
|
||||
res.end("define(function(require, exports, module) { return "
|
||||
+ JSON.stringify(process.env.HOME.replace(/\\/g, "/")) + "; });");
|
||||
});
|
||||
|
||||
api.get("/update", function(req, res, next) {
|
||||
|
|
|
@ -446,6 +446,7 @@ require([
|
|||
"metrics": {
|
||||
getLastPing: function() { throw Error("Not implemented"); },
|
||||
getLastest: function() { throw Error("Not implemented"); },
|
||||
onPingComplete: function() { throw Error("Not implemented"); },
|
||||
log: function() {},
|
||||
increment: function() {}
|
||||
},
|
||||
|
|
|
@ -82,7 +82,7 @@ updatePackage() {
|
|||
}
|
||||
|
||||
updateAllPackages() {
|
||||
c9packages=(`"$NODE" -e 'console.log(Object.keys(require("./package.json").c9plugins).join(" "))'`)
|
||||
c9packages=`"$NODE" -e 'console.log(Object.keys(require("./package.json").c9plugins).join(" "))'`;
|
||||
count=${#c9packages[@]}
|
||||
i=0
|
||||
for m in ${c9packages[@]}; do echo $m;
|
||||
|
@ -95,7 +95,7 @@ updateAllPackages() {
|
|||
updateNodeModules() {
|
||||
echo "${magenta}--- Running npm install --------------------------------------------${resetColor}"
|
||||
safeInstall(){
|
||||
deps=(`"$NODE" -e 'console.log(Object.keys(require("./package.json").dependencies).join(" "))'`)
|
||||
deps=`"$NODE" -e 'console.log(Object.keys(require("./package.json").dependencies).join(" "))'`;
|
||||
for m in ${deps[@]}; do echo $m;
|
||||
"$NPM" install --loglevel warn $m || true
|
||||
done
|
||||
|
|
|
@ -91,8 +91,10 @@ function main(argv, config, onLoaded) {
|
|||
var configs = options.argv._;
|
||||
if (!configs.length)
|
||||
configs = [config || DEFAULT_CONFIG];
|
||||
if (options.argv.exclude && !Array.isArray(options.argv.exclude.length))
|
||||
options.argv.exclude = [options.argv.exclude];
|
||||
|
||||
var exclude = options.argv.exclude || [];
|
||||
if (typeof exclude == "string")
|
||||
exclude = exclude.split(",");
|
||||
|
||||
var expanded = expandShortCuts(configs);
|
||||
|
||||
|
@ -120,7 +122,7 @@ function main(argv, config, onLoaded) {
|
|||
|
||||
function startConfigs(configs, done) {
|
||||
async.each(configs, function(config, next) {
|
||||
if (options.argv.exclude && options.argv.exclude.indexOf(config) > -1)
|
||||
if (exclude && exclude.indexOf(config) > -1)
|
||||
return next();
|
||||
start(config, options, function(err, result, path) {
|
||||
onLoaded && onLoaded(err, result, path);
|
||||
|
|
|
@ -125,7 +125,6 @@ module.exports = function(manifest, installPath) {
|
|||
}
|
||||
},
|
||||
pricing: { containers: [] },
|
||||
zuora: {},
|
||||
localExtend: true,
|
||||
extendDirectory: __dirname + "/../plugins"
|
||||
};
|
||||
|
@ -155,4 +154,6 @@ function readWin32Settings() {
|
|||
if (!fs.existsSync(path.join(process.env.HOME, ".c9", "msys/bin/bash.exe")))
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
process.env.CHERE_INVOKING = 1; // prevent cygwin from changing bash path
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue