Merge remote-tracking branch 'remotes/origin/master'

This commit is contained in:
nightwing 2015-01-18 23:44:18 +04:00
commit 8c4173ba11
58 changed files with 7233 additions and 923 deletions

View file

@ -31,13 +31,15 @@
define(function(require, exports, module) { define(function(require, exports, module) {
var dom = require("ace/lib/dom"); var dom = require("ace/lib/dom");
var Range = require("ace/range").Range; var Range = require("ace/range").Range;
// allow easy access to ace in console, but not in ace code which uses strict
function isStrict() {
try { return !arguments.callee.caller.caller.caller}
catch(e){ return true }
}
function warn() { function warn() {
if (isStrict()) { var s = (new Error()).stack || "";
s = s.split("\n");
if (s[1] == "Error") s.shift(); // remove error description on chrome
s.shift(); // remove warn
s.shift(); // remove the getter
s = s.join("\n");
// allow easy access to ace in console, but not in ace code
if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}/.test(s)) {
console.error("trying to access to global variable"); console.error("trying to access to global variable");
} }
} }

View file

@ -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,

View file

@ -0,0 +1,171 @@
%abc-2.1
H:This file contains some example English tunes
% note that the comments (like this one) are to highlight usages
% and would not normally be included in such detail
O:England % the origin of all tunes is England
X:1 % tune no 1
T:Dusty Miller, The % title
T:Binny's Jig % an alternative title
C:Trad. % traditional
R:DH % double hornpipe
M:3/4 % meter
K:G % key
B>cd BAG|FA Ac BA|B>cd BAG|DG GB AG:|
Bdd gfg|aA Ac BA|Bdd gfa|gG GB AG:|
BG G/2G/2G BG|FA Ac BA|BG G/2G/2G BG|DG GB AG:|
W:Hey, the dusty miller, and his dusty coat;
W:He will win a shilling, or he spend a groat.
W:Dusty was the coat, dusty was the colour;
W:Dusty was the kiss, that I got frae the miller.
X:2
T:Old Sir Simon the King
C:Trad.
S:Offord MSS % from Offord manuscript
N:see also Playford % reference note
M:9/8
R:SJ % slip jig
N:originally in C % transcription note
K:G
D|GFG GAG G2D|GFG GAG F2D|EFE EFE EFG|A2G F2E D2:|
D|GAG GAB d2D|GAG GAB c2D|[1 EFE EFE EFG|[A2G] F2E D2:|\ % no line-break in score
M:12/8 % change of meter
[2 E2E EFE E2E EFG|\ % no line-break in score
M:9/8 % change of meter
A2G F2E D2|]
X:3
T:William and Nancy
T:New Mown Hay
T:Legacy, The
C:Trad.
O:England; Gloucs; Bledington % place of origin
B:Sussex Tune Book % can be found in these books
B:Mally's Cotswold Morris vol.1 2
D:Morris On % can be heard on this record
P:(AB)2(AC)2A % play the parts in this order
M:6/8
K:G
[P:A] D|"G"G2G GBd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
[P:B] d|"G"e2d B2d|"C"gfe "G"d2d| "G"e2d B2d|"C"gfe "D7"d2c|
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
% changes of meter, using inline fields
[T:Slows][M:4/4][L:1/4][P:C]"G"d2|"C"e2 "G"d2|B2 d2|"Em"gf "A7"e2|"D7"d2 "G"d2|\
"C"e2 "G"d2|[M:3/8][L:1/8] "G"B2 d |[M:6/8] "C"gfe "D7"d2c|
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
X:4
T:South Downs Jig
R:jig
S:Robert Harbron
M:6/8
L:1/8
K:G
|: d | dcA G3 | EFG AFE | DEF GAB | cde d2d |
dcA G3 | EFG AFE | DEF GAB | cAF G2 :|
B | Bcd e2c | d2B c2A | Bcd e2c | [M:9/8]d2B c2B A3 |
[M:6/8]DGF E3 | cBA FED | DEF GAB |1 cAF G2 :|2 cAF G3 |]
X:5
T:Atholl Brose
% in this example, which reproduces Highland Bagpipe gracing,
% the large number of grace notes mean that it is more convenient to be specific about
% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them
I:linebreak $
K:D
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
{gcd}c<{e}A {gAGAG}A>e {ag}a>f {gef}e>d|
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
{g}c/d/e {g}G>{d}B {gf}gG {dc}d>B:|$
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
{g}c<e {gf}g>e {ag}a2 {GdG}a>d|
{g}c<e {gf}g>e {ag}a>e {gf}g>f|
{gef}e>d {gf}g>d {gBd}B<{e}G {dc}d>B|
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
{g}c<e {gf}g>e {ag}a2 {GdG}ad|
{g}c<{GdG}e {gf}ga {f}g>e {g}f>d|
{g}e/f/g {Gdc}d>c {gBd}B<{e}G {dc}d2|]
X:6
T:Untitled Reel
C:Trad.
K:D
eg|a2ab ageg|agbg agef|g2g2 fgag|f2d2 d2:|\
ed|cecA B2ed|cAcA E2ed|cecA B2ed|c2A2 A2:|
K:G
AB|cdec BcdB|ABAF GFE2|cdec BcdB|c2A2 A2:|
X:7
T:Kitchen Girl
C:Trad.
K:D
[c4a4] [B4g4]|efed c2cd|e2f2 gaba|g2e2 e2fg|
a4 g4|efed cdef|g2d2 efed|c2A2 A4:|
K:G
ABcA BAGB|ABAG EDEG|A2AB c2d2|e3f edcB|ABcA BAGB|
ABAG EGAB|cBAc BAG2|A4 A4:|
%abc-2.1
%%pagewidth 21cm
%%pageheight 29.7cm
%%topspace 0.5cm
%%topmargin 1cm
%%botmargin 0cm
%%leftmargin 1cm
%%rightmargin 1cm
%%titlespace 0cm
%%titlefont Times-Bold 32
%%subtitlefont Times-Bold 24
%%composerfont Times 16
%%vocalfont Times-Roman 14
%%staffsep 60pt
%%sysstaffsep 20pt
%%musicspace 1cm
%%vocalspace 5pt
%%measurenb 0
%%barsperstaff 5
%%scale 0.7
X: 1
T: Canzonetta a tre voci
C: Claudio Monteverdi (1567-1643)
M: C
L: 1/4
Q: "Andante mosso" 1/4 = 110
%%score [1 2 3]
V: 1 clef=treble name="Soprano"sname="A"
V: 2 clef=treble name="Alto" sname="T"
V: 3 clef=bass middle=d name="Tenor" sname="B"
%%MIDI program 1 75 % recorder
%%MIDI program 2 75
%%MIDI program 3 75
K: Eb
% 1 - 4
[V: 1] |:z4 |z4 |f2ec |_ddcc |
w: Son que-sti~i cre-spi cri-ni~e
w: Que-sti son gli~oc-chi che mi-
[V: 2] |:c2BG|AAGc|(F/G/A/B/)c=A|B2AA |
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e
w: Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi-
[V: 3] |:z4 |f2ec|_ddcf |(B/c/_d/e/)ff|
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il
w: Que-sti son~gli oc-chi che mi-ran - - - - do
% 5 - 9
[V: 1] cAB2 |cAAA |c3B|G2!fermata!Gz ::e4|
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
w: ran-do fi-so, tut-to re-stai con-qui-so.
[V: 2] AAG2 |AFFF |A3F|=E2!fermata!Ez::c4|
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
w: ran-do fi-so tut-to re-stai con-qui-so.
[V: 3] (ag/f/e2)|A_ddd|A3B|c2!fermata!cz ::A4|
w: vi - - - so ond' io ti-man-go~uc-ci-so. Deh,
w: fi - - - so tut-to re-stai con-qui-so.
% 10 - 15
[V: 1] f_dec |B2c2|zAGF |\
w: dim-me-lo ben mi-o, che que-sto\
=EFG2 |1F2z2:|2F8|] % more notes
w: sol de-si-o_. % more lyrics
[V: 2] ABGA |G2AA|GF=EF |(GF3/2=E//D//E)|1F2z2:|2F8|]
w: dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_.
[V: 3] _dBc>d|e2AF|=EFc_d|c4 |1F2z2:|2F8|]
w: dim-me-lo ben mi-o, che que-sto sol de-si-o_.

View file

@ -20,7 +20,7 @@ class Range
end end
end end
{:id => 34, :key => "value"} {:id => ?", :key => "value"}
herDocs = [<<'FOO', <<BAR, <<-BAZ, <<-`EXEC`] #comment herDocs = [<<'FOO', <<BAR, <<-BAZ, <<-`EXEC`] #comment

View file

@ -53,16 +53,16 @@ require("ace/commands/default_commands").commands.push({
return; return;
} }
var rowCount = 10; var rowCount = 10;
var w = { var w = {
row: row, row: row,
// rowCount: rowCount, // rowCount: rowCount,
fixedWidth: true, fixedWidth: true,
el: dom.createElement("div"), el: dom.createElement("div"),
editor: editor editor: inlineEditor
}; };
var el = w.el; var el = w.el;
el.appendChild(inlineEditor.container); el.appendChild(inlineEditor.container);
if (!editor.session.widgetManager) { if (!editor.session.widgetManager) {
editor.session.widgetManager = new LineWidgets(editor.session); editor.session.widgetManager = new LineWidgets(editor.session);

View file

@ -196,8 +196,7 @@ console.log(addResult);
<p><span class="expand_arrow">&gt;</span> <a href="https://github.com/ajaxorg/ace/tree/master/lib/ace/theme" target="_blank">See all themes</a></p> <p><span class="expand_arrow">&gt;</span> <a href="https://github.com/ajaxorg/ace/tree/master/lib/ace/theme" target="_blank">See all themes</a></p>
<h2>Setting the Programming Language Mode</h2> <h2>Setting the Programming Language Mode</h2>
<p>By default, the editor supports plain text mode. All other language modes are available as separate modules, loaded on demand like this:</p> <p>By default, the editor supports plain text mode. All other language modes are available as separate modules, loaded on demand like this:</p>
<pre><code class="javascript">editor.getSession().setMode("ace/mode/javascript"); <pre><code class="javascript">editor.getSession().setMode("ace/mode/javascript");</code></pre>
</code></pre>
<!--h2>One Editor, Multiple Sessions</h2> <!--h2>One Editor, Multiple Sessions</h2>
<p>Ace keeps everything about the state of the editor (selection, scroll position, etc.) <p>Ace keeps everything about the state of the editor (selection, scroll position, etc.)
in <code class="javascript">editor.session</code>. This means you can grab the in <code class="javascript">editor.session</code>. This means you can grab the

View file

@ -40,9 +40,10 @@ var dom = require("./lib/dom");
var snippetManager = require("./snippets").snippetManager; var snippetManager = require("./snippets").snippetManager;
var Autocomplete = function() { var Autocomplete = function() {
this.autoInsert = true; this.autoInsert = false;
this.autoSelect = true; this.autoSelect = true;
this.exactMatch = false; this.exactMatch = false;
this.gatherCompletionsId = 0;
this.keyboardHandler = new HashHandler(); this.keyboardHandler = new HashHandler();
this.keyboardHandler.bindKeys(this.commands); this.keyboardHandler.bindKeys(this.commands);
@ -59,7 +60,6 @@ var Autocomplete = function() {
}; };
(function() { (function() {
this.gatherCompletionsId = 0;
this.$init = function() { this.$init = function() {
this.popup = new AcePopup(document.body || document.documentElement); this.popup = new AcePopup(document.body || document.documentElement);
@ -84,6 +84,8 @@ var Autocomplete = function() {
this.popup.setData(this.completions.filtered); this.popup.setData(this.completions.filtered);
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
var renderer = editor.renderer; var renderer = editor.renderer;
this.popup.setRow(this.autoSelect ? 0 : -1); this.popup.setRow(this.autoSelect ? 0 : -1);
if (!keepPopupPosition) { if (!keepPopupPosition) {
@ -115,10 +117,9 @@ var Autocomplete = function() {
this.changeTimer.cancel(); this.changeTimer.cancel();
this.hideDocTooltip(); this.hideDocTooltip();
if (this.popup && this.popup.isOpen) { this.gatherCompletionsId += 1;
this.gatherCompletionsId += 1; if (this.popup && this.popup.isOpen)
this.popup.hide(); this.popup.hide();
}
if (this.base) if (this.base)
this.base.detach(); this.base.detach();
@ -261,7 +262,6 @@ var Autocomplete = function() {
editor.completer = this; editor.completer = this;
} }
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
editor.on("changeSelection", this.changeListener); editor.on("changeSelection", this.changeListener);
editor.on("blur", this.blurListener); editor.on("blur", this.blurListener);
editor.on("mousedown", this.mousedownListener); editor.on("mousedown", this.mousedownListener);
@ -408,10 +408,10 @@ Autocomplete.startCommand = {
exec: function(editor) { exec: function(editor) {
if (!editor.completer) if (!editor.completer)
editor.completer = new Autocomplete(); editor.completer = new Autocomplete();
editor.completer.autoInsert = editor.completer.autoInsert = false;
editor.completer.autoSelect = true; editor.completer.autoSelect = true;
editor.completer.showPopup(editor); editor.completer.showPopup(editor);
// needed for firefox on mac // prevent ctrl-space opening context menu on firefox on mac
editor.completer.cancelContextMenu(); editor.completer.cancelContextMenu();
}, },
bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"

View file

@ -892,17 +892,17 @@ var EditSession = function(text, mode) {
config.loadModule(["mode", path], function(m) { config.loadModule(["mode", path], function(m) {
if (this.$modeId !== path) if (this.$modeId !== path)
return cb && cb(); return cb && cb();
if (this.$modes[path] && !options) if (this.$modes[path] && !options) {
return this.$onChangeMode(this.$modes[path]); this.$onChangeMode(this.$modes[path]);
if (m && m.Mode) { } else if (m && m.Mode) {
m = new m.Mode(options); m = new m.Mode(options);
if (!options) { if (!options) {
this.$modes[path] = m; this.$modes[path] = m;
m.$id = path; m.$id = path;
} }
this.$onChangeMode(m); this.$onChangeMode(m);
cb && cb();
} }
cb && cb();
}.bind(this)); }.bind(this));
// set mode to text until loading is finished // set mode to text until loading is finished

View file

@ -545,9 +545,12 @@ var Editor = function(renderer, session) {
return; return;
} }
if (token.type.indexOf("tag-open") != -1) if (token.type.indexOf("tag-open") != -1) {
token = iterator.stepForward(); token = iterator.stepForward();
if (!token)
return;
}
var tag = token.value; var tag = token.value;
var depth = 0; var depth = 0;
var prevToken = iterator.stepBackward(); var prevToken = iterator.stepBackward();
@ -1284,7 +1287,7 @@ var Editor = function(renderer, session) {
}; };
/** /**
* Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace. * Removes the current selection or one character.
* @param {String} dir The direction of the deletion to occur, either "left" or "right" * @param {String} dir The direction of the deletion to occur, either "left" or "right"
* *
**/ **/

View file

@ -140,7 +140,7 @@ var loadSnippetFile = function(id) {
function getCompletionPrefix(editor) { function getCompletionPrefix(editor) {
var pos = editor.getCursorPosition(); var pos = editor.getCursorPosition();
var line = editor.session.getLine(pos.row); var line = editor.session.getLine(pos.row);
var prefix = util.retrievePrecedingIdentifier(line, pos.column); var prefix;
// Try to find custom prefixes on the completers // Try to find custom prefixes on the completers
editor.completers.forEach(function(completer) { editor.completers.forEach(function(completer) {
if (completer.identifierRegexps) { if (completer.identifierRegexps) {
@ -150,7 +150,7 @@ function getCompletionPrefix(editor) {
}); });
} }
}); });
return prefix; return prefix || util.retrievePrecedingIdentifier(line, pos.column);
} }
var doLiveAutocomplete = function(e) { var doLiveAutocomplete = function(e) {
@ -158,8 +158,6 @@ var doLiveAutocomplete = function(e) {
var text = e.args || ""; var text = e.args || "";
var hasCompleter = editor.completer && editor.completer.activated; var hasCompleter = editor.completer && editor.completer.activated;
// We don't want to autocomplete with no prefix // We don't want to autocomplete with no prefix
if (e.command.name === "backspace") { if (e.command.name === "backspace") {
if (hasCompleter && !getCompletionPrefix(editor)) if (hasCompleter && !getCompletionPrefix(editor))
@ -174,7 +172,6 @@ var doLiveAutocomplete = function(e) {
editor.completer = new Autocomplete(); editor.completer = new Autocomplete();
} }
// Disable autoInsert // Disable autoInsert
editor.completer.autoSelect = false;
editor.completer.autoInsert = false; editor.completer.autoInsert = false;
editor.completer.showPopup(editor); editor.completer.showPopup(editor);
} }

View file

@ -43,6 +43,7 @@ Mode.prototype.supportsFile = function(filename) {
// todo firstlinematch // todo firstlinematch
var supportedModes = { var supportedModes = {
ABAP: ["abap"], ABAP: ["abap"],
ABC: ["abc"],
ActionScript:["as"], ActionScript:["as"],
ADA: ["ada|adb"], ADA: ["ada|adb"],
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],

View file

@ -102,6 +102,11 @@ var TextInput = function(parentNode, host) {
function resetSelection(isEmpty) { function resetSelection(isEmpty) {
if (inComposition) if (inComposition)
return; return;
// this prevents infinite recursion on safari 8
// see https://github.com/ajaxorg/ace/issues/2114
inComposition = true;
if (inputHandler) { if (inputHandler) {
selectionStart = 0; selectionStart = 0;
selectionEnd = isEmpty ? 0 : text.value.length - 1; selectionEnd = isEmpty ? 0 : text.value.length - 1;
@ -113,6 +118,8 @@ var TextInput = function(parentNode, host) {
try { try {
text.setSelectionRange(selectionStart, selectionEnd); text.setSelectionRange(selectionStart, selectionEnd);
} catch(e){} } catch(e){}
inComposition = false;
} }
function resetValue() { function resetValue() {

View file

@ -2110,7 +2110,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
newHead = copyCursor(origHead); newHead = copyCursor(origHead);
} }
if (vim.visualMode) { if (vim.visualMode) {
newHead = clipCursorToContent(cm, newHead, vim.visualBlock); if (!(vim.visualBlock && newHead.ch === Infinity)) {
newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
}
if (newAnchor) { if (newAnchor) {
newAnchor = clipCursorToContent(cm, newAnchor, true); newAnchor = clipCursorToContent(cm, newAnchor, true);
} }

View file

@ -1957,6 +1957,14 @@ testVim('visual_line', function(cm, vim, helpers) {
helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
eq(' 4\n 5', cm.getValue()); eq(' 4\n 5', cm.getValue());
}, { value: ' 1\n 2\n 3\n 4\n 5' }); }, { value: ' 1\n 2\n 3\n 4\n 5' });
testVim('visual_block_move_to_eol', function(cm, vim, helpers) {
// moveToEol should move all block cursors to end of line
cm.setCursor(0, 0);
helpers.doKeys('<C-v>', 'G', '$');
var selections = cm.getSelections().join();
console.log(selections);
eq("123,45,6", selections);
}, {value: '123\n45\n6'});
testVim('visual_block_different_line_lengths', function(cm, vim, helpers) { testVim('visual_block_different_line_lengths', function(cm, vim, helpers) {
// test the block selection with lines of different length // test the block selection with lines of different length
// i.e. extending the selection // i.e. extending the selection

View file

@ -253,20 +253,6 @@ function normalizeCommandKeys(callback, e, keyCode) {
} }
if (keyCode in keys.MODIFIER_KEYS) { if (keyCode in keys.MODIFIER_KEYS) {
switch (keys.MODIFIER_KEYS[keyCode]) {
case "Alt":
hashId = 2;
break;
case "Shift":
hashId = 4;
break;
case "Ctrl":
hashId = 1;
break;
default:
hashId = 8;
break;
}
keyCode = -1; keyCode = -1;
} }

View file

@ -146,7 +146,7 @@ var Keys = (function() {
})(); })();
ret.KEY_MODS[0] = ""; ret.KEY_MODS[0] = "";
ret.KEY_MODS[-1] = "input"; ret.KEY_MODS[-1] = "input-";
return ret; return ret;
})(); })();

View file

@ -13,7 +13,7 @@
[1, +1, -1, 12_345, 0.000_1, [1, +1, -1, 12_345, 0.000_1,
_, 3_1, 1_2, 1_.0, 0._1]; _, 3_1, 1_2, 1_.0, 0._1];
{:id => 34, :key => "value"} {:id => ?", :key => "value", anotherKey: [x, y?]}
=begin =begin
=end =end

File diff suppressed because it is too large Load diff

View file

@ -137,7 +137,12 @@
"start", "start",
["text"," "], ["text"," "],
["keyword","#if"], ["keyword","#if"],
["constant.other"," VERBOSE >= 2"] ["text"," "],
["identifier","VERBOSE"],
["text"," "],
["keyword.operator",">="],
["text"," "],
["constant.numeric","2"]
],[ ],[
"start", "start",
["text"," "], ["text"," "],

View file

@ -727,7 +727,8 @@
],[ ],[
"start", "start",
["keyword","#ifndef"], ["keyword","#ifndef"],
["constant.other"," Nil"] ["text"," "],
["constant.language.objc","Nil"]
],[ ],[
"start", "start",
["keyword","#define"], ["keyword","#define"],

View file

@ -139,7 +139,7 @@
["text"," "], ["text"," "],
["punctuation.separator.key-value","=>"], ["punctuation.separator.key-value","=>"],
["text"," "], ["text"," "],
["constant.numeric","34"], ["string.character","?\""],
["text",", "], ["text",", "],
["constant.other.symbol.ruby",":key"], ["constant.other.symbol.ruby",":key"],
["text"," "], ["text"," "],
@ -148,7 +148,15 @@
["string.start","\""], ["string.start","\""],
["string","value"], ["string","value"],
["string.end","\""], ["string.end","\""],
["paren.rparen","}"] ["text",", "],
["identifier","anotherKey"],
["text",": "],
["paren.lparen","["],
["identifier","x"],
["text",", "],
["identifier","y"],
["text","?"],
["paren.rparen","]}"]
],[ ],[
"start" "start"
],[ ],[

View file

@ -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);

58
lib/ace/mode/abc.js Normal file
View file

@ -0,0 +1,58 @@
/* ***** 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.
*
* ***** END LICENSE BLOCK ***** */
/*
THIS FILE WAS AUTOGENERATED BY mode.tmpl.js
*/
define(function (require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var ABCHighlightRules = require("./abc_highlight_rules").ABCHighlightRules;
// TODO: pick appropriate fold mode
var FoldMode = require("./folding/cstyle").FoldMode;
var Mode = function () {
this.HighlightRules = ABCHighlightRules;
this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);
(function () {
// this.lineCommentStart = ""%.*"";
// this.blockComment = {start: ""/*"", end: ""*/""};
// Extra logic goes here.
this.$id = "ace/mode/abc"
}).call(Mode.prototype);
exports.Mode = Mode;
});

View file

@ -0,0 +1,114 @@
/* This file was partially autogenerated from https://github.com/jimhawkridge/SublimeABC
Modifications
- more classes to express the abc semantic
- added syntax highlighting for Zupfnoter conventions (https://github.com/bwl21/zupfnoter)
- separate note pitch and note duration - even if it looks the same
***********************************************************************************************/
define(function (require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var ABCHighlightRules = function () {
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules = {
start: [
{
token: ['zupfnoter.information.comment.line.percentage', 'information.keyword', 'in formation.keyword.embedded'],
regex: '(%%%%)(hn\\.[a-z]*)(.*)',
comment: 'Instruction Comment'
},
{
token: ['information.comment.line.percentage', 'information.keyword.embedded'],
regex: '(%%)(.*)',
comment: 'Instruction Comment'
},
{
token: 'comment.line.percentage',
regex: '%.*',
comment: 'Comments'
},
{
token: 'barline.keyword.operator',
regex: '[\\[:]*[|:][|\\]:]*(?:\\[?[0-9]+)?|\\[[0-9]+',
comment: 'Bar lines'
},
{
token: ['information.keyword.embedded', 'information.argument.string.unquoted'],
regex: '(\\[[A-Za-z]:)([^\\]]*\\])',
comment: 'embedded Header lines'
},
{
token: ['information.keyword', 'information.argument.string.unquoted'],
regex: '^([A-Za-z]:)([^%\\\\]*)',
comment: 'Header lines'
},
{
token: ['text', 'entity.name.function', 'string.unquoted', 'text'],
regex: '(\\[)([A-Z]:)(.*?)(\\])',
comment: 'Inline fields'
},
{
token: ['accent.constant.language', 'pitch.constant.numeric', 'duration.constant.numeric'],
regex: '([\\^=_]*)([A-Ga-gz][,\']*)([0-9]*/*[><0-9]*)',
comment: 'Notes'
},
{
token: 'zupfnoter.jumptarget.string.quoted',
regex: '[\\"!]\\^\\:.*?[\\"!]',
comment: 'Zupfnoter jumptarget'
}, {
token: 'zupfnoter.goto.string.quoted',
regex: '[\\"!]\\^\\@.*?[\\"!]',
comment: 'Zupfnoter goto'
},
{
token: 'zupfnoter.annotation.string.quoted',
regex: '[\\"!]\\^\\!.*?[\\"!]',
comment: 'Zupfnoter annoation'
},
{
token: 'zupfnoter.annotationref.string.quoted',
regex: '[\\"!]\\^\\#.*?[\\"!]',
comment: 'Zupfnoter annotation reference'
},
{
token: 'chordname.string.quoted',
regex: '[\\"!]\\^.*?[\\"!]',
comment: 'abc chord'
},
{
token: 'string.quoted',
regex: '[\\"!].*?[\\"!]',
comment: 'abc annotation'
}
]
};
// this.embedRules(JsonHighlightRules, "json-")
this.normalizeRules();
};
ABCHighlightRules.metaData = {
fileTypes: ['abc'],
name: 'ABC',
scopeName: 'text.abcnotation'
};
oop.inherits(ABCHighlightRules, TextHighlightRules);
exports.ABCHighlightRules = ABCHighlightRules;
});

View file

@ -84,11 +84,11 @@ var c_cppHighlightRules = function() {
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
}, { }, {
token : "keyword", // pre-compiler directives token : "keyword", // pre-compiler directives
regex : "#\\s*(?:include|import|pragma|line|define|undef|if|ifdef|else|elif|ifndef)\\b", regex : "#\\s*(?:include|import|pragma|line|define|undef)\\b",
next : "directive" next : "directive"
}, { }, {
token : "keyword", // special case pre-compiler directive token : "keyword", // special case pre-compiler directive
regex : "(?:#\\s*endif)\\b" regex : "#\\s*(?:endif|if|ifdef|else|elif|ifndef)\\b"
}, { }, {
token : "support.function.C99.c", token : "support.function.C99.c",
regex : cFunctions regex : cFunctions

View file

@ -116,11 +116,11 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker"); var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations([e.data]); session.setAnnotations(e.data);
}); });
worker.on("ok", function(e) { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -49,13 +49,13 @@ oop.inherits(Worker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
var errors = [];
try { try {
coffee.parse(value).compile(); coffee.parse(value).compile();
} catch(e) { } catch(e) {
var loc = e.location; var loc = e.location;
if (loc) { if (loc) {
this.sender.emit("error", { errors.push({
row: loc.first_line, row: loc.first_line,
column: loc.first_column, column: loc.first_column,
endRow: loc.last_line, endRow: loc.last_line,
@ -64,9 +64,8 @@ oop.inherits(Worker, Mirror);
type: "error" type: "error"
}); });
} }
return;
} }
this.sender.emit("ok"); this.sender.emit("annotate", errors);
}; };
}).call(Worker.prototype); }).call(Worker.prototype);

View file

@ -81,7 +81,7 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker"); var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("csslint", function(e) { worker.on("annotate", function(e) {
session.setAnnotations(e.data); session.setAnnotations(e.data);
}); });

View file

@ -80,11 +80,11 @@ oop.inherits(Worker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
if (!value) if (!value)
return this.sender.emit("csslint", []); return this.sender.emit("annotate", []);
var infoRules = this.infoRules; var infoRules = this.infoRules;
var result = CSSLint.verify(value, this.ruleset); var result = CSSLint.verify(value, this.ruleset);
this.sender.emit("csslint", result.messages.map(function(msg) { this.sender.emit("annotate", result.messages.map(function(msg) {
return { return {
row: msg.line - 1, row: msg.line - 1,
column: msg.col - 1, column: msg.col - 1,

View file

@ -59,8 +59,8 @@ module.exports = {
assert.equal(session.getFoldWidget(3), "end"); assert.equal(session.getFoldWidget(3), "end");
assert.equal(session.getFoldWidget(4), "end"); assert.equal(session.getFoldWidget(4), "end");
assert.range(session.getFoldWidgetRange(0), 0, 8, 4, 0); assert.range(session.getFoldWidgetRange(0), 0, 31, 4, 0);
assert.range(session.getFoldWidgetRange(4), 0, 8, 4, 0); assert.range(session.getFoldWidgetRange(4), 0, 31, 4, 0);
assert.range(session.getFoldWidgetRange(1), 1, 16, 3, 0); assert.range(session.getFoldWidgetRange(1), 1, 16, 3, 0);
assert.range(session.getFoldWidgetRange(3), 1, 16, 3, 0); assert.range(session.getFoldWidgetRange(3), 1, 16, 3, 0);
@ -85,8 +85,8 @@ module.exports = {
assert.equal(session.getFoldWidget(3), "end"); assert.equal(session.getFoldWidget(3), "end");
assert.equal(session.getFoldWidget(4), "end"); assert.equal(session.getFoldWidget(4), "end");
assert.range(session.getFoldWidgetRange(0), 0, 7, 4, 0); assert.range(session.getFoldWidgetRange(0), 0, 23, 4, 0);
assert.range(session.getFoldWidgetRange(4), 0, 7, 4, 0); assert.range(session.getFoldWidgetRange(4), 0, 23, 4, 0);
assert.range(session.getFoldWidgetRange(1), 1, 17, 3, 4); assert.range(session.getFoldWidgetRange(1), 1, 17, 3, 4);
assert.range(session.getFoldWidgetRange(3), 1, 17, 3, 4); assert.range(session.getFoldWidgetRange(3), 1, 17, 3, 4);

View file

@ -217,6 +217,8 @@ function is(token, type) {
row: row, row: row,
column: firstTag.start.column + firstTag.tagName.length + 2 column: firstTag.start.column + firstTag.tagName.length + 2
}; };
if (firstTag.start.row == firstTag.end.row)
start.column = firstTag.end.column;
while (tag = this._readTagForward(iterator)) { while (tag = this._readTagForward(iterator)) {
if (tag.selfClosing) { if (tag.selfClosing) {
if (!stack.length) { if (!stack.length) {
@ -258,6 +260,8 @@ function is(token, type) {
this._pop(stack, tag); this._pop(stack, tag);
if (stack.length == 0) { if (stack.length == 0) {
tag.start.column += tag.tagName.length + 2; tag.start.column += tag.tagName.length + 2;
if (tag.start.row == tag.end.row && tag.start.column < tag.end.column)
tag.start.column = tag.end.column;
return Range.fromPoints(tag.start, end); return Range.fromPoints(tag.start, end);
} }
} }

View file

@ -55,9 +55,9 @@ var HaskellHighlightRules = function() {
{ token: 'constant.language.empty-list.haskell', { token: 'constant.language.empty-list.haskell',
regex: '\\[\\]' }, regex: '\\[\\]' },
{ token: 'keyword.other.haskell', { token: 'keyword.other.haskell',
regex: 'module', regex: '\\bmodule\\b',
push: push:
[ { token: 'keyword.other.haskell', regex: 'where', next: 'pop' }, [ { token: 'keyword.other.haskell', regex: '\\bwhere\\b', next: 'pop' },
{ include: '#module_name' }, { include: '#module_name' },
{ include: '#module_exports' }, { include: '#module_exports' },
{ token: 'invalid', regex: '[a-z]+' }, { token: 'invalid', regex: '[a-z]+' },

View file

@ -98,7 +98,7 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("jslint", function(results) { worker.on("annotate", function(results) {
session.setAnnotations(results.data); session.setAnnotations(results.data);
}); });

File diff suppressed because it is too large Load diff

View file

@ -116,12 +116,10 @@ oop.inherits(JavaScriptWorker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
value = value.replace(/^#!.*\n/, "\n"); value = value.replace(/^#!.*\n/, "\n");
if (!value) { if (!value)
this.sender.emit("jslint", []); return this.sender.emit("annotate", []);
return;
}
var errors = [];
var errors = [];
// jshint reports many false errors // jshint reports many false errors
// report them as error only if code is actually invalid // report them as error only if code is actually invalid
var maxErrorLevel = this.isValidJS(value) ? "warning" : "error"; var maxErrorLevel = this.isValidJS(value) ? "warning" : "error";
@ -179,7 +177,7 @@ oop.inherits(JavaScriptWorker, Mirror);
} }
// console.log("lint time: " + (new Date() - start)); // console.log("lint time: " + (new Date() - start));
this.sender.emit("jslint", errors); this.sender.emit("annotate", errors);
}; };
}).call(JavaScriptWorker.prototype); }).call(JavaScriptWorker.prototype);

View file

@ -74,11 +74,11 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker"); var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations([e.data]); session.setAnnotations(e.data);
}); });
worker.on("ok", function() { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -46,21 +46,20 @@ oop.inherits(JsonWorker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
var errors = [];
try { try {
if (value) if (value)
parse(value); parse(value);
} catch (e) { } catch (e) {
var pos = this.doc.indexToPosition(e.at-1); var pos = this.doc.indexToPosition(e.at-1);
this.sender.emit("error", { errors.push({
row: pos.row, row: pos.row,
column: pos.column, column: pos.column,
text: e.message, text: e.message,
type: "error" type: "error"
}); });
return;
} }
this.sender.emit("ok"); this.sender.emit("annotate", errors);
}; };
}).call(JsonWorker.prototype); }).call(JsonWorker.prototype);

View file

@ -58,7 +58,7 @@ module.exports = {
worker.setValue("{}"); worker.setValue("{}");
worker.deferredUpdate.call(); worker.deferredUpdate.call();
assert.equal(this.sender.events[0][0], "ok"); assert.equal(this.sender.events[0][1].length, 0);
}, },
"test check for syntax error": function() { "test check for syntax error": function() {
@ -71,11 +71,12 @@ module.exports = {
worker.deferredUpdate.call(); worker.deferredUpdate.call();
var event = this.sender.events[0]; var event = this.sender.events[0];
assert.equal(event[0], "error"); assert.equal(event[0], "annotate");
assert.equal(event[1].type, "error"); assert.equal(event[1].length, 1);
assert.equal(event[1].text, "Bad string"); assert.equal(event[1][0].type, "error");
assert.equal(event[1].row, 1); assert.equal(event[1][0].text, "Bad string");
assert.equal(event[1].column, 0); assert.equal(event[1][0].row, 1);
assert.equal(event[1][0].column, 0);
}, },
@ -85,11 +86,11 @@ module.exports = {
worker.deferredUpdate.call(); worker.deferredUpdate.call();
var event = this.sender.events[0]; var event = this.sender.events[0];
assert.equal(event[0], "error"); assert.equal(event[0], "annotate");
assert.equal(event[1].type, "error"); assert.equal(event[1][0].type, "error");
assert.equal(event[1].text, "Unexpected 'x'"); assert.equal(event[1][0].text, "Unexpected 'x'");
assert.equal(event[1].row, 0); assert.equal(event[1][0].row, 0);
assert.equal(event[1].column, 0); assert.equal(event[1][0].column, 0);
} }
}; };

View file

@ -52,8 +52,7 @@ define(function(require, exports, module){
}(require('../mode/text').Mode)); }(require('../mode/text').Mode));
keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))'; keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))';
stringfill = { stringfill = {
token: 'string', defaultToken: 'string'
regex: '.+'
}; };
LiveScriptMode.Rules = { LiveScriptMode.Rules = {
start: [ start: [
@ -146,7 +145,7 @@ define(function(require, exports, module){
next: 'key' next: 'key'
}, { }, {
token: 'keyword.operator', token: 'keyword.operator',
regex: '\\S+' regex: '[\\^!|&%+\\-]+'
}, { }, {
token: 'text', token: 'text',
regex: '\\s+' regex: '\\s+'
@ -164,8 +163,7 @@ define(function(require, exports, module){
token: 'comment.regex', token: 'comment.regex',
regex: '\\s+(?:#.*)?' regex: '\\s+(?:#.*)?'
}, { }, {
token: 'string.regex', defaultToken: 'string.regex'
regex: '\\S+'
} }
], ],
key: [ key: [
@ -178,7 +176,7 @@ define(function(require, exports, module){
next: 'start' next: 'start'
}, { }, {
token: 'text', token: 'text',
regex: '.', regex: '',
next: 'start' next: 'start'
} }
], ],
@ -188,8 +186,7 @@ define(function(require, exports, module){
regex: '.*?\\*/', regex: '.*?\\*/',
next: 'start' next: 'start'
}, { }, {
token: 'comment.doc', defaultToken: 'comment.doc'
regex: '.+'
} }
], ],
qdoc: [ qdoc: [

View file

@ -148,11 +148,11 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/lua_worker", "Worker"); var worker = new WorkerClient(["ace"], "ace/mode/lua_worker", "Worker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations([e.data]); session.setAnnotations(e.data);
}); });
worker.on("ok", function(e) { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -46,24 +46,23 @@ oop.inherits(Worker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
var errors = [];
// var t=Date.now()
// var t=Date.now()
try { try {
luaparse.parse(value); luaparse.parse(value);
} catch(e) { } catch(e) {
if (e instanceof SyntaxError) { if (e instanceof SyntaxError) {
this.sender.emit("error", { errors.push({
row: e.line - 1, row: e.line - 1,
column: e.column, column: e.column,
text: e.message, text: e.message,
type: "error" type: "error"
}); });
} }
// console.log( t-Date.now())
return;
} }
// console.log( t-Date.now()) // console.log( t-Date.now())
this.sender.emit("ok"); this.sender.emit("annotate", errors);
}; };
}).call(Worker.prototype); }).call(Worker.prototype);

View file

@ -143,11 +143,11 @@ oop.inherits(Mode, HtmlMode);
if (this.inlinePhp) if (this.inlinePhp)
worker.call("setOptions", [{inline: true}]); worker.call("setOptions", [{inline: true}]);
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations(e.data); session.setAnnotations(e.data);
}); });
worker.on("ok", function() { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -69,11 +69,7 @@ oop.inherits(PhpWorker, Mirror);
// console.log("lint time: " + (new Date() - start)); // console.log("lint time: " + (new Date() - start));
if (errors.length) { this.sender.emit("annotate", errors);
this.sender.emit("error", errors);
} else {
this.sender.emit("ok");
}
}; };
}).call(PhpWorker.prototype); }).call(PhpWorker.prototype);

View file

@ -288,6 +288,9 @@ var RubyHighlightRules = function() {
return stack[0]; return stack[0];
return currentState; return currentState;
} }
}, {
token : "string.character",
regex : "\\B\\?."
}, { }, {
token : "keyword.operator", token : "keyword.operator",
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"

View file

@ -37,11 +37,12 @@ var TextMode = require("./text").Mode;
var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
var XmlBehaviour = require("./behaviour/xml").XmlBehaviour; var XmlBehaviour = require("./behaviour/xml").XmlBehaviour;
var XmlFoldMode = require("./folding/xml").FoldMode; var XmlFoldMode = require("./folding/xml").FoldMode;
var WorkerClient = require("../worker/worker_client").WorkerClient;
var Mode = function() { var Mode = function() {
this.HighlightRules = XmlHighlightRules; this.HighlightRules = XmlHighlightRules;
this.$behaviour = new XmlBehaviour(); this.$behaviour = new XmlBehaviour();
this.foldingRules = new XmlFoldMode(); this.foldingRules = new XmlFoldMode();
}; };
oop.inherits(Mode, TextMode); oop.inherits(Mode, TextMode);
@ -52,6 +53,21 @@ oop.inherits(Mode, TextMode);
this.blockComment = {start: "<!--", end: "-->"}; this.blockComment = {start: "<!--", end: "-->"};
this.createWorker = function(session) {
var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
worker.attachToDocument(session.getDocument());
worker.on("error", function(e) {
session.setAnnotations(e.data);
});
worker.on("terminate", function() {
session.clearAnnotations();
});
return worker;
};
this.$id = "ace/mode/xml"; this.$id = "ace/mode/xml";
}).call(Mode.prototype); }).call(Mode.prototype);

View file

@ -0,0 +1,260 @@
define(function(require, exports, module) {
'use strict';
var XMLReader = require('./sax'),
DOMImplementation = require('./dom');
function DOMParser(options){
this.options = options ||{locator:{}};
}
DOMParser.prototype.parseFromString = function(source,mimeType){
var options = this.options;
var sax = new XMLReader();
var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
var errorHandler = options.errorHandler;
var locator = options.locator;
var defaultNSMap = options.xmlns||{};
var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"}
if(locator){
domBuilder.setDocumentLocator(locator)
}
sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
sax.domBuilder = options.domBuilder || domBuilder;
if(/\/x?html?$/.test(mimeType)){
entityMap.nbsp = '\xa0';
entityMap.copy = '\xa9';
defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
}
if(source){
sax.parse(source,defaultNSMap,entityMap);
}else{
sax.errorHandler.error("invalid document source");
}
return domBuilder.document;
}
function buildErrorHandler(errorImpl,domBuilder,locator){
if(!errorImpl){
if(domBuilder instanceof DOMHandler){
return domBuilder;
}
errorImpl = domBuilder ;
}
var errorHandler = {}
var isCallback = errorImpl instanceof Function;
locator = locator||{}
function build(key){
var fn = errorImpl[key];
if(!fn){
if(isCallback){
fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;
}else{
var i=arguments.length;
while(--i){
if(fn = errorImpl[arguments[i]]){
break;
}
}
}
}
errorHandler[key] = fn && function(msg){
fn(msg+_locator(locator), msg, locator);
}||function(){};
}
build('warning','warn');
build('error','warn','warning');
build('fatalError','warn','warning','error');
return errorHandler;
}
/**
* +ContentHandler+ErrorHandler
* +LexicalHandler+EntityResolver2
* -DeclHandler-DTDHandler
*
* DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
* DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
* @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
*/
function DOMHandler() {
this.cdata = false;
}
function position(locator,node){
node.lineNumber = locator.lineNumber;
node.columnNumber = locator.columnNumber;
}
/**
* @see org.xml.sax.ContentHandler#startDocument
* @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
*/
DOMHandler.prototype = {
startDocument : function() {
this.document = new DOMImplementation().createDocument(null, null, null);
if (this.locator) {
this.document.documentURI = this.locator.systemId;
}
},
startElement:function(namespaceURI, localName, qName, attrs) {
var doc = this.document;
var el = doc.createElementNS(namespaceURI, qName||localName);
var len = attrs.length;
appendElement(this, el);
this.currentElement = el;
this.locator && position(this.locator,el)
for (var i = 0 ; i < len; i++) {
var namespaceURI = attrs.getURI(i);
var value = attrs.getValue(i);
var qName = attrs.getQName(i);
var attr = doc.createAttributeNS(namespaceURI, qName);
if( attr.getOffset){
position(attr.getOffset(1),attr)
}
attr.value = attr.nodeValue = value;
el.setAttributeNode(attr)
}
},
endElement:function(namespaceURI, localName, qName) {
var current = this.currentElement
var tagName = current.tagName;
this.currentElement = current.parentNode;
},
startPrefixMapping:function(prefix, uri) {
},
endPrefixMapping:function(prefix) {
},
processingInstruction:function(target, data) {
var ins = this.document.createProcessingInstruction(target, data);
this.locator && position(this.locator,ins)
appendElement(this, ins);
},
ignorableWhitespace:function(ch, start, length) {
},
characters:function(chars, start, length) {
chars = _toString.apply(this,arguments)
//console.log(chars)
if(this.currentElement && chars){
if (this.cdata) {
var charNode = this.document.createCDATASection(chars);
this.currentElement.appendChild(charNode);
} else {
var charNode = this.document.createTextNode(chars);
this.currentElement.appendChild(charNode);
}
this.locator && position(this.locator,charNode)
}
},
skippedEntity:function(name) {
},
endDocument:function() {
this.document.normalize();
},
setDocumentLocator:function (locator) {
if(this.locator = locator){// && !('lineNumber' in locator)){
locator.lineNumber = 0;
}
},
//LexicalHandler
comment:function(chars, start, length) {
chars = _toString.apply(this,arguments)
var comm = this.document.createComment(chars);
this.locator && position(this.locator,comm)
appendElement(this, comm);
},
startCDATA:function() {
//used in characters() methods
this.cdata = true;
},
endCDATA:function() {
this.cdata = false;
},
startDTD:function(name, publicId, systemId) {
var impl = this.document.implementation;
if (impl && impl.createDocumentType) {
var dt = impl.createDocumentType(name, publicId, systemId);
this.locator && position(this.locator,dt)
appendElement(this, dt);
}
},
/**
* @see org.xml.sax.ErrorHandler
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
*/
warning:function(error) {
console.warn(error,_locator(this.locator));
},
error:function(error) {
console.error(error,_locator(this.locator));
},
fatalError:function(error) {
console.error(error,_locator(this.locator));
throw error;
}
}
function _locator(l){
if(l){
return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
}
}
function _toString(chars,start,length){
if(typeof chars == 'string'){
return chars.substr(start,length)
}else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
if(chars.length >= start+length || start){
return new java.lang.String(chars,start,length)+'';
}
return chars;
}
}
/*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
* used method of org.xml.sax.ext.LexicalHandler:
* #comment(chars, start, length)
* #startCDATA()
* #endCDATA()
* #startDTD(name, publicId, systemId)
*
*
* IGNORED method of org.xml.sax.ext.LexicalHandler:
* #endDTD()
* #startEntity(name)
* #endEntity(name)
*
*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
* IGNORED method of org.xml.sax.ext.DeclHandler
* #attributeDecl(eName, aName, type, mode, value)
* #elementDecl(name, model)
* #externalEntityDecl(name, publicId, systemId)
* #internalEntityDecl(name, value)
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
* IGNORED method of org.xml.sax.EntityResolver2
* #resolveEntity(String name,String publicId,String baseURI,String systemId)
* #resolveEntity(publicId, systemId)
* #getExternalSubset(name, baseURI)
* @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
* IGNORED method of org.xml.sax.DTDHandler
* #notationDecl(name, publicId, systemId) {};
* #unparsedEntityDecl(name, publicId, systemId, notationName) {};
*/
"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
DOMHandler.prototype[key] = function(){return null}
})
/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
function appendElement (hander,node) {
if (!hander.currentElement) {
hander.document.appendChild(node);
} else {
hander.currentElement.appendChild(node);
}
}//appendChild and setAttributeNS are preformance key
return {
DOMParser: DOMParser
};
});

1138
lib/ace/mode/xml/dom.js Normal file

File diff suppressed because it is too large Load diff

592
lib/ace/mode/xml/sax.js Normal file
View file

@ -0,0 +1,592 @@
define(function(require, exports, module) {
//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//[5] Name ::= NameStartChar (NameChar)*
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\ux203F-\u2040]");
var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
//S_TAG, S_ATTR, S_EQ, S_V
//S_ATTR_S, S_E, S_S, S_C
var S_TAG = 0;//tag name offerring
var S_ATTR = 1;//attr name offerring
var S_ATTR_S=2;//attr name end and space offer
var S_EQ = 3;//=space?
var S_V = 4;//attr value(no quot value only)
var S_E = 5;//attr value end and no space(quot end)
var S_S = 6;//(attr value end || tag end ) && (space offer)
var S_C = 7;//closed el<el />
function XMLReader(){
}
XMLReader.prototype = {
parse:function(source,defaultNSMap,entityMap){
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap ,defaultNSMap = {})
parse(source,defaultNSMap,entityMap,
domBuilder,this.errorHandler);
domBuilder.endDocument();
}
}
function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
function fixedFromCharCode(code) {
// String.prototype.fromCharCode does not supports
// > 2 bytes unicode chars directly
if (code > 0xffff) {
code -= 0x10000;
var surrogate1 = 0xd800 + (code >> 10)
, surrogate2 = 0xdc00 + (code & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a){
var k = a.slice(1,-1);
if(k in entityMap){
return entityMap[k];
}else if(k.charAt(0) === '#'){
return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
}else{
errorHandler.error('entity not found:'+a);
return a;
}
}
function appendText(end){//has some bugs
var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
locator&&position(start);
domBuilder.characters(xt,0,end-start);
start = end
}
function position(start,m){
while(start>=endPos && (m = linePattern.exec(source))){
startPos = m.index;
endPos = startPos + m[0].length;
locator.lineNumber++;
//console.log('line++:',locator,startPos,endPos)
}
locator.columnNumber = start-startPos+1;
}
var startPos = 0;
var endPos = 0;
var linePattern = /.+(?:\r\n?|\n)|.*$/g
var locator = domBuilder.locator;
var parseStack = [{currentNSMap:defaultNSMapCopy}]
var closeMap = {};
var start = 0;
while(true){
var i = source.indexOf('<',start);
if(i<0){
if(!source.substr(start).match(/^\s*$/)){
var doc = domBuilder.document;
var text = doc.createTextNode(source.substr(start));
doc.appendChild(text);
domBuilder.currentElement = text;
}
return;
}
if(i>start){
appendText(i);
}
switch(source.charAt(i+1)){
case '/':
var end = source.indexOf('>',i+3);
var tagName = source.substring(i+2,end);
var config;
if (parseStack.length > 1) {
config = parseStack.pop();
} else {
errorHandler.fatalError("end tag name not found for: "+tagName);
break;
}
var localNSMap = config.localNSMap;
if(config.tagName != tagName){
errorHandler.fatalError("end tag name: " + tagName + " does not match the current start tagName: "+config.tagName );
}
domBuilder.endElement(config.uri,config.localName,tagName);
if(localNSMap){
for(var prefix in localNSMap){
domBuilder.endPrefixMapping(prefix) ;
}
}
end++;
break;
// end elment
case '?':// <?...?>
locator&&position(i);
end = parseInstruction(source,i,domBuilder);
break;
case '!':// <!doctype,<![CDATA,<!--
locator&&position(i);
end = parseDCC(source,i,domBuilder,errorHandler);
break;
default:
try{
locator&&position(i);
var el = new ElementAttributes();
//elStartEnd
var end = parseElementStartPart(source,i,el,entityReplacer,errorHandler);
var len = el.length;
//position fixed
if(len && locator){
var backup = copyLocator(locator,{});
for(var i = 0;i<len;i++){
var a = el[i];
position(a.offset);
a.offset = copyLocator(locator,{});
}
copyLocator(backup,locator);
}
if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
el.closed = true;
if(!entityMap.nbsp){
errorHandler.warning('unclosed xml attribute');
}
}
appendElement(el,domBuilder,parseStack);
if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
}else{
end++;
}
}catch(e){
errorHandler.error('element parse error: '+e);
end = -1;
}
}
if(end<0){
//TODO: 这里有可能sax回退,有位置错误风险
appendText(i+1);
}else{
start = end;
}
}
}
function copyLocator(f,t){
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
/**
* @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
var attrName;
var value;
var p = ++start;
var s = S_TAG;//status
while(true){
var c = source.charAt(p);
switch(c){
case '=':
if(s === S_ATTR){//attrName
attrName = source.slice(start,p);
s = S_EQ;
}else if(s === S_ATTR_S){
s = S_EQ;
}else{
//fatalError: equal must after attrName or space after attrName
throw new Error('attribute equal must after attrName');
}
break;
case '\'':
case '"':
if(s === S_EQ){//equal
start = p+1;
p = source.indexOf(c,start)
if(p>0){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
el.add(attrName,value,start-1);
s = S_E;
}else{
//fatalError: no end quot match
throw new Error('attribute value no end \''+c+'\' match');
}
}else if(s == S_V){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
//console.log(attrName,value,start,p)
el.add(attrName,value,start);
//console.dir(el)
errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
start = p+1;
s = S_E
}else{
//fatalError: no equal before
throw new Error('attribute value must after "="');
}
break;
case '/':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_E:
case S_S:
case S_C:
s = S_C;
el.closed = true;
case S_V:
case S_ATTR:
case S_ATTR_S:
break;
//case S_EQ:
default:
throw new Error("attribute invalid close char('/')")
}
break;
case ''://end document
//throw new Error('unexpected end of input')
errorHandler.error('unexpected end of input');
case '>':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_E:
case S_S:
case S_C:
break;//normal
case S_V://Compatible state
case S_ATTR:
value = source.slice(start,p);
if(value.slice(-1) === '/'){
el.closed = true;
value = value.slice(0,-1)
}
case S_ATTR_S:
if(s === S_ATTR_S){
value = attrName;
}
if(s == S_V){
errorHandler.warning('attribute "'+value+'" missed quot(")!!');
el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start)
}else{
errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
el.add(value,value,start)
}
break;
case S_EQ:
throw new Error('attribute value missed!!');
}
// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
return p;
/*xml space '\x20' | #x9 | #xD | #xA; */
case '\u0080':
c = ' ';
default:
if(c<= ' '){//space
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));//tagName
s = S_S;
break;
case S_ATTR:
attrName = source.slice(start,p)
s = S_ATTR_S;
break;
case S_V:
var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
errorHandler.warning('attribute "'+value+'" missed quot(")!!');
el.add(attrName,value,start)
case S_E:
s = S_S;
break;
//case S_S:
//case S_EQ:
//case S_ATTR_S:
// void();break;
//case S_C:
//ignore warning
}
}else{//not space
//S_TAG, S_ATTR, S_EQ, S_V
//S_ATTR_S, S_E, S_S, S_C
switch(s){
//case S_TAG:void();break;
//case S_ATTR:void();break;
//case S_V:void();break;
case S_ATTR_S:
errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!')
el.add(attrName,attrName,start);
start = p;
s = S_ATTR;
break;
case S_E:
errorHandler.warning('attribute space is required"'+attrName+'"!!')
case S_S:
s = S_ATTR;
start = p;
break;
case S_EQ:
s = S_V;
start = p;
break;
case S_C:
throw new Error("elements closed character '/' and '>' must be connected to");
}
}
}
p++;
}
}
/**
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function appendElement(el,domBuilder,parseStack){
var tagName = el.tagName;
var localNSMap = null;
var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
var i = el.length;
while(i--){
var a = el[i];
var qName = a.qName;
var value = a.value;
var nsp = qName.indexOf(':');
if(nsp>0){
var prefix = a.prefix = qName.slice(0,nsp);
var localName = qName.slice(nsp+1);
var nsPrefix = prefix === 'xmlns' && localName
}else{
localName = qName;
prefix = null
nsPrefix = qName === 'xmlns' && ''
}
//can not set prefix,because prefix !== ''
a.localName = localName ;
//prefix == null for no ns prefix attribute
if(nsPrefix !== false){//hack!!
if(localNSMap == null){
localNSMap = {}
//console.log(currentNSMap,0)
_copy(currentNSMap,currentNSMap={})
//console.log(currentNSMap,1)
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = 'http://www.w3.org/2000/xmlns/'
domBuilder.startPrefixMapping(nsPrefix, value)
}
}
var i = el.length;
while(i--){
a = el[i];
var prefix = a.prefix;
if(prefix){//no prefix attribute has no namespace
if(prefix === 'xml'){
a.uri = 'http://www.w3.org/XML/1998/namespace';
}if(prefix !== 'xmlns'){
a.uri = currentNSMap[prefix]
//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
}
}
}
var nsp = tagName.indexOf(':');
if(nsp>0){
prefix = el.prefix = tagName.slice(0,nsp);
localName = el.localName = tagName.slice(nsp+1);
}else{
prefix = null;//important!!
localName = el.localName = tagName;
}
//no prefix element has default namespace
var ns = el.uri = currentNSMap[prefix || ''];
domBuilder.startElement(ns,localName,tagName,el);
//endPrefixMapping and startPrefixMapping have not any help for dom builder
//localNSMap = null
if(el.closed){
domBuilder.endElement(ns,localName,tagName);
if(localNSMap){
for(prefix in localNSMap){
domBuilder.endPrefixMapping(prefix)
}
}
}else{
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap;
parseStack.push(el);
}
}
function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
if(/^(?:script|textarea)$/i.test(tagName)){
var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
var text = source.substring(elStartEnd+1,elEndStart);
if(/[&<]/.test(text)){
if(/^script$/i.test(tagName)){
//if(!/\]\]>/.test(text)){
//lexHandler.startCDATA();
domBuilder.characters(text,0,text.length);
//lexHandler.endCDATA();
return elEndStart;
//}
}//}else{//text area
text = text.replace(/&#?\w+;/g,entityReplacer);
domBuilder.characters(text,0,text.length);
return elEndStart;
//}
}
}
return elStartEnd+1;
}
function fixSelfClosed(source,elStartEnd,tagName,closeMap){
//if(tagName in closeMap){
var pos = closeMap[tagName];
if(pos == null){
//console.log(tagName)
pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>')
}
return pos<elStartEnd;
//}
}
function _copy(source,target){
for(var n in source){target[n] = source[n]}
}
function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
var next= source.charAt(start+2)
switch(next){
case '-':
if(source.charAt(start + 3) === '-'){
var end = source.indexOf('-->',start+4);
//append comment source.substring(4,end)//<!--
if(end>start){
domBuilder.comment(source,start+4,end-start-4);
return end+3;
}else{
errorHandler.error("Unclosed comment");
return -1;
}
}else{
//error
return -1;
}
default:
if(source.substr(start+3,6) == 'CDATA['){
var end = source.indexOf(']]>',start+9);
domBuilder.startCDATA();
domBuilder.characters(source,start+9,end-start-9);
domBuilder.endCDATA()
return end+3;
}
//<!DOCTYPE
//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
var matchs = split(source,start);
var len = matchs.length;
if(len>1 && /!doctype/i.test(matchs[0][0])){
var name = matchs[1][0];
var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0]
var sysid = len>4 && matchs[4][0];
var lastMatch = matchs[len-1]
domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
domBuilder.endDTD();
return lastMatch.index+lastMatch[0].length
}
}
return -1;
}
function parseInstruction(source,start,domBuilder){
var end = source.indexOf('?>',start);
if(end){
var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
if(match){
var len = match[0].length;
domBuilder.processingInstruction(match[1], match[2]) ;
return end+2;
}else{//error
return -1;
}
}
return -1;
}
/**
* @param source
*/
function ElementAttributes(source){
}
ElementAttributes.prototype = {
setTagName:function(tagName){
if(!tagNamePattern.test(tagName)){
throw new Error('invalid tagName:'+tagName)
}
this.tagName = tagName
},
add:function(qName,value,offset){
if(!tagNamePattern.test(qName)){
throw new Error('invalid attribute:'+qName)
}
this[this.length++] = {qName:qName,value:value,offset:offset}
},
length:0,
getLocalName:function(i){return this[i].localName},
getOffset:function(i){return this[i].offset},
getQName:function(i){return this[i].qName},
getURI:function(i){return this[i].uri},
getValue:function(i){return this[i].value}
// ,getIndex:function(uri, localName)){
// if(localName){
//
// }else{
// var qName = uri
// }
// },
// getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
// getType:function(uri,localName){}
// getType:function(i){},
}
function _set_proto_(thiz,parent){
thiz.__proto__ = parent;
return thiz;
}
if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
_set_proto_ = function(thiz,parent){
function p(){};
p.prototype = parent;
p = new p();
for(parent in thiz){
p[parent] = thiz[parent];
}
return p;
}
}
function split(source,start){
var match;
var buf = [];
var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
reg.lastIndex = start;
reg.exec(source);//skip <
while(match = reg.exec(source)){
buf.push(match);
if(match[1])return buf;
}
}
return XMLReader;
});

View file

@ -0,0 +1,92 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2010, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var lang = require("../lib/lang");
var Mirror = require("../worker/mirror").Mirror;
var DOMParser = require("./xml/dom-parser").DOMParser;
var Worker = exports.Worker = function(sender) {
Mirror.call(this, sender);
this.setTimeout(400);
this.context = null;
};
oop.inherits(Worker, Mirror);
(function() {
this.setOptions = function(options) {
this.context = options.context;
};
this.onUpdate = function() {
var value = this.doc.getValue();
if (!value)
return;
var parser = new DOMParser();
var errors = [];
parser.options.errorHandler = {
fatalError: function(fullMsg, errorMsg, locator) {
errors.push({
row: locator.lineNumber,
column: locator.columnNumber,
text: errorMsg,
type: "error"
});
},
error: function(fullMsg, errorMsg, locator) {
errors.push({
row: locator.lineNumber,
column: locator.columnNumber,
text: errorMsg,
type: "error"
});
},
warning: function(fullMsg, errorMsg, locator) {
errors.push({
row: locator.lineNumber,
column: locator.columnNumber,
text: errorMsg,
type: "warning"
});
}
};
parser.parseFromString(value);
this.sender.emit("error", errors);
};
}).call(Worker.prototype);
});

7
lib/ace/snippets/abc.js Normal file
View file

@ -0,0 +1,7 @@
define(function(require, exports, module) {
"use strict";
exports.snippetText = require("../requirejs/text!./abc.snippets");
exports.scope = "abc";
});

View file

@ -0,0 +1,31 @@
snippet zupfnoter.print
%%%%hn.print {"startpos": ${1:pos_y}, "t":"${2:title}", "v":[${3:voices}], "s":[[${4:syncvoices}1,2]], "f":[${5:flowlines}], "sf":[${6:subflowlines}], "j":[${7:jumplines}]}
snippet zupfnoter.note
%%%%hn.note {"pos": [${1:pos_x},${2:pos_y}], "text": "${3:text}", "style": "${4:style}"}
snippet zupfnoter.annotation
%%%%hn.annotation {"id": "${1:id}", "pos": [${2:pos}], "text": "${3:text}"}
snippet zupfnoter.lyrics
%%%%hn.lyrics {"pos": [${1:x_pos},${2:y_pos}]}
snippet zupfnoter.legend
%%%%hn.legend {"pos": [${1:x_pos},${2:y_pos}]}
snippet zupfnoter.target
"^:${1:target}"
snippet zupfnoter.goto
"^@${1:target}@${2:distance}"
snippet zupfnoter.annotationref
"^#${1:target}"
snippet zupfnoter.annotation
"^!${1:text}@${2:x_offset},${3:y_offset}"

View file

@ -750,7 +750,7 @@ var VirtualRenderer = function(container, theme) {
* @returns {Boolean} * @returns {Boolean}
**/ **/
this.getVScrollBarAlwaysVisible = function() { this.getVScrollBarAlwaysVisible = function() {
return this.$hScrollBarAlwaysVisible; return this.$vScrollBarAlwaysVisible;
}; };
/** /**

113
static.js
View file

@ -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
View file

@ -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()

View file

@ -9,7 +9,7 @@ function main(displayName, extRe) {
var demoFileExt = extRe.split("|")[0] || name; var demoFileExt = extRe.split("|")[0] || name;
var demoFileName = demoFileExt[0] == "^" ? demoFileExt.substr(1) : name + "." + demoFileExt; var demoFileName = demoFileExt[0] == "^" ? demoFileExt.substr(1) : name + "." + demoFileExt;
var demoFilePath = lib.AceRoot + "demo/kitchen-sink/docs/" + demoFileName; var demoFilePath = lib.AceRoot + "demo/kitchen-sink/docs/" + demoFileName;
fs.writeFileSync(demoFilePath, "TODO add a nice demo!", "utf8"); fs.writeFileSync(demoFilePath, "TODO add a nice demo!\nTry to keep it short!", "utf8");
console.log("Created demo file at: " + path.normalize(demoFilePath)); console.log("Created demo file at: " + path.normalize(demoFilePath));
/** mode **/ /** mode **/

View file

@ -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="&#10227;" title="sync" id="syncToMode"></select> <input type="button" value="&#10227;" 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>

View file

@ -53,6 +53,7 @@ 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);
updateSaveButtonState(null, editor2);
} }
}); });
}); });
@ -60,6 +61,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 +70,17 @@ 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]);
updateSaveButtonState(null, editor1);
schedule(); schedule();
}); });
}); });
@ -85,6 +90,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)

View file

@ -135,6 +135,10 @@ var deps = {
}); });
} }
}, },
liveScript: {
path: "mode/livescript.js",
url: "https://raw.githubusercontent.com/gkz/LiveScript/master/lib/mode-ls.js"
},
coffee: { coffee: {
fetch: function(){ fetch: function(){
var rootHref = "https://raw.github.com/jashkenas/coffee-script/master/"; var rootHref = "https://raw.github.com/jashkenas/coffee-script/master/";
@ -200,7 +204,24 @@ var deps = {
}); });
} }
} }
} },
xmldom: {
fetch: function() {
var rootHref = "https://raw.githubusercontent.com/iDeBugger/xmldom/master/"
var fileMap = {
"sax.js": "mode/xml/sax.js",
"dom-parser.js": "mode/xml/dom-parser.js",
"dom.js": "mode/xml/dom.js"
};
async.forEach(Object.keys(fileMap), function(x, next) {
download(rootHref + x, function(e, d) {
fs.writeFile(rootDir + fileMap[x], d, next)
})
}, function() {
console.log("XmlDOM updating done")
});
}
},
}; };
var download = function(href, callback) { var download = function(href, callback) {