Merge branch 'pull/2269'
This commit is contained in:
commit
b66fb6def8
6 changed files with 274 additions and 71 deletions
|
|
@ -169,13 +169,44 @@ function loadDoc(name, callback) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveDoc(name, callback) {
|
||||||
|
var doc = fileCache[name] || name;
|
||||||
|
if (!doc || !doc.session)
|
||||||
|
return callback("Unknown document: " + name);
|
||||||
|
|
||||||
|
var path = doc.path;
|
||||||
|
var parts = path.split("/");
|
||||||
|
if (parts[0] == "docs")
|
||||||
|
path = "demo/kitchen-sink/" + path;
|
||||||
|
else if (parts[0] == "ace")
|
||||||
|
path = "lib/" + path;
|
||||||
|
|
||||||
|
upload(path, doc.session.getValue(), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function upload(url, data, callback) {
|
||||||
|
url = net.qualifyURL(url);
|
||||||
|
if (!/https?:/.test(url))
|
||||||
|
return callback(new Error("Unsupported url scheme"));
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("PUT", url, true);
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
callback(!/^2../.test(xhr.status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
fileCache: fileCache,
|
fileCache: fileCache,
|
||||||
docs: sort(prepareDocList(docs)),
|
docs: sort(prepareDocList(docs)),
|
||||||
ownSource: prepareDocList(ownSource),
|
ownSource: prepareDocList(ownSource),
|
||||||
hugeDocs: prepareDocList(hugeDocs),
|
hugeDocs: prepareDocList(hugeDocs),
|
||||||
initDoc: initDoc,
|
initDoc: initDoc,
|
||||||
loadDoc: loadDoc
|
loadDoc: loadDoc,
|
||||||
|
saveDoc: saveDoc,
|
||||||
};
|
};
|
||||||
module.exports.all = {
|
module.exports.all = {
|
||||||
"Mode Examples": module.exports.docs,
|
"Mode Examples": module.exports.docs,
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ var AbapHighlightRules = function() {
|
||||||
{token : "string", regex : "`", next : "start"},
|
{token : "string", regex : "`", next : "start"},
|
||||||
{defaultToken : "string"}
|
{defaultToken : "string"}
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
oop.inherits(AbapHighlightRules, TextHighlightRules);
|
oop.inherits(AbapHighlightRules, TextHighlightRules);
|
||||||
|
|
||||||
|
|
|
||||||
113
static.js
113
static.js
|
|
@ -10,37 +10,100 @@ var http = require("http")
|
||||||
|
|
||||||
// compatibility with node 0.6
|
// compatibility with node 0.6
|
||||||
if (!fs.exists)
|
if (!fs.exists)
|
||||||
fs.exists = path.exists;
|
fs.exists = path.exists;
|
||||||
|
|
||||||
http.createServer(function(request, response) {
|
var allowSave = process.argv.indexOf("--allow-save") != -1;
|
||||||
|
|
||||||
var uri = url.parse(request.url).pathname
|
http.createServer(function(req, res) {
|
||||||
, filename = path.join(process.cwd(), uri);
|
var uri = url.parse(req.url).pathname
|
||||||
|
, filename = path.join(process.cwd(), uri);
|
||||||
fs.exists(filename, function(exists) {
|
|
||||||
if(!exists) {
|
if (req.method == "PUT") {
|
||||||
response.writeHead(404, {"Content-Type": "text/plain"});
|
if (!allowSave)
|
||||||
response.write("404 Not Found\n");
|
return error(res, 404, "Saving not allowed pass --allow-save to enable");
|
||||||
response.end();
|
save(req, res, filename);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs.statSync(filename).isDirectory()) filename += '/index.html';
|
fs.exists(filename, function(exists) {
|
||||||
|
if (!exists)
|
||||||
|
return error(res, 404, "404 Not Found\n");
|
||||||
|
|
||||||
fs.readFile(filename, "binary", function(err, file) {
|
if (fs.statSync(filename).isDirectory()) {
|
||||||
if(err) {
|
var files = fs.readdirSync(filename);
|
||||||
response.writeHead(500, {"Content-Type": "text/plain"});
|
res.writeHead(200, {"Content-Type": "text/html"});
|
||||||
response.write(err + "\n");
|
|
||||||
response.end();
|
files.push(".", "..");
|
||||||
return;
|
var html = files.map(function(name) {
|
||||||
}
|
var href = uri + "/" + name;
|
||||||
|
href = href.replace(/[\/\\]+/g, "/").replace(/\/$/g, "");
|
||||||
|
if (fs.statSync(filename + "/" + name + "/").isDirectory())
|
||||||
|
href += "/";
|
||||||
|
return "<a href='" + href + "'>" + name + "</a><br>";
|
||||||
|
});
|
||||||
|
|
||||||
var contentType = mime.lookup(filename) || "text/plain";
|
res._hasBody && res.write(html.join(""));
|
||||||
response.writeHead(200, {"Content-Type": contentType});
|
res.end();
|
||||||
response.write(file, "binary");
|
return;
|
||||||
response.end();
|
}
|
||||||
|
|
||||||
|
fs.readFile(filename, "binary", function(err, file) {
|
||||||
|
if (err) {
|
||||||
|
res.writeHead(500, { "Content-Type": "text/plain" });
|
||||||
|
res.write(err + "\n");
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contentType = mime.lookup(filename) || "text/plain";
|
||||||
|
res.writeHead(200, { "Content-Type": contentType });
|
||||||
|
res.write(file, "binary");
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}).listen(port, ip);
|
}).listen(port, ip);
|
||||||
|
|
||||||
console.log("http://localhost:" + port);
|
function error(res, status, message, error) {
|
||||||
|
console.error(error || message);
|
||||||
|
res.writeHead(status, { "Content-Type": "text/plain" });
|
||||||
|
res.write(message);
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
function save(req, res, filePath) {
|
||||||
|
var data = "";
|
||||||
|
req.on("data", function(chunk) {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
req.on("error", function() {
|
||||||
|
error(res, 404, "Could't save file");
|
||||||
|
});
|
||||||
|
req.on("end", function() {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(filePath, data);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return error(res, 404, "Could't save file", e);
|
||||||
|
}
|
||||||
|
res.statusCode = 200;
|
||||||
|
res.end("OK");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLocalIps() {
|
||||||
|
var os = require("os");
|
||||||
|
|
||||||
|
var interfaces = os.networkInterfaces ? os.networkInterfaces() : {};
|
||||||
|
var addresses = [];
|
||||||
|
for (var k in interfaces) {
|
||||||
|
for (var k2 in interfaces[k]) {
|
||||||
|
var address = interfaces[k][k2];
|
||||||
|
if (address.family === "IPv4" && !address.internal) {
|
||||||
|
addresses.push(address.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("http://" + (ip == "0.0.0.0" ? getLocalIps()[0] : ip) + ":" + port);
|
||||||
|
|
||||||
|
|
|
||||||
136
static.py
136
static.py
|
|
@ -32,7 +32,9 @@ import time
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
from os import path, stat, getcwd
|
from os import path, stat, getcwd
|
||||||
|
from fnmatch import fnmatch
|
||||||
from wsgiref import util
|
from wsgiref import util
|
||||||
|
from wsgiref.validate import validator
|
||||||
from wsgiref.headers import Headers
|
from wsgiref.headers import Headers
|
||||||
from wsgiref.simple_server import make_server
|
from wsgiref.simple_server import make_server
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
@ -84,6 +86,8 @@ class Cling(object):
|
||||||
not_modified = StatusApp('304 Not Modified', "")
|
not_modified = StatusApp('304 Not Modified', "")
|
||||||
moved_permanently = StatusApp('301 Moved Permanently')
|
moved_permanently = StatusApp('301 Moved Permanently')
|
||||||
method_not_allowed = StatusApp('405 Method Not Allowed')
|
method_not_allowed = StatusApp('405 Method Not Allowed')
|
||||||
|
success_no_content = StatusApp('204 No Content', "")
|
||||||
|
server_error = StatusApp('500 Internal Server Error')
|
||||||
|
|
||||||
def __init__(self, root, **kw):
|
def __init__(self, root, **kw):
|
||||||
"""Just set the root and any other attribs passes via **kw."""
|
"""Just set the root and any other attribs passes via **kw."""
|
||||||
|
|
@ -93,9 +97,6 @@ class Cling(object):
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
"""Respond to a request when called in the usual WSGI way."""
|
"""Respond to a request when called in the usual WSGI way."""
|
||||||
if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'):
|
|
||||||
headers = [('Allow', 'GET, HEAD')]
|
|
||||||
return self.method_not_allowed(environ, start_response, headers)
|
|
||||||
path_info = environ.get('PATH_INFO', '')
|
path_info = environ.get('PATH_INFO', '')
|
||||||
full_path = self._full_path(path_info)
|
full_path = self._full_path(path_info)
|
||||||
if not self._is_under_root(full_path):
|
if not self._is_under_root(full_path):
|
||||||
|
|
@ -109,6 +110,23 @@ class Cling(object):
|
||||||
return self.moved_permanently(environ, start_response, headers)
|
return self.moved_permanently(environ, start_response, headers)
|
||||||
else:
|
else:
|
||||||
full_path = self._full_path(path_info + self.index_file)
|
full_path = self._full_path(path_info + self.index_file)
|
||||||
|
try:
|
||||||
|
sz = int(environ['CONTENT_LENGTH'])
|
||||||
|
except:
|
||||||
|
sz = 0
|
||||||
|
if environ['REQUEST_METHOD'] == 'PUT' and sz > 0:
|
||||||
|
for putglob in self.puttable:
|
||||||
|
if fnmatch(path_info, putglob):
|
||||||
|
data = environ['wsgi.input'].read(sz)
|
||||||
|
try:
|
||||||
|
with open(full_path, "wb") as f: f.write(data)
|
||||||
|
return self.success_no_content(environ, start_response)
|
||||||
|
except:
|
||||||
|
print sys.exc_info()[1]
|
||||||
|
return self.server_error(environ, start_response)
|
||||||
|
if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'):
|
||||||
|
headers = [('Allow', 'GET, HEAD')]
|
||||||
|
return self.method_not_allowed(environ, start_response, headers)
|
||||||
content_type = self._guess_type(full_path)
|
content_type = self._guess_type(full_path)
|
||||||
try:
|
try:
|
||||||
etag, last_modified = self._conditions(full_path, environ)
|
etag, last_modified = self._conditions(full_path, environ)
|
||||||
|
|
@ -191,52 +209,90 @@ def cling_wrap(package_name, dir_name, **kw):
|
||||||
|
|
||||||
|
|
||||||
def command():
|
def command():
|
||||||
parser = OptionParser(usage="%prog DIR [HOST][:][PORT]",
|
usage = "%prog [--help] [-d DIR] [-l [HOST][:PORT]] [-p GLOB[,GLOB...]]"
|
||||||
version="static 0.3.6")
|
parser = OptionParser(usage=usage, version="static 0.3.6")
|
||||||
|
parser.add_option("-d", "--dir", dest="rootdir", default=".",
|
||||||
|
help="Root directory to serve. Defaults to '.' .", metavar="DIR")
|
||||||
|
parser.add_option("-l", "--listen", dest="listen", default="127.0.0.1:8888",
|
||||||
|
help="Listen on this interface (given by its hostname or IP) and port."+
|
||||||
|
" HOST defaults to 127.0.0.1. PORT defaults to 8888. "+
|
||||||
|
"Leave HOST empty to listen on all interfaces (INSECURE!).",
|
||||||
|
metavar="[HOST][:PORT]")
|
||||||
|
parser.add_option("-p", "--puttable", dest="puttable", default="",
|
||||||
|
help="Comma or space-separated list of request paths for which to"+
|
||||||
|
" permit PUT requests. Each path is a glob pattern that may "+
|
||||||
|
"contain wildcard characters '*' and/or '?'. "+
|
||||||
|
"'*' matches any sequence of characters, including the empty"+
|
||||||
|
" string. '?' matches exactly 1 arbitrary character. "+
|
||||||
|
"NOTE: Both '*' and '?' match slashes and dots. "+
|
||||||
|
"I.e. --puttable=* makes every file under DIR writable!",
|
||||||
|
metavar="GLOB[,GLOB...]")
|
||||||
|
parser.add_option("--validate", dest="validate", action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Enable HTTP validation. You don't need this unless "+
|
||||||
|
"you're developing static.py itself.")
|
||||||
|
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
if len(args) in (1, 2):
|
if len(args) > 0:
|
||||||
if len(args) == 2:
|
|
||||||
parts = args[1].split(":")
|
|
||||||
if len(parts) == 1:
|
|
||||||
host = parts[0]
|
|
||||||
port = None
|
|
||||||
elif len(parts) == 2:
|
|
||||||
host, port = parts
|
|
||||||
else:
|
|
||||||
sys.exit("Invalid host:port specification.")
|
|
||||||
elif len(args) == 1:
|
|
||||||
host, port = None, None
|
|
||||||
if not host:
|
|
||||||
host = '0.0.0.0'
|
|
||||||
if not port:
|
|
||||||
port = 8888
|
|
||||||
try:
|
|
||||||
port = int(port)
|
|
||||||
except:
|
|
||||||
sys.exit("Invalid host:port specification.")
|
|
||||||
app = Cling(args[0])
|
|
||||||
try:
|
|
||||||
make_server(host, port, app).serve_forever()
|
|
||||||
except KeyboardInterrupt, ki:
|
|
||||||
print "Cio, baby!"
|
|
||||||
except:
|
|
||||||
sys.exit("Problem initializing server.")
|
|
||||||
else:
|
|
||||||
parser.print_help(sys.stderr)
|
parser.print_help(sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
parts = options.listen.split(":")
|
||||||
|
if len(parts) == 1:
|
||||||
|
try: # if the the listen argument consists only of a port number
|
||||||
|
port = int(parts[0])
|
||||||
|
host = None
|
||||||
|
except: # could not parse as port number => must be a host IP or name
|
||||||
|
host = parts[0]
|
||||||
|
port = None
|
||||||
|
elif len(parts) == 2:
|
||||||
|
host, port = parts
|
||||||
|
else:
|
||||||
|
sys.exit("Invalid host:port specification.")
|
||||||
|
|
||||||
def test():
|
if not host:
|
||||||
from wsgiref.validate import validator
|
host = '0.0.0.0'
|
||||||
app = Cling(getcwd())
|
if not port:
|
||||||
|
port = 8888
|
||||||
try:
|
try:
|
||||||
print "Serving " + getcwd() + " to http://localhost:8888"
|
port = int(port)
|
||||||
make_server('0.0.0.0', 8888, validator(app)).serve_forever()
|
if port <= 0 or port > 65535: raise ValueError
|
||||||
|
except:
|
||||||
|
sys.exit("Invalid host:port specification.")
|
||||||
|
|
||||||
|
puttable = set(path.abspath(p) for p in
|
||||||
|
options.puttable.replace(","," ").split())
|
||||||
|
if puttable and host not in ('127.0.0.1', 'localhost'):
|
||||||
|
print("Permitting PUT access for non-localhost connections may be unwise.")
|
||||||
|
|
||||||
|
options.rootdir = path.abspath(options.rootdir)
|
||||||
|
|
||||||
|
for p in puttable:
|
||||||
|
if not p.startswith(options.rootdir):
|
||||||
|
sys.exit("puttable path '%s' not under root '%s'" % (p, options.rootdir))
|
||||||
|
|
||||||
|
# cut off root prefix from puttable paths
|
||||||
|
puttable = set(p[len(options.rootdir):] for p in puttable)
|
||||||
|
|
||||||
|
app = Cling(options.rootdir, puttable=puttable)
|
||||||
|
|
||||||
|
if options.validate:
|
||||||
|
app = validator(app)
|
||||||
|
|
||||||
|
try:
|
||||||
|
print "Serving %s to http://%s:%d" % (options.rootdir, host, port)
|
||||||
|
if puttable:
|
||||||
|
print("The following paths (relative to server root) may be "+
|
||||||
|
"OVERWRITTEN via HTTP PUT.")
|
||||||
|
for p in puttable:
|
||||||
|
print p
|
||||||
|
make_server(host, port, app).serve_forever()
|
||||||
except KeyboardInterrupt, ki:
|
except KeyboardInterrupt, ki:
|
||||||
print ""
|
|
||||||
print "Ciao, baby!"
|
print "Ciao, baby!"
|
||||||
|
except:
|
||||||
|
sys.exit("Problem initializing server: %s" % sys.exc_info()[1])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test()
|
command()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
border-bottom: solid 1px;
|
border-bottom: solid 1px;
|
||||||
}
|
}
|
||||||
.separator-h {
|
.separator-h {
|
||||||
padding: 0 20px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
#closeBtn {
|
#closeBtn {
|
||||||
background: rgba(245, 146, 146, 0.5);
|
background: rgba(245, 146, 146, 0.5);
|
||||||
|
|
@ -59,6 +59,7 @@
|
||||||
<select id="modeEl" size="1"></select>
|
<select id="modeEl" size="1"></select>
|
||||||
<input type="button" value="⟳" title="sync" id="syncToMode"></select>
|
<input type="button" value="⟳" title="sync" id="syncToMode"></select>
|
||||||
<span id="tablist"></span>
|
<span id="tablist"></span>
|
||||||
|
<input type="button" value="Save" id="saveButton1"></select>
|
||||||
<span class="separator-h"></span>
|
<span class="separator-h"></span>
|
||||||
<label for="autorunEl">live preview</label>
|
<label for="autorunEl">live preview</label>
|
||||||
<input type="checkbox" label="autorun" id="autorunEl" checked>
|
<input type="checkbox" label="autorun" id="autorunEl" checked>
|
||||||
|
|
@ -70,6 +71,7 @@
|
||||||
<label for="themeEl">Theme</label>
|
<label for="themeEl">Theme</label>
|
||||||
<select id="themeEl" size="1" value="textmate"></select>
|
<select id="themeEl" size="1" value="textmate"></select>
|
||||||
<span class="separator-h"></span>
|
<span class="separator-h"></span>
|
||||||
|
<input type="button" value="Save" id="saveButton2"></select>
|
||||||
<label for="doc">Document</label>
|
<label for="doc">Document</label>
|
||||||
<select id="doc" size="1"></select>
|
<select id="doc" size="1"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ util.bindDropdown("doc", function(value) {
|
||||||
doclist.loadDoc(value, function(session) {
|
doclist.loadDoc(value, function(session) {
|
||||||
if (session) {
|
if (session) {
|
||||||
editor2.setSession(session);
|
editor2.setSession(session);
|
||||||
|
session.getUndoManager().markClean();
|
||||||
|
updateSaveButtonState(null, editor2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -60,6 +62,7 @@ util.bindDropdown("doc", function(value) {
|
||||||
var modeEl = document.getElementById("modeEl");
|
var modeEl = document.getElementById("modeEl");
|
||||||
util.fillDropdown(modeEl, modelist.modes);
|
util.fillDropdown(modeEl, modelist.modes);
|
||||||
var modeSessions = {};
|
var modeSessions = {};
|
||||||
|
|
||||||
util.bindDropdown(modeEl, function(value) {
|
util.bindDropdown(modeEl, function(value) {
|
||||||
if (modeSessions[value]) {
|
if (modeSessions[value]) {
|
||||||
editor1.setSession(modeSessions[value]);
|
editor1.setSession(modeSessions[value]);
|
||||||
|
|
@ -68,14 +71,18 @@ util.bindDropdown(modeEl, function(value) {
|
||||||
}
|
}
|
||||||
var hp = "./lib/ace/mode/" + value + "_highlight_rules.js";
|
var hp = "./lib/ace/mode/" + value + "_highlight_rules.js";
|
||||||
net.get(hp, function(text) {
|
net.get(hp, function(text) {
|
||||||
text = util.stripLeadingComments(text);
|
|
||||||
|
|
||||||
var session = new EditSession(text);
|
var session = new EditSession(text);
|
||||||
session.setUndoManager(new UndoManager());
|
session.setUndoManager(new UndoManager());
|
||||||
|
|
||||||
modeSessions[value] = session;
|
modeSessions[value] = session;
|
||||||
session.setMode("ace/mode/javascript");
|
session.setMode("ace/mode/javascript", function() {
|
||||||
|
if (session.getLine(0).match(/^\s*\//))
|
||||||
|
session.toggleFoldWidget(0); // fold licence comment
|
||||||
|
});
|
||||||
|
|
||||||
editor1.setSession(modeSessions[value]);
|
editor1.setSession(modeSessions[value]);
|
||||||
|
session.getUndoManager().markClean();
|
||||||
|
updateSaveButtonState(null, editor1);
|
||||||
schedule();
|
schedule();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -85,6 +92,50 @@ document.getElementById("syncToMode").onclick = function() {
|
||||||
docEl.onchange();
|
docEl.onchange();
|
||||||
run();
|
run();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
editor1.saveButton = document.getElementById("saveButton1");
|
||||||
|
editor2.saveButton = document.getElementById("saveButton2");
|
||||||
|
editor1.saveButton.editor = editor1;
|
||||||
|
editor2.saveButton.editor = editor2;
|
||||||
|
|
||||||
|
editor1.saveButton.onclick = function() {
|
||||||
|
doclist.saveDoc({
|
||||||
|
path: "./lib/ace/mode/" + modeEl.value + "_highlight_rules.js",
|
||||||
|
session: editor1.session
|
||||||
|
}, function(err) {
|
||||||
|
handleSaveResult(err, editor1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
editor1.commands.bindKey({
|
||||||
|
win: "Ctrl-S", mac: "Cmd-s"
|
||||||
|
}, editor1.saveButton.onclick);
|
||||||
|
editor2.saveButton.onclick = function() {
|
||||||
|
doclist.saveDoc(docEl.value, function(err) {
|
||||||
|
handleSaveResult(err, editor2);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
editor2.commands.bindKey({
|
||||||
|
win: "Ctrl-S", mac: "Cmd-s"
|
||||||
|
}, editor2.saveButton.onclick);
|
||||||
|
function updateSaveButtonState(e, editor){
|
||||||
|
editor.saveButton.disabled = editor.session.getUndoManager().isClean();
|
||||||
|
}
|
||||||
|
editor1.on("input", updateSaveButtonState);
|
||||||
|
editor2.on("input", updateSaveButtonState);
|
||||||
|
|
||||||
|
function handleSaveResult(err, editor) {
|
||||||
|
if (err) {
|
||||||
|
return log(
|
||||||
|
"Write access to this file is disabled.\n"+
|
||||||
|
"To enable saving your changes to disk, clone the Ace repository\n"+
|
||||||
|
"and run the included web server with the --allow-write option\n"+
|
||||||
|
"`node static.js --allow-write` or `static.py --puttable=*`"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
editor.session.getUndoManager().markClean();
|
||||||
|
updateSaveButtonState(null, editor);
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById("perfTest").onclick = function() {
|
document.getElementById("perfTest").onclick = function() {
|
||||||
var lines = editor2.session.doc.getAllLines();
|
var lines = editor2.session.doc.getAllLines();
|
||||||
if (!lines.length)
|
if (!lines.length)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue