├── .gitignore ├── LICENSE ├── README.md ├── index.html ├── javascripts ├── autoComplete.js ├── autoCompleteView.js ├── compilationService.js ├── documentPositionUtil.js ├── editorPosition.js ├── fileService.js ├── lib │ ├── ace │ │ ├── ace.js │ │ ├── mode-javascript.js │ │ ├── mode-typescript.js │ │ ├── theme-monokai.js │ │ ├── worker-javascript.js │ │ └── worker-typescript.js │ ├── jquery-1.8.2.min.js │ └── typescript │ │ └── typescriptServices.js ├── lightHarness.js └── main.js ├── samples ├── animal.ts ├── greeter.ts └── raytracer.ts ├── src ├── coffee │ ├── autoCompleteView.coffee │ ├── compilationService.coffee │ ├── documentPositionUtil.coffee │ ├── editorPosition.coffee │ └── fileService.coffee └── typescript-mode │ ├── typescript.js │ └── typescript │ ├── DocumentPositionUtil.js │ ├── lightHarness.js │ └── typescriptServices.js ├── stylesheets ├── bootstrap.min.css └── style.css └── typescripts └── lib.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | *# 2 | #* 3 | *~ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Hitoshi Nakada 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TypeScript Playground on Ace 2 | ========================== 3 | TypeScript Playground build on ace editor 4 | 5 | https://hi104.github.io/typescript-playground-on-ace/ 6 | 7 | See Also 8 | ----------------- 9 | 10 | TypeScript Playground 11 | http://www.typescriptlang.org/Playground/ 12 | 13 | Ace 14 | http://ace.ajax.org 15 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Typescript playground on ace editor 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

TypeScript Playground on Ace Editor

14 |
15 |

16 | typescript playground build on 17 | ace editor. 18 |

19 |

20 |

    21 |
  • shortcut key [Ctrl-Space] : AutoComplete
  • 22 |
23 |

24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |

typescript

32 |
33 |
34 | 40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 |
52 |
Run
53 |
54 |
55 |

javascript

56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 66 | 69 |
70 | 71 | 72 | 73 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /javascripts/autoComplete.js: -------------------------------------------------------------------------------- 1 | define('autocomplete', ['require', 'exports', 'module', 'ace/keyboard/hash_handler'], function(require, exports, module) { 2 | 3 | var HashHandler = require('ace/keyboard/hash_handler').HashHandler; 4 | var EventEmitter = require("ace/lib/event_emitter").EventEmitter; 5 | var AutoCompleteView = require('AutoCompleteView').AutoCompleteView; 6 | 7 | var oop = require("ace/lib/oop"); 8 | 9 | exports.AutoComplete = function(editor,script, compilationService){ 10 | 11 | var self = this; 12 | 13 | oop.implement(self, EventEmitter); 14 | this.handler = new HashHandler(); 15 | this.view = new AutoCompleteView(editor, self); 16 | this.scriptName = script; 17 | this._active = false; 18 | this.inputText =''; //TODO imporve name 19 | 20 | this.isActive = function () { 21 | return self._active; 22 | }; 23 | 24 | this.setScriptName = function (name){ 25 | self.scriptName = name; 26 | }; 27 | 28 | this.show = function () { 29 | self.listElement = self.view.listElement; 30 | editor.container.appendChild(self.view.wrap); 31 | self.listElement.innerHTML = ''; 32 | }; 33 | 34 | this.compilation = function(cursor){ 35 | var compilationInfo = compilationService.getCursorCompilation(self.scriptName, cursor); 36 | var text = compilationService.matchText; 37 | var coords = editor.renderer.textToScreenCoordinates(cursor.row, cursor.column - text.length); 38 | 39 | self.view.setPosition(coords); 40 | self.inputText = text; 41 | 42 | var compilations = compilationInfo.entries; 43 | 44 | if (self.inputText.length > 0){ 45 | compilations = compilationInfo.entries.filter(function(elm){ 46 | return elm.name.toLowerCase().indexOf(self.inputText.toLowerCase()) == 0 ; 47 | }); 48 | } 49 | 50 | var matchFunc = function(elm) { 51 | return elm.name.indexOf(self.inputText) == 0 ? 1 : 0; 52 | }; 53 | 54 | var matchCompare = function(a, b){ 55 | return matchFunc(b) - matchFunc(a); 56 | }; 57 | 58 | var textCompare = function(a, b){ 59 | if (a.name == b.name){ 60 | return 0; 61 | }else{ 62 | return (a.name > b.name) ? 1 : -1; 63 | } 64 | }; 65 | var compare = function(a, b){ 66 | var ret = matchCompare(a, b); 67 | return (ret != 0) ? ret : textCompare(a, b); 68 | }; 69 | 70 | compilations = compilations.sort(compare); 71 | 72 | self.showCompilation(compilations); 73 | 74 | return compilations.length; 75 | }; 76 | 77 | this.refreshCompilation = function(e){ 78 | var cursor = editor.getCursorPosition(); 79 | if(e.data.action == "insertText"){ 80 | cursor.column += 1; 81 | } else if (e.data.action == "removeText"){ 82 | if(e.data.text == '\n'){ 83 | self.deactivate(); 84 | return; 85 | } 86 | } 87 | 88 | self.compilation(cursor); 89 | }; 90 | 91 | this.showCompilation = function(infos){ 92 | if (infos.length > 0){ 93 | self.view.show(); 94 | var html = ''; 95 | // TODO use template 96 | for(var n in infos) { 97 | var info = infos[n]; 98 | var name = '' + info.name + ''; 99 | var type = '' + info.type + ''; 100 | var kind = '' + info.kind.charAt(0) + ''; 101 | 102 | html += '
  • ' + kind + name + type + '
  • '; 103 | } 104 | self.listElement.innerHTML = html; 105 | self.view.ensureFocus(); 106 | }else{ 107 | self.view.hide(); 108 | } 109 | }; 110 | 111 | this.active = function () { 112 | self.show(); 113 | var count = self.compilation(editor.getCursorPosition()); 114 | if(!(count > 0)){ 115 | self.hide(); 116 | return; 117 | } 118 | editor.keyBinding.addKeyboardHandler(self.handler); 119 | }; 120 | 121 | this.deactivate = function() { 122 | editor.keyBinding.removeKeyboardHandler(self.handler); 123 | }; 124 | 125 | this.handler.attach = function(){ 126 | editor.addEventListener("change", self.refreshCompilation); 127 | self._emit("attach", {sender: self}); 128 | self._active = true; 129 | }; 130 | 131 | this.handler.detach = function(){ 132 | editor.removeEventListener("change", self.refreshCompilation); 133 | self.view.hide(); 134 | self._emit("detach", {sender: self}); 135 | self._active = false; 136 | }; 137 | 138 | this.handler.handleKeyboard = function(data, hashId, key, keyCode) { 139 | if (hashId == -1) { 140 | 141 | if(" -=,[]_/()!';:<>".indexOf(key) != -1){ //TODO 142 | self.deactivate(); 143 | } 144 | return null; 145 | } 146 | 147 | var command = self.handler.findKeyCommand(hashId, key); 148 | 149 | if (!command){ 150 | 151 | var defaultCommand = editor.commands.findKeyCommand(hashId, key); 152 | if(defaultCommand){ 153 | if(defaultCommand.name == "backspace"){ 154 | return null; 155 | } 156 | self.deactivate(); 157 | } 158 | return null; 159 | } 160 | 161 | if (typeof command != "string") { 162 | var args = command.args; 163 | command = command.command; 164 | } 165 | 166 | if (typeof command == "string") { 167 | command = this.commands[command]; 168 | } 169 | 170 | return {command: command, args: args}; 171 | }; 172 | 173 | 174 | exports.Keybinding = { 175 | "Up|Ctrl-p" : "focusprev", 176 | "Down|Ctrl-n" : "focusnext", 177 | "esc|Ctrl-g" : "cancel", 178 | "Return|Tab": "insertComplete" 179 | }; 180 | 181 | this.handler.bindKeys(exports.Keybinding); 182 | 183 | this.handler.addCommands({ 184 | focusnext:function(editor){ 185 | self.view.focusNext(); 186 | }, 187 | focusprev:function(editor){ 188 | self.view.focusPrev(); 189 | }, 190 | cancel:function(editor){ 191 | self.deactivate(); 192 | }, 193 | insertComplete:function(editor){ 194 | editor.removeEventListener("change", self.refreshCompilation); 195 | var curr = self.view.current(); 196 | 197 | for(var i = 0; i< self.inputText.length; i++){ 198 | editor.remove("left"); 199 | } 200 | 201 | if(curr){ 202 | editor.insert($(curr).data("name")); 203 | } 204 | self.deactivate(); 205 | 206 | } 207 | }); 208 | }; 209 | }); -------------------------------------------------------------------------------- /javascripts/autoCompleteView.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; 3 | 4 | define('AutoCompleteView', ['require', 'exports', 'module'], function(require, exports, module) { 5 | var AutoCompleteView, selectedClassName; 6 | selectedClassName = 'ace_autocomplete_selected'; 7 | AutoCompleteView = (function() { 8 | 9 | function AutoCompleteView(editor, autoComplete) { 10 | this.editor = editor; 11 | this.autoComplete = autoComplete; 12 | this.init = __bind(this.init, this); 13 | this.init(); 14 | } 15 | 16 | AutoCompleteView.prototype.init = function() { 17 | this.wrap = document.createElement('div'); 18 | this.listElement = document.createElement('ul'); 19 | this.wrap.className = 'ace_autocomplete'; 20 | this.wrap.style.display = 'none'; 21 | this.listElement.style.listStyleType = 'none'; 22 | this.wrap.style.position = 'fixed'; 23 | this.wrap.style.zIndex = '1000'; 24 | return this.wrap.appendChild(this.listElement); 25 | }; 26 | 27 | AutoCompleteView.prototype.show = function() { 28 | return this.wrap.style.display = 'block'; 29 | }; 30 | 31 | AutoCompleteView.prototype.hide = function() { 32 | return this.wrap.style.display = 'none'; 33 | }; 34 | 35 | AutoCompleteView.prototype.setPosition = function(coords) { 36 | var bottom, editorBottom, top; 37 | top = coords.pageY + 20; 38 | editorBottom = $(this.editor.container).offset().top + $(this.editor.container).height(); 39 | bottom = top + $(this.wrap).height(); 40 | if (bottom < editorBottom) { 41 | this.wrap.style.top = top + 'px'; 42 | return this.wrap.style.left = coords.pageX + 'px'; 43 | } else { 44 | this.wrap.style.top = (top - $(this.wrap).height() - 20) + 'px'; 45 | return this.wrap.style.left = coords.pageX + 'px'; 46 | } 47 | }; 48 | 49 | AutoCompleteView.prototype.current = function() { 50 | var child, children, i; 51 | children = this.listElement.childNodes; 52 | for (i in children) { 53 | child = children[i]; 54 | if (child.className === selectedClassName) return child; 55 | } 56 | return null; 57 | }; 58 | 59 | AutoCompleteView.prototype.focusNext = function() { 60 | var curr, focus; 61 | curr = this.current(); 62 | focus = curr.nextSibling; 63 | if (focus) { 64 | curr.className = ''; 65 | focus.className = selectedClassName; 66 | return this.adjustPosition(); 67 | } 68 | }; 69 | 70 | AutoCompleteView.prototype.focusPrev = function() { 71 | var curr, focus; 72 | curr = this.current(); 73 | focus = curr.previousSibling; 74 | if (focus) { 75 | curr.className = ''; 76 | focus.className = selectedClassName; 77 | return this.adjustPosition(); 78 | } 79 | }; 80 | 81 | AutoCompleteView.prototype.ensureFocus = function() { 82 | if (!this.current()) { 83 | if (this.listElement.firstChild) { 84 | this.listElement.firstChild.className = selectedClassName; 85 | return this.adjustPosition(); 86 | } 87 | } 88 | }; 89 | 90 | AutoCompleteView.prototype.adjustPosition = function() { 91 | var elm, elmOuterHeight, newMargin, pos, preMargin, wrapHeight; 92 | elm = this.current(); 93 | if (elm) { 94 | newMargin = ''; 95 | wrapHeight = $(this.wrap).height(); 96 | elmOuterHeight = $(elm).outerHeight(); 97 | preMargin = $(this.listElement).css("margin-top").replace('px', ''); 98 | preMargin = parseInt(preMargin); 99 | pos = $(elm).position(); 100 | if (pos.top >= (wrapHeight - elmOuterHeight)) { 101 | newMargin = (preMargin - elmOuterHeight) + 'px'; 102 | $(this.listElement).css("margin-top", newMargin); 103 | } 104 | if (pos.top < 0) { 105 | newMargin = (-pos.top + preMargin) + 'px'; 106 | return $(this.listElement).css("margin-top", newMargin); 107 | } 108 | } 109 | }; 110 | 111 | return AutoCompleteView; 112 | 113 | })(); 114 | exports.AutoCompleteView = AutoCompleteView; 115 | return exports; 116 | }); 117 | 118 | }).call(this); 119 | -------------------------------------------------------------------------------- /javascripts/compilationService.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; 3 | 4 | define('CompilationService', ['require', 'exports', 'module', 'EditorPosition'], function(require, exports, module) { 5 | var CompilationService, EditorPosition; 6 | EditorPosition = require('EditorPosition').EditorPosition; 7 | CompilationService = (function() { 8 | 9 | function CompilationService(editor, ServiceShim) { 10 | this.editor = editor; 11 | this.ServiceShim = ServiceShim; 12 | this.getCurrentPositionCompilation = __bind(this.getCurrentPositionCompilation, this); 13 | this.getCursorCompilation = __bind(this.getCursorCompilation, this); 14 | this.getCompilation = __bind(this.getCompilation, this); 15 | this.editorPos = new EditorPosition(this.editor); 16 | } 17 | 18 | CompilationService.prototype.getCompilation = function(script, charpos, isMemberCompletion) { 19 | var compInfo; 20 | compInfo = this.ServiceShim.languageService.getCompletionsAtPosition(script, charpos, isMemberCompletion); 21 | return compInfo; 22 | }; 23 | 24 | CompilationService.prototype.getCursorCompilation = function(script, cursor) { 25 | var isMemberCompletion, matches, pos, text; 26 | pos = this.editorPos.getPositionChars(cursor); 27 | text = this.editor.session.getLine(cursor.row).slice(0, cursor.column); 28 | isMemberCompletion = false; 29 | matches = text.match(/\.([a-zA-Z_0-9\$]*$)/); 30 | if (matches && matches.length > 0) { 31 | this.matchText = matches[1]; 32 | isMemberCompletion = true; 33 | pos -= this.matchText.length; 34 | } else { 35 | matches = text.match(/[a-zA-Z_0-9\$]*$/); 36 | this.matchText = matches[0]; 37 | } 38 | return this.getCompilation(script, pos, isMemberCompletion); 39 | }; 40 | 41 | CompilationService.prototype.getCurrentPositionCompilation = function(script) { 42 | return this.getCursorCompilation(script, this.editor.getCursorPosition()); 43 | }; 44 | 45 | return CompilationService; 46 | 47 | })(); 48 | exports.CompilationService = CompilationService; 49 | return exports; 50 | }); 51 | 52 | }).call(this); 53 | -------------------------------------------------------------------------------- /javascripts/documentPositionUtil.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | define('DocumentPositionUtil', ['require', 'exports', 'module'], function(require, exports, module) { 4 | var DocumentPositionUtil; 5 | DocumentPositionUtil = (function() { 6 | 7 | function DocumentPositionUtil() {} 8 | 9 | DocumentPositionUtil.getLinesChars = function(lines) { 10 | var count, 11 | _this = this; 12 | count = 0; 13 | lines.forEach(function(line) { 14 | return count += line.length + 1; 15 | }); 16 | return count; 17 | }; 18 | 19 | DocumentPositionUtil.getChars = function(doc, pos) { 20 | return this.getLinesChars(doc.getLines(0, pos.row - 1)) + pos.column; 21 | }; 22 | 23 | DocumentPositionUtil.getPosition = function(doc, chars) { 24 | var count, i, line, lines, row; 25 | lines = doc.getAllLines(); 26 | count = 0; 27 | row = 0; 28 | for (i in lines) { 29 | line = lines[i]; 30 | if (chars < (count + (line.length + 1))) { 31 | return { 32 | row: row, 33 | column: chars - count 34 | }; 35 | } 36 | count += line.length + 1; 37 | row += 1; 38 | } 39 | return { 40 | row: row, 41 | column: chars - count 42 | }; 43 | }; 44 | 45 | return DocumentPositionUtil; 46 | 47 | })(); 48 | exports.DocumentPositionUtil = DocumentPositionUtil; 49 | return exports; 50 | }); 51 | 52 | }).call(this); 53 | -------------------------------------------------------------------------------- /javascripts/editorPosition.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; 3 | 4 | define('EditorPosition', ['require', 'exports', 'module'], function(require, exports, module) { 5 | var DocumentPositionUtil, EditorPosition; 6 | DocumentPositionUtil = require('DocumentPositionUtil').DocumentPositionUtil; 7 | EditorPosition = (function() { 8 | 9 | function EditorPosition(editor) { 10 | this.editor = editor; 11 | this.getPositionLeftChar = __bind(this.getPositionLeftChar, this); 12 | this.getPositionChar = __bind(this.getPositionChar, this); 13 | this.getCurrentLeftChar = __bind(this.getCurrentLeftChar, this); 14 | this.getCurrentCharPosition = __bind(this.getCurrentCharPosition, this); 15 | this.getAcePositionFromChars = __bind(this.getAcePositionFromChars, this); 16 | this.getPositionChars = __bind(this.getPositionChars, this); 17 | } 18 | 19 | EditorPosition.prototype.getLinesChars = function(lines) { 20 | return DocumentPositionUtil.getLinesChars(lines); 21 | }; 22 | 23 | EditorPosition.prototype.getPositionChars = function(pos) { 24 | var doc; 25 | doc = this.editor.getSession().getDocument(); 26 | return DocumentPositionUtil.getChars(doc, pos); 27 | }; 28 | 29 | EditorPosition.prototype.getAcePositionFromChars = function(chars) { 30 | var doc; 31 | doc = this.editor.getSession().getDocument(); 32 | return DocumentPositionUtil.getPosition(doc, chars); 33 | }; 34 | 35 | EditorPosition.prototype.getCurrentCharPosition = function() { 36 | return this.getPositionChars(this.editor.getCursorPosition()); 37 | }; 38 | 39 | EditorPosition.prototype.getCurrentLeftChar = function() { 40 | return this.getPositionLeftChar(this.editor.getCursorPosition()); 41 | }; 42 | 43 | EditorPosition.prototype.getPositionChar = function(cursor) { 44 | var range; 45 | range = { 46 | start: { 47 | row: cursor.row, 48 | column: cursor.column 49 | }, 50 | end: { 51 | row: cursor.row, 52 | column: cursor.column + 1 53 | } 54 | }; 55 | return this.editor.getSession().getDocument().getTextRange(range); 56 | }; 57 | 58 | EditorPosition.prototype.getPositionLeftChar = function(cursor) { 59 | var range; 60 | range = { 61 | start: { 62 | row: cursor.row, 63 | column: cursor.column 64 | }, 65 | end: { 66 | row: cursor.row, 67 | column: cursor.column - 1 68 | } 69 | }; 70 | return this.editor.getSession().getDocument().getTextRange(range); 71 | }; 72 | 73 | return EditorPosition; 74 | 75 | })(); 76 | exports.EditorPosition = EditorPosition; 77 | return exports; 78 | }); 79 | 80 | }).call(this); 81 | -------------------------------------------------------------------------------- /javascripts/fileService.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; 3 | 4 | define('FileService', ['require', 'exports', 'module'], function(require, exports, module) { 5 | var FileService; 6 | FileService = (function() { 7 | 8 | function FileService(ajaxHost) { 9 | this.ajaxHost = ajaxHost; 10 | this.getInfo = __bind(this.getInfo, this); 11 | this.writeFile = __bind(this.writeFile, this); 12 | this.readFile = __bind(this.readFile, this); 13 | } 14 | 15 | FileService.prototype.readFile = function(path, cb) { 16 | var _this = this; 17 | return this.ajaxHost.ajax({ 18 | type: "GET", 19 | url: path, 20 | success: cb, 21 | error: (function(jqXHR, textStatus) { 22 | return console.log(textStatus); 23 | }) 24 | }); 25 | }; 26 | 27 | FileService.prototype.writeFile = function(path, content, cb) { 28 | var _this = this; 29 | return this.ajaxHost.ajax({ 30 | type: "POST", 31 | url: path, 32 | data: { 33 | content: content 34 | }, 35 | success: cb, 36 | error: (function(jqXHR, textStatus) { 37 | return console.log(textStatus); 38 | }) 39 | }); 40 | }; 41 | 42 | FileService.prototype.getInfo = function() {}; 43 | 44 | return FileService; 45 | 46 | })(); 47 | exports.FileService = FileService; 48 | return exports; 49 | }); 50 | 51 | }).call(this); 52 | -------------------------------------------------------------------------------- /javascripts/lib/ace/mode-javascript.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Distributed under the BSD license: 3 | * 4 | * Copyright (c) 2010, Ajax.org B.V. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Ajax.org B.V. nor the 15 | * names of its contributors may be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | * ***** END LICENSE BLOCK ***** */ 30 | 31 | define('ace/mode/javascript', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/javascript_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/range', 'ace/worker/worker_client', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle'], function(require, exports, module) { 32 | 33 | 34 | var oop = require("../lib/oop"); 35 | var TextMode = require("./text").Mode; 36 | var Tokenizer = require("../tokenizer").Tokenizer; 37 | var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; 38 | var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; 39 | var Range = require("../range").Range; 40 | var WorkerClient = require("../worker/worker_client").WorkerClient; 41 | var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; 42 | var CStyleFoldMode = require("./folding/cstyle").FoldMode; 43 | 44 | var Mode = function() { 45 | this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules()); 46 | this.$outdent = new MatchingBraceOutdent(); 47 | this.$behaviour = new CstyleBehaviour(); 48 | this.foldingRules = new CStyleFoldMode(); 49 | }; 50 | oop.inherits(Mode, TextMode); 51 | 52 | (function() { 53 | 54 | 55 | this.toggleCommentLines = function(state, doc, startRow, endRow) { 56 | var outdent = true; 57 | var re = /^(\s*)\/\//; 58 | 59 | for (var i=startRow; i<= endRow; i++) { 60 | if (!re.test(doc.getLine(i))) { 61 | outdent = false; 62 | break; 63 | } 64 | } 65 | 66 | if (outdent) { 67 | var deleteRange = new Range(0, 0, 0, 0); 68 | for (var i=startRow; i<= endRow; i++) 69 | { 70 | var line = doc.getLine(i); 71 | var m = line.match(re); 72 | deleteRange.start.row = i; 73 | deleteRange.end.row = i; 74 | deleteRange.end.column = m[0].length; 75 | doc.replace(deleteRange, m[1]); 76 | } 77 | } 78 | else { 79 | doc.indentRows(startRow, endRow, "//"); 80 | } 81 | }; 82 | 83 | this.getNextLineIndent = function(state, line, tab) { 84 | var indent = this.$getIndent(line); 85 | 86 | var tokenizedLine = this.$tokenizer.getLineTokens(line, state); 87 | var tokens = tokenizedLine.tokens; 88 | var endState = tokenizedLine.state; 89 | 90 | if (tokens.length && tokens[tokens.length-1].type == "comment") { 91 | return indent; 92 | } 93 | 94 | if (state == "start" || state == "regex_allowed") { 95 | var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); 96 | if (match) { 97 | indent += tab; 98 | } 99 | } else if (state == "doc-start") { 100 | if (endState == "start" || state == "regex_allowed") { 101 | return ""; 102 | } 103 | var match = line.match(/^\s*(\/?)\*/); 104 | if (match) { 105 | if (match[1]) { 106 | indent += " "; 107 | } 108 | indent += "* "; 109 | } 110 | } 111 | 112 | return indent; 113 | }; 114 | 115 | this.checkOutdent = function(state, line, input) { 116 | return this.$outdent.checkOutdent(line, input); 117 | }; 118 | 119 | this.autoOutdent = function(state, doc, row) { 120 | this.$outdent.autoOutdent(doc, row); 121 | }; 122 | 123 | this.createWorker = function(session) { 124 | var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); 125 | worker.attachToDocument(session.getDocument()); 126 | 127 | worker.on("jslint", function(results) { 128 | session.setAnnotations(results.data); 129 | }); 130 | 131 | worker.on("terminate", function() { 132 | session.clearAnnotations(); 133 | }); 134 | 135 | return worker; 136 | }; 137 | 138 | }).call(Mode.prototype); 139 | 140 | exports.Mode = Mode; 141 | }); 142 | 143 | define('ace/mode/javascript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules'], function(require, exports, module) { 144 | 145 | 146 | var oop = require("../lib/oop"); 147 | var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; 148 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; 149 | 150 | var JavaScriptHighlightRules = function() { 151 | // see: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects 152 | var keywordMapper = this.createKeywordMapper({ 153 | "variable.language": 154 | "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors 155 | "Namespace|QName|XML|XMLList|" + // E4X 156 | "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + 157 | "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + 158 | "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors 159 | "SyntaxError|TypeError|URIError|" + 160 | "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions 161 | "isNaN|parseFloat|parseInt|" + 162 | "JSON|Math|" + // Other 163 | "this|arguments|prototype|window|document" , // Pseudo 164 | "invalid.deprecated": 165 | "__parent__|__count__|escape|unescape|with|__proto__", 166 | "keyword": 167 | "const|yield|import|get|set" + 168 | "break|case|catch|continue|default|delete|do|else|finally|for|function|" + 169 | "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger", 170 | "storage.type": 171 | "const|let|var|function", 172 | "invalid.illegal": 173 | "class|enum|extends|super|export|implements|private|" + 174 | "public|interface|package|protected|static", 175 | "constant.language": 176 | "null|Infinity|NaN|undefined", 177 | "support.function": 178 | "alert" 179 | }, "identifier"); 180 | 181 | // keywords which can be followed by regular expressions 182 | var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield"; 183 | 184 | // TODO: Unicode escape sequences 185 | var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; 186 | 187 | var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex 188 | "u[0-9a-fA-F]{4}|" + // unicode 189 | "[0-2][0-7]{0,2}|" + // oct 190 | "3[0-6][0-7]?|" + // oct 191 | "37[0-7]?|" + // oct 192 | "[4-7][0-7]?|" + //oct 193 | ".)"; 194 | 195 | // regexp must not have capturing parentheses. Use (?:) instead. 196 | // regexps are ordered -> the first match is used 197 | 198 | this.$rules = { 199 | "start" : [ 200 | { 201 | token : "comment", 202 | regex : /\/\/.*$/ 203 | }, 204 | DocCommentHighlightRules.getStartRule("doc-start"), 205 | { 206 | token : "comment", // multi line comment 207 | merge : true, 208 | regex : /\/\*/, 209 | next : "comment" 210 | }, { 211 | token : "string", 212 | regex : "'(?=.)", 213 | next : "qstring" 214 | }, { 215 | token : "string", 216 | regex : '"(?=.)', 217 | next : "qqstring" 218 | }, { 219 | token : "constant.numeric", // hex 220 | regex : /0[xX][0-9a-fA-F]+\b/ 221 | }, { 222 | token : "constant.numeric", // float 223 | regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ 224 | }, { 225 | // Sound.prototype.play = 226 | token : [ 227 | "storage.type", "punctuation.operator", "support.function", 228 | "punctuation.operator", "entity.name.function", "text","keyword.operator" 229 | ], 230 | regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", 231 | next: "function_arguments" 232 | }, { 233 | // Sound.play = function() { } 234 | token : [ 235 | "storage.type", "punctuation.operator", "entity.name.function", "text", 236 | "keyword.operator", "text", "storage.type", "text", "paren.lparen" 237 | ], 238 | regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", 239 | next: "function_arguments" 240 | }, { 241 | // play = function() { } 242 | token : [ 243 | "entity.name.function", "text", "keyword.operator", "text", "storage.type", 244 | "text", "paren.lparen" 245 | ], 246 | regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", 247 | next: "function_arguments" 248 | }, { 249 | // Sound.play = function play() { } 250 | token : [ 251 | "storage.type", "punctuation.operator", "entity.name.function", "text", 252 | "keyword.operator", "text", 253 | "storage.type", "text", "entity.name.function", "text", "paren.lparen" 254 | ], 255 | regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", 256 | next: "function_arguments" 257 | }, { 258 | // function myFunc(arg) { } 259 | token : [ 260 | "storage.type", "text", "entity.name.function", "text", "paren.lparen" 261 | ], 262 | regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", 263 | next: "function_arguments" 264 | }, { 265 | // foobar: function() { } 266 | token : [ 267 | "entity.name.function", "text", "punctuation.operator", 268 | "text", "storage.type", "text", "paren.lparen" 269 | ], 270 | regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", 271 | next: "function_arguments" 272 | }, { 273 | // : function() { } (this is for issues with 'foo': function() { }) 274 | token : [ 275 | "text", "text", "storage.type", "text", "paren.lparen" 276 | ], 277 | regex : "(:)(\\s*)(function)(\\s*)(\\()", 278 | next: "function_arguments" 279 | }, { 280 | token : "constant.language.boolean", 281 | regex : /(?:true|false)\b/ 282 | }, { 283 | token : "keyword", 284 | regex : "(?:" + kwBeforeRe + ")\\b", 285 | next : "regex_allowed" 286 | }, { 287 | token : ["punctuation.operator", "support.function"], 288 | regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ 289 | }, { 290 | token : ["punctuation.operator", "support.function.dom"], 291 | regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ 292 | }, { 293 | token : ["punctuation.operator", "support.constant"], 294 | regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ 295 | }, { 296 | token : ["storage.type", "punctuation.operator", "support.function.firebug"], 297 | regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/ 298 | }, { 299 | token : keywordMapper, 300 | regex : identifierRe 301 | }, { 302 | token : "keyword.operator", 303 | regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/, 304 | next : "regex_allowed" 305 | }, { 306 | token : "punctuation.operator", 307 | regex : /\?|\:|\,|\;|\./, 308 | next : "regex_allowed" 309 | }, { 310 | token : "paren.lparen", 311 | regex : /[\[({]/, 312 | next : "regex_allowed" 313 | }, { 314 | token : "paren.rparen", 315 | regex : /[\])}]/ 316 | }, { 317 | token : "keyword.operator", 318 | regex : /\/=?/, 319 | next : "regex_allowed" 320 | }, { 321 | token: "comment", 322 | regex: /^#!.*$/ 323 | }, { 324 | token : "text", 325 | regex : /\s+/ 326 | } 327 | ], 328 | // regular expressions are only allowed after certain tokens. This 329 | // makes sure we don't mix up regexps with the divison operator 330 | "regex_allowed": [ 331 | DocCommentHighlightRules.getStartRule("doc-start"), 332 | { 333 | token : "comment", // multi line comment 334 | merge : true, 335 | regex : "\\/\\*", 336 | next : "comment_regex_allowed" 337 | }, { 338 | token : "comment", 339 | regex : "\\/\\/.*$" 340 | }, { 341 | token: "string.regexp", 342 | regex: "\\/", 343 | next: "regex", 344 | merge: true 345 | }, { 346 | token : "text", 347 | regex : "\\s+" 348 | }, { 349 | // immediately return to the start mode without matching 350 | // anything 351 | token: "empty", 352 | regex: "", 353 | next: "start" 354 | } 355 | ], 356 | "regex": [ 357 | { 358 | // escapes 359 | token: "regexp.keyword.operator", 360 | regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" 361 | }, { 362 | // flag 363 | token: "string.regexp", 364 | regex: "/\\w*", 365 | next: "start", 366 | merge: true 367 | }, { 368 | // invalid operators 369 | token : "invalid", 370 | regex: /\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ 371 | }, { 372 | // operators 373 | token : "constant.language.escape", 374 | regex: /\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/ 375 | }, { 376 | token: "string.regexp", 377 | regex: /{|[^{\[\/\\(|)$^+*?]+/, 378 | merge: true 379 | }, { 380 | token: "constant.language.escape", 381 | regex: /\[\^?/, 382 | next: "regex_character_class", 383 | merge: true 384 | }, { 385 | token: "empty", 386 | regex: "", 387 | next: "start" 388 | } 389 | ], 390 | "regex_character_class": [ 391 | { 392 | token: "regexp.keyword.operator", 393 | regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" 394 | }, { 395 | token: "constant.language.escape", 396 | regex: "]", 397 | next: "regex", 398 | merge: true 399 | }, { 400 | token: "constant.language.escape", 401 | regex: "-" 402 | }, { 403 | token: "string.regexp.charachterclass", 404 | regex: /[^\]\-\\]+/, 405 | merge: true 406 | }, { 407 | token: "empty", 408 | regex: "", 409 | next: "start" 410 | } 411 | ], 412 | "function_arguments": [ 413 | { 414 | token: "variable.parameter", 415 | regex: identifierRe 416 | }, { 417 | token: "punctuation.operator", 418 | regex: "[, ]+", 419 | merge: true 420 | }, { 421 | token: "punctuation.operator", 422 | regex: "$", 423 | merge: true 424 | }, { 425 | token: "empty", 426 | regex: "", 427 | next: "start" 428 | } 429 | ], 430 | "comment_regex_allowed" : [ 431 | { 432 | token : "comment", // closing comment 433 | regex : ".*?\\*\\/", 434 | merge : true, 435 | next : "regex_allowed" 436 | }, { 437 | token : "comment", // comment spanning whole line 438 | merge : true, 439 | regex : ".+" 440 | } 441 | ], 442 | "comment" : [ 443 | { 444 | token : "comment", // closing comment 445 | regex : ".*?\\*\\/", 446 | merge : true, 447 | next : "start" 448 | }, { 449 | token : "comment", // comment spanning whole line 450 | merge : true, 451 | regex : ".+" 452 | } 453 | ], 454 | "qqstring" : [ 455 | { 456 | token : "constant.language.escape", 457 | regex : escapedRe 458 | }, { 459 | token : "string", 460 | regex : '[^"\\\\]+', 461 | merge : true 462 | }, { 463 | token : "string", 464 | regex : "\\\\$", 465 | next : "qqstring", 466 | merge : true 467 | }, { 468 | token : "string", 469 | regex : '"|$', 470 | next : "start", 471 | merge : true 472 | } 473 | ], 474 | "qstring" : [ 475 | { 476 | token : "constant.language.escape", 477 | regex : escapedRe 478 | }, { 479 | token : "string", 480 | regex : "[^'\\\\]+", 481 | merge : true 482 | }, { 483 | token : "string", 484 | regex : "\\\\$", 485 | next : "qstring", 486 | merge : true 487 | }, { 488 | token : "string", 489 | regex : "'|$", 490 | next : "start", 491 | merge : true 492 | } 493 | ] 494 | }; 495 | 496 | this.embedRules(DocCommentHighlightRules, "doc-", 497 | [ DocCommentHighlightRules.getEndRule("start") ]); 498 | }; 499 | 500 | oop.inherits(JavaScriptHighlightRules, TextHighlightRules); 501 | 502 | exports.JavaScriptHighlightRules = JavaScriptHighlightRules; 503 | }); 504 | 505 | define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) { 506 | 507 | 508 | var oop = require("../lib/oop"); 509 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; 510 | 511 | var DocCommentHighlightRules = function() { 512 | 513 | this.$rules = { 514 | "start" : [ { 515 | token : "comment.doc.tag", 516 | regex : "@[\\w\\d_]+" // TODO: fix email addresses 517 | }, { 518 | token : "comment.doc", 519 | merge : true, 520 | regex : "\\s+" 521 | }, { 522 | token : "comment.doc", 523 | merge : true, 524 | regex : "TODO" 525 | }, { 526 | token : "comment.doc", 527 | merge : true, 528 | regex : "[^@\\*]+" 529 | }, { 530 | token : "comment.doc", 531 | merge : true, 532 | regex : "." 533 | }] 534 | }; 535 | }; 536 | 537 | oop.inherits(DocCommentHighlightRules, TextHighlightRules); 538 | 539 | DocCommentHighlightRules.getStartRule = function(start) { 540 | return { 541 | token : "comment.doc", // doc comment 542 | merge : true, 543 | regex : "\\/\\*(?=\\*)", 544 | next : start 545 | }; 546 | }; 547 | 548 | DocCommentHighlightRules.getEndRule = function (start) { 549 | return { 550 | token : "comment.doc", // closing comment 551 | merge : true, 552 | regex : "\\*\\/", 553 | next : start 554 | }; 555 | }; 556 | 557 | 558 | exports.DocCommentHighlightRules = DocCommentHighlightRules; 559 | 560 | }); 561 | 562 | define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { 563 | 564 | 565 | var Range = require("../range").Range; 566 | 567 | var MatchingBraceOutdent = function() {}; 568 | 569 | (function() { 570 | 571 | this.checkOutdent = function(line, input) { 572 | if (! /^\s+$/.test(line)) 573 | return false; 574 | 575 | return /^\s*\}/.test(input); 576 | }; 577 | 578 | this.autoOutdent = function(doc, row) { 579 | var line = doc.getLine(row); 580 | var match = line.match(/^(\s*\})/); 581 | 582 | if (!match) return 0; 583 | 584 | var column = match[1].length; 585 | var openBracePos = doc.findMatchingBracket({row: row, column: column}); 586 | 587 | if (!openBracePos || openBracePos.row == row) return 0; 588 | 589 | var indent = this.$getIndent(doc.getLine(openBracePos.row)); 590 | doc.replace(new Range(row, 0, row, column-1), indent); 591 | }; 592 | 593 | this.$getIndent = function(line) { 594 | var match = line.match(/^(\s+)/); 595 | if (match) { 596 | return match[1]; 597 | } 598 | 599 | return ""; 600 | }; 601 | 602 | }).call(MatchingBraceOutdent.prototype); 603 | 604 | exports.MatchingBraceOutdent = MatchingBraceOutdent; 605 | }); 606 | 607 | define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour'], function(require, exports, module) { 608 | 609 | 610 | var oop = require("../../lib/oop"); 611 | var Behaviour = require("../behaviour").Behaviour; 612 | 613 | var CstyleBehaviour = function () { 614 | 615 | this.add("braces", "insertion", function (state, action, editor, session, text) { 616 | if (text == '{') { 617 | var selection = editor.getSelectionRange(); 618 | var selected = session.doc.getTextRange(selection); 619 | if (selected !== "") { 620 | return { 621 | text: '{' + selected + '}', 622 | selection: false 623 | }; 624 | } else { 625 | return { 626 | text: '{}', 627 | selection: [1, 1] 628 | }; 629 | } 630 | } else if (text == '}') { 631 | var cursor = editor.getCursorPosition(); 632 | var line = session.doc.getLine(cursor.row); 633 | var rightChar = line.substring(cursor.column, cursor.column + 1); 634 | if (rightChar == '}') { 635 | var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); 636 | if (matching !== null) { 637 | return { 638 | text: '', 639 | selection: [1, 1] 640 | }; 641 | } 642 | } 643 | } else if (text == "\n") { 644 | var cursor = editor.getCursorPosition(); 645 | var line = session.doc.getLine(cursor.row); 646 | var rightChar = line.substring(cursor.column, cursor.column + 1); 647 | if (rightChar == '}') { 648 | var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1}); 649 | if (!openBracePos) 650 | return null; 651 | 652 | var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString()); 653 | var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row)); 654 | 655 | return { 656 | text: '\n' + indent + '\n' + next_indent, 657 | selection: [1, indent.length, 1, indent.length] 658 | }; 659 | } 660 | } 661 | }); 662 | 663 | this.add("braces", "deletion", function (state, action, editor, session, range) { 664 | var selected = session.doc.getTextRange(range); 665 | if (!range.isMultiLine() && selected == '{') { 666 | var line = session.doc.getLine(range.start.row); 667 | var rightChar = line.substring(range.end.column, range.end.column + 1); 668 | if (rightChar == '}') { 669 | range.end.column++; 670 | return range; 671 | } 672 | } 673 | }); 674 | 675 | this.add("parens", "insertion", function (state, action, editor, session, text) { 676 | if (text == '(') { 677 | var selection = editor.getSelectionRange(); 678 | var selected = session.doc.getTextRange(selection); 679 | if (selected !== "") { 680 | return { 681 | text: '(' + selected + ')', 682 | selection: false 683 | }; 684 | } else { 685 | return { 686 | text: '()', 687 | selection: [1, 1] 688 | }; 689 | } 690 | } else if (text == ')') { 691 | var cursor = editor.getCursorPosition(); 692 | var line = session.doc.getLine(cursor.row); 693 | var rightChar = line.substring(cursor.column, cursor.column + 1); 694 | if (rightChar == ')') { 695 | var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); 696 | if (matching !== null) { 697 | return { 698 | text: '', 699 | selection: [1, 1] 700 | }; 701 | } 702 | } 703 | } 704 | }); 705 | 706 | this.add("parens", "deletion", function (state, action, editor, session, range) { 707 | var selected = session.doc.getTextRange(range); 708 | if (!range.isMultiLine() && selected == '(') { 709 | var line = session.doc.getLine(range.start.row); 710 | var rightChar = line.substring(range.start.column + 1, range.start.column + 2); 711 | if (rightChar == ')') { 712 | range.end.column++; 713 | return range; 714 | } 715 | } 716 | }); 717 | 718 | this.add("brackets", "insertion", function (state, action, editor, session, text) { 719 | if (text == '[') { 720 | var selection = editor.getSelectionRange(); 721 | var selected = session.doc.getTextRange(selection); 722 | if (selected !== "") { 723 | return { 724 | text: '[' + selected + ']', 725 | selection: false 726 | }; 727 | } else { 728 | return { 729 | text: '[]', 730 | selection: [1, 1] 731 | }; 732 | } 733 | } else if (text == ']') { 734 | var cursor = editor.getCursorPosition(); 735 | var line = session.doc.getLine(cursor.row); 736 | var rightChar = line.substring(cursor.column, cursor.column + 1); 737 | if (rightChar == ']') { 738 | var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); 739 | if (matching !== null) { 740 | return { 741 | text: '', 742 | selection: [1, 1] 743 | }; 744 | } 745 | } 746 | } 747 | }); 748 | 749 | this.add("brackets", "deletion", function (state, action, editor, session, range) { 750 | var selected = session.doc.getTextRange(range); 751 | if (!range.isMultiLine() && selected == '[') { 752 | var line = session.doc.getLine(range.start.row); 753 | var rightChar = line.substring(range.start.column + 1, range.start.column + 2); 754 | if (rightChar == ']') { 755 | range.end.column++; 756 | return range; 757 | } 758 | } 759 | }); 760 | 761 | this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { 762 | if (text == '"' || text == "'") { 763 | var quote = text; 764 | var selection = editor.getSelectionRange(); 765 | var selected = session.doc.getTextRange(selection); 766 | if (selected !== "") { 767 | return { 768 | text: quote + selected + quote, 769 | selection: false 770 | }; 771 | } else { 772 | var cursor = editor.getCursorPosition(); 773 | var line = session.doc.getLine(cursor.row); 774 | var leftChar = line.substring(cursor.column-1, cursor.column); 775 | 776 | // We're escaped. 777 | if (leftChar == '\\') { 778 | return null; 779 | } 780 | 781 | // Find what token we're inside. 782 | var tokens = session.getTokens(selection.start.row); 783 | var col = 0, token; 784 | var quotepos = -1; // Track whether we're inside an open quote. 785 | 786 | for (var x = 0; x < tokens.length; x++) { 787 | token = tokens[x]; 788 | if (token.type == "string") { 789 | quotepos = -1; 790 | } else if (quotepos < 0) { 791 | quotepos = token.value.indexOf(quote); 792 | } 793 | if ((token.value.length + col) > selection.start.column) { 794 | break; 795 | } 796 | col += tokens[x].value.length; 797 | } 798 | 799 | // Try and be smart about when we auto insert. 800 | if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { 801 | return { 802 | text: quote + quote, 803 | selection: [1,1] 804 | }; 805 | } else if (token && token.type === "string") { 806 | // Ignore input and move right one if we're typing over the closing quote. 807 | var rightChar = line.substring(cursor.column, cursor.column + 1); 808 | if (rightChar == quote) { 809 | return { 810 | text: '', 811 | selection: [1, 1] 812 | }; 813 | } 814 | } 815 | } 816 | } 817 | }); 818 | 819 | this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { 820 | var selected = session.doc.getTextRange(range); 821 | if (!range.isMultiLine() && (selected == '"' || selected == "'")) { 822 | var line = session.doc.getLine(range.start.row); 823 | var rightChar = line.substring(range.start.column + 1, range.start.column + 2); 824 | if (rightChar == '"') { 825 | range.end.column++; 826 | return range; 827 | } 828 | } 829 | }); 830 | 831 | }; 832 | 833 | oop.inherits(CstyleBehaviour, Behaviour); 834 | 835 | exports.CstyleBehaviour = CstyleBehaviour; 836 | }); 837 | 838 | define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) { 839 | 840 | 841 | var oop = require("../../lib/oop"); 842 | var Range = require("../../range").Range; 843 | var BaseFoldMode = require("./fold_mode").FoldMode; 844 | 845 | var FoldMode = exports.FoldMode = function() {}; 846 | oop.inherits(FoldMode, BaseFoldMode); 847 | 848 | (function() { 849 | 850 | this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; 851 | this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; 852 | 853 | this.getFoldWidgetRange = function(session, foldStyle, row) { 854 | var line = session.getLine(row); 855 | var match = line.match(this.foldingStartMarker); 856 | if (match) { 857 | var i = match.index; 858 | 859 | if (match[1]) 860 | return this.openingBracketBlock(session, match[1], row, i); 861 | 862 | var range = session.getCommentFoldRange(row, i + match[0].length); 863 | range.end.column -= 2; 864 | return range; 865 | } 866 | 867 | if (foldStyle !== "markbeginend") 868 | return; 869 | 870 | var match = line.match(this.foldingStopMarker); 871 | if (match) { 872 | var i = match.index + match[0].length; 873 | 874 | if (match[2]) { 875 | var range = session.getCommentFoldRange(row, i); 876 | range.end.column -= 2; 877 | return range; 878 | } 879 | 880 | var end = {row: row, column: i}; 881 | var start = session.$findOpeningBracket(match[1], end); 882 | 883 | if (!start) 884 | return; 885 | 886 | start.column++; 887 | end.column--; 888 | 889 | return Range.fromPoints(start, end); 890 | } 891 | }; 892 | 893 | }).call(FoldMode.prototype); 894 | 895 | }); 896 | 897 | define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { 898 | 899 | 900 | var Range = require("../../range").Range; 901 | 902 | var FoldMode = exports.FoldMode = function() {}; 903 | 904 | (function() { 905 | 906 | this.foldingStartMarker = null; 907 | this.foldingStopMarker = null; 908 | 909 | // must return "" if there's no fold, to enable caching 910 | this.getFoldWidget = function(session, foldStyle, row) { 911 | var line = session.getLine(row); 912 | if (this.foldingStartMarker.test(line)) 913 | return "start"; 914 | if (foldStyle == "markbeginend" 915 | && this.foldingStopMarker 916 | && this.foldingStopMarker.test(line)) 917 | return "end"; 918 | return ""; 919 | }; 920 | 921 | this.getFoldWidgetRange = function(session, foldStyle, row) { 922 | return null; 923 | }; 924 | 925 | this.indentationBlock = function(session, row, column) { 926 | var re = /\S/; 927 | var line = session.getLine(row); 928 | var startLevel = line.search(re); 929 | if (startLevel == -1) 930 | return; 931 | 932 | var startColumn = column || line.length; 933 | var maxRow = session.getLength(); 934 | var startRow = row; 935 | var endRow = row; 936 | 937 | while (++row < maxRow) { 938 | var level = session.getLine(row).search(re); 939 | 940 | if (level == -1) 941 | continue; 942 | 943 | if (level <= startLevel) 944 | break; 945 | 946 | endRow = row; 947 | } 948 | 949 | if (endRow > startRow) { 950 | var endColumn = session.getLine(endRow).length; 951 | return new Range(startRow, startColumn, endRow, endColumn); 952 | } 953 | }; 954 | 955 | this.openingBracketBlock = function(session, bracket, row, column, typeRe) { 956 | var start = {row: row, column: column + 1}; 957 | var end = session.$findClosingBracket(bracket, start, typeRe); 958 | if (!end) 959 | return; 960 | 961 | var fw = session.foldWidgets[end.row]; 962 | if (fw == null) 963 | fw = this.getFoldWidget(session, end.row); 964 | 965 | if (fw == "start" && end.row > start.row) { 966 | end.row --; 967 | end.column = session.getLine(end.row).length; 968 | } 969 | return Range.fromPoints(start, end); 970 | }; 971 | 972 | }).call(FoldMode.prototype); 973 | 974 | }); 975 | -------------------------------------------------------------------------------- /javascripts/lib/ace/mode-typescript.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Distributed under the BSD license: 3 | * 4 | * Copyright (c) 2012, Ajax.org B.V. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Ajax.org B.V. nor the 15 | * names of its contributors may be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | * 30 | * Contributor(s): 31 | * 32 | * 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | define('ace/mode/typescript', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/typescript_highlight_rules', 'ace/worker/worker_client'], function(require, exports, module) { 37 | 38 | 39 | var oop = require("../lib/oop"); 40 | var TextMode = require("./text").Mode; 41 | var Tokenizer = require("../tokenizer").Tokenizer; 42 | var TypeScriptHighlightRules = require("./typescript_highlight_rules").TypeScriptHighlightRules; 43 | var WorkerClient = require("../worker/worker_client").WorkerClient; 44 | 45 | var Mode = function() { 46 | var highlighter = new TypeScriptHighlightRules(); 47 | 48 | this.$tokenizer = new Tokenizer(highlighter.getRules()); 49 | }; 50 | oop.inherits(Mode, TextMode); 51 | 52 | (function() { 53 | 54 | this.createWorker = function(session) { 55 | var worker = new WorkerClient(["ace"], "ace/mode/typescript_worker", "TypeScriptWorker"); 56 | worker.attachToDocument(session.getDocument()); 57 | 58 | worker.on("terminate", function() { 59 | session.clearAnnotations(); 60 | }); 61 | 62 | worker.on("compileErrors", function(results) { 63 | session.setAnnotations(results.data); 64 | session._emit("compileErrors", {data: results.data}); 65 | 66 | }); 67 | 68 | worker.on("compiled", function(result) { 69 | session._emit("compiled", {data: result.data}); 70 | }); 71 | 72 | return worker; 73 | }; 74 | }).call(Mode.prototype); 75 | 76 | exports.Mode = Mode; 77 | }); 78 | 79 | 80 | define('ace/mode/typescript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/javascript_highlight_rules'], function(require, exports, module) { 81 | 82 | 83 | var oop = require("../lib/oop"); 84 | var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; 85 | 86 | var TypeScriptHighlightRules = function() { 87 | 88 | var tsRules = [ 89 | { 90 | "token": ["keyword.operator.ts", "text", "variable.parameter.function.ts", "text"], 91 | "regex": "\\b(module)(\\s*)([a-zA-Z0-9_?.$][\\w?.$]*)(\\s*\\{)" 92 | }, 93 | { 94 | "token": ["storage.type.variable.ts", "text", "keyword.other.ts", "text"], 95 | "regex": "(super)(\\s*\\()([a-zA-Z0-9,_?.$\\s]+\\s*)(\\))" 96 | }, 97 | { 98 | "token": ["entity.name.function.ts","paren.lparen", "paren.rparen"], 99 | "regex": "([a-zA-Z_?.$][\\w?.$]*)(\\()(\\))" 100 | }, 101 | { 102 | "token": ["variable.parameter.function.ts", "text", "variable.parameter.function.ts"], 103 | "regex": "([a-zA-Z0-9_?.$][\\w?.$]*)(\\s*:\\s*)([a-zA-Z0-9_?.$][\\w?.$]*)" 104 | }, 105 | { 106 | "token": ["keyword.operator.ts"], 107 | "regex": "(?:\\b(constructor|declare|interface|as|AS|public|private|class|extends|export|super)\\b)" 108 | }, 109 | { 110 | "token": ["storage.type.variable.ts"], 111 | "regex": "(?:\\b(this\\.|string\\b|bool\\b|number)\\b)" 112 | }, 113 | { 114 | "token": ["keyword.operator.ts", "storage.type.variable.ts", "keyword.operator.ts", "storage.type.variable.ts"], 115 | "regex": "(class)(\\s+[a-zA-Z0-9_?.$][\\w?.$]*\\s+)(extends)(\\s+[a-zA-Z0-9_?.$][\\w?.$]*\\s+)?" 116 | }, 117 | { 118 | "token": "keyword", 119 | "regex": "(?:super|export|class|extends|import)\\b" 120 | } 121 | ]; 122 | 123 | var JSRules = new JavaScriptHighlightRules().getRules(); 124 | 125 | JSRules.start = tsRules.concat(JSRules.start); 126 | this.$rules = JSRules; 127 | }; 128 | 129 | oop.inherits(TypeScriptHighlightRules, JavaScriptHighlightRules); 130 | 131 | exports.TypeScriptHighlightRules = TypeScriptHighlightRules; 132 | }); 133 | 134 | define('ace/mode/javascript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules'], function(require, exports, module) { 135 | 136 | 137 | var oop = require("../lib/oop"); 138 | var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; 139 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; 140 | 141 | var JavaScriptHighlightRules = function() { 142 | var keywordMapper = this.createKeywordMapper({ 143 | "variable.language": 144 | "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors 145 | "Namespace|QName|XML|XMLList|" + // E4X 146 | "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + 147 | "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + 148 | "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors 149 | "SyntaxError|TypeError|URIError|" + 150 | "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions 151 | "isNaN|parseFloat|parseInt|" + 152 | "JSON|Math|" + // Other 153 | "this|arguments|prototype|window|document" , // Pseudo 154 | "keyword": 155 | "const|yield|import|get|set|" + 156 | "break|case|catch|continue|default|delete|do|else|finally|for|function|" + 157 | "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" + 158 | "__parent__|__count__|escape|unescape|with|__proto__|" + 159 | "class|enum|extends|super|export|implements|private|public|interface|package|protected|static", 160 | "storage.type": 161 | "const|let|var|function", 162 | "constant.language": 163 | "null|Infinity|NaN|undefined", 164 | "support.function": 165 | "alert" 166 | }, "identifier"); 167 | var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield"; 168 | var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; 169 | 170 | var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex 171 | "u[0-9a-fA-F]{4}|" + // unicode 172 | "[0-2][0-7]{0,2}|" + // oct 173 | "3[0-6][0-7]?|" + // oct 174 | "37[0-7]?|" + // oct 175 | "[4-7][0-7]?|" + //oct 176 | ".)"; 177 | 178 | this.$rules = { 179 | "start" : [ 180 | { 181 | token : "comment", 182 | regex : /\/\/.*$/ 183 | }, 184 | DocCommentHighlightRules.getStartRule("doc-start"), 185 | { 186 | token : "comment", // multi line comment 187 | merge : true, 188 | regex : /\/\*/, 189 | next : "comment" 190 | }, { 191 | token : "string", 192 | regex : "'(?=.)", 193 | next : "qstring" 194 | }, { 195 | token : "string", 196 | regex : '"(?=.)', 197 | next : "qqstring" 198 | }, { 199 | token : "constant.numeric", // hex 200 | regex : /0[xX][0-9a-fA-F]+\b/ 201 | }, { 202 | token : "constant.numeric", // float 203 | regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ 204 | }, { 205 | token : [ 206 | "storage.type", "punctuation.operator", "support.function", 207 | "punctuation.operator", "entity.name.function", "text","keyword.operator" 208 | ], 209 | regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", 210 | next: "function_arguments" 211 | }, { 212 | token : [ 213 | "storage.type", "punctuation.operator", "entity.name.function", "text", 214 | "keyword.operator", "text", "storage.type", "text", "paren.lparen" 215 | ], 216 | regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", 217 | next: "function_arguments" 218 | }, { 219 | token : [ 220 | "entity.name.function", "text", "keyword.operator", "text", "storage.type", 221 | "text", "paren.lparen" 222 | ], 223 | regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", 224 | next: "function_arguments" 225 | }, { 226 | token : [ 227 | "storage.type", "punctuation.operator", "entity.name.function", "text", 228 | "keyword.operator", "text", 229 | "storage.type", "text", "entity.name.function", "text", "paren.lparen" 230 | ], 231 | regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", 232 | next: "function_arguments" 233 | }, { 234 | token : [ 235 | "storage.type", "text", "entity.name.function", "text", "paren.lparen" 236 | ], 237 | regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", 238 | next: "function_arguments" 239 | }, { 240 | token : [ 241 | "entity.name.function", "text", "punctuation.operator", 242 | "text", "storage.type", "text", "paren.lparen" 243 | ], 244 | regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", 245 | next: "function_arguments" 246 | }, { 247 | token : [ 248 | "text", "text", "storage.type", "text", "paren.lparen" 249 | ], 250 | regex : "(:)(\\s*)(function)(\\s*)(\\()", 251 | next: "function_arguments" 252 | }, { 253 | token : "constant.language.boolean", 254 | regex : /(?:true|false)\b/ 255 | }, { 256 | token : "keyword", 257 | regex : "(?:" + kwBeforeRe + ")\\b", 258 | next : "regex_allowed" 259 | }, { 260 | token : ["punctuation.operator", "support.function"], 261 | regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ 262 | }, { 263 | token : ["punctuation.operator", "support.function.dom"], 264 | regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ 265 | }, { 266 | token : ["punctuation.operator", "support.constant"], 267 | regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ 268 | }, { 269 | token : ["storage.type", "punctuation.operator", "support.function.firebug"], 270 | regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/ 271 | }, { 272 | token : keywordMapper, 273 | regex : identifierRe 274 | }, { 275 | token : "keyword.operator", 276 | regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/, 277 | next : "regex_allowed" 278 | }, { 279 | token : "punctuation.operator", 280 | regex : /\?|\:|\,|\;|\./, 281 | next : "regex_allowed" 282 | }, { 283 | token : "paren.lparen", 284 | regex : /[\[({]/, 285 | next : "regex_allowed" 286 | }, { 287 | token : "paren.rparen", 288 | regex : /[\])}]/ 289 | }, { 290 | token : "keyword.operator", 291 | regex : /\/=?/, 292 | next : "regex_allowed" 293 | }, { 294 | token: "comment", 295 | regex: /^#!.*$/ 296 | }, { 297 | token : "text", 298 | regex : /\s+/ 299 | } 300 | ], 301 | "regex_allowed": [ 302 | DocCommentHighlightRules.getStartRule("doc-start"), 303 | { 304 | token : "comment", // multi line comment 305 | merge : true, 306 | regex : "\\/\\*", 307 | next : "comment_regex_allowed" 308 | }, { 309 | token : "comment", 310 | regex : "\\/\\/.*$" 311 | }, { 312 | token: "string.regexp", 313 | regex: "\\/", 314 | next: "regex", 315 | merge: true 316 | }, { 317 | token : "text", 318 | regex : "\\s+" 319 | }, { 320 | token: "empty", 321 | regex: "", 322 | next: "start" 323 | } 324 | ], 325 | "regex": [ 326 | { 327 | token: "regexp.keyword.operator", 328 | regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" 329 | }, { 330 | token: "string.regexp", 331 | regex: "/\\w*", 332 | next: "start", 333 | merge: true 334 | }, { 335 | token : "invalid", 336 | regex: /\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ 337 | }, { 338 | token : "constant.language.escape", 339 | regex: /\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/ 340 | }, { 341 | token: "string.regexp", 342 | regex: /{|[^{\[\/\\(|)$^+*?]+/, 343 | merge: true 344 | }, { 345 | token: "constant.language.escape", 346 | regex: /\[\^?/, 347 | next: "regex_character_class", 348 | merge: true 349 | }, { 350 | token: "empty", 351 | regex: "", 352 | next: "start" 353 | } 354 | ], 355 | "regex_character_class": [ 356 | { 357 | token: "regexp.keyword.operator", 358 | regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" 359 | }, { 360 | token: "constant.language.escape", 361 | regex: "]", 362 | next: "regex", 363 | merge: true 364 | }, { 365 | token: "constant.language.escape", 366 | regex: "-" 367 | }, { 368 | token: "string.regexp.charachterclass", 369 | regex: /[^\]\-\\]+/, 370 | merge: true 371 | }, { 372 | token: "empty", 373 | regex: "", 374 | next: "start" 375 | } 376 | ], 377 | "function_arguments": [ 378 | { 379 | token: "variable.parameter", 380 | regex: identifierRe 381 | }, { 382 | token: "punctuation.operator", 383 | regex: "[, ]+", 384 | merge: true 385 | }, { 386 | token: "punctuation.operator", 387 | regex: "$", 388 | merge: true 389 | }, { 390 | token: "empty", 391 | regex: "", 392 | next: "start" 393 | } 394 | ], 395 | "comment_regex_allowed" : [ 396 | { 397 | token : "comment", // closing comment 398 | regex : ".*?\\*\\/", 399 | merge : true, 400 | next : "regex_allowed" 401 | }, { 402 | token : "comment", // comment spanning whole line 403 | merge : true, 404 | regex : ".+" 405 | } 406 | ], 407 | "comment" : [ 408 | { 409 | token : "comment", // closing comment 410 | regex : ".*?\\*\\/", 411 | merge : true, 412 | next : "start" 413 | }, { 414 | token : "comment", // comment spanning whole line 415 | merge : true, 416 | regex : ".+" 417 | } 418 | ], 419 | "qqstring" : [ 420 | { 421 | token : "constant.language.escape", 422 | regex : escapedRe 423 | }, { 424 | token : "string", 425 | regex : '[^"\\\\]+', 426 | merge : true 427 | }, { 428 | token : "string", 429 | regex : "\\\\$", 430 | next : "qqstring", 431 | merge : true 432 | }, { 433 | token : "string", 434 | regex : '"|$', 435 | next : "start", 436 | merge : true 437 | } 438 | ], 439 | "qstring" : [ 440 | { 441 | token : "constant.language.escape", 442 | regex : escapedRe 443 | }, { 444 | token : "string", 445 | regex : "[^'\\\\]+", 446 | merge : true 447 | }, { 448 | token : "string", 449 | regex : "\\\\$", 450 | next : "qstring", 451 | merge : true 452 | }, { 453 | token : "string", 454 | regex : "'|$", 455 | next : "start", 456 | merge : true 457 | } 458 | ] 459 | }; 460 | 461 | this.embedRules(DocCommentHighlightRules, "doc-", 462 | [ DocCommentHighlightRules.getEndRule("start") ]); 463 | }; 464 | 465 | oop.inherits(JavaScriptHighlightRules, TextHighlightRules); 466 | 467 | exports.JavaScriptHighlightRules = JavaScriptHighlightRules; 468 | }); 469 | 470 | define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) { 471 | 472 | 473 | var oop = require("../lib/oop"); 474 | var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; 475 | 476 | var DocCommentHighlightRules = function() { 477 | 478 | this.$rules = { 479 | "start" : [ { 480 | token : "comment.doc.tag", 481 | regex : "@[\\w\\d_]+" // TODO: fix email addresses 482 | }, { 483 | token : "comment.doc", 484 | merge : true, 485 | regex : "\\s+" 486 | }, { 487 | token : "comment.doc", 488 | merge : true, 489 | regex : "TODO" 490 | }, { 491 | token : "comment.doc", 492 | merge : true, 493 | regex : "[^@\\*]+" 494 | }, { 495 | token : "comment.doc", 496 | merge : true, 497 | regex : "." 498 | }] 499 | }; 500 | }; 501 | 502 | oop.inherits(DocCommentHighlightRules, TextHighlightRules); 503 | 504 | DocCommentHighlightRules.getStartRule = function(start) { 505 | return { 506 | token : "comment.doc", // doc comment 507 | merge : true, 508 | regex : "\\/\\*(?=\\*)", 509 | next : start 510 | }; 511 | }; 512 | 513 | DocCommentHighlightRules.getEndRule = function (start) { 514 | return { 515 | token : "comment.doc", // closing comment 516 | merge : true, 517 | regex : "\\*\\/", 518 | next : start 519 | }; 520 | }; 521 | 522 | 523 | exports.DocCommentHighlightRules = DocCommentHighlightRules; 524 | 525 | }); 526 | -------------------------------------------------------------------------------- /javascripts/lib/ace/theme-monokai.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Distributed under the BSD license: 3 | * 4 | * Copyright (c) 2010, Ajax.org B.V. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Ajax.org B.V. nor the 15 | * names of its contributors may be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | * ***** END LICENSE BLOCK ***** */ 30 | 31 | define('ace/theme/monokai', ['require', 'exports', 'module', 'ace/lib/dom'], function(require, exports, module) { 32 | 33 | exports.isDark = true; 34 | exports.cssClass = "ace-monokai"; 35 | exports.cssText = ".ace-monokai .ace_gutter {\ 36 | background: #2f3129;\ 37 | color: #f1f1f1\ 38 | }\ 39 | \ 40 | .ace-monokai .ace_print-margin {\ 41 | width: 1px;\ 42 | background: #555651\ 43 | }\ 44 | \ 45 | .ace-monokai .ace_scroller {\ 46 | background-color: #272822\ 47 | }\ 48 | \ 49 | .ace-monokai .ace_text-layer {\ 50 | color: #F8F8F2\ 51 | }\ 52 | \ 53 | .ace-monokai .ace_cursor {\ 54 | border-left: 2px solid #F8F8F0\ 55 | }\ 56 | \ 57 | .ace-monokai .ace_cursor.ace_overwrite {\ 58 | border-left: 0px;\ 59 | border-bottom: 1px solid #F8F8F0\ 60 | }\ 61 | \ 62 | .ace-monokai .ace_marker-layer .ace_selection {\ 63 | background: #49483E\ 64 | }\ 65 | \ 66 | .ace-monokai.ace_multiselect .ace_selection.ace_start {\ 67 | box-shadow: 0 0 3px 0px #272822;\ 68 | border-radius: 2px\ 69 | }\ 70 | \ 71 | .ace-monokai .ace_marker-layer .ace_step {\ 72 | background: rgb(102, 82, 0)\ 73 | }\ 74 | \ 75 | .ace-monokai .ace_marker-layer .ace_bracket {\ 76 | margin: -1px 0 0 -1px;\ 77 | border: 1px solid #49483E\ 78 | }\ 79 | \ 80 | .ace-monokai .ace_marker-layer .ace_active-line {\ 81 | background: #202020\ 82 | }\ 83 | \ 84 | .ace-monokai .ace_gutter-active-line {\ 85 | background-color: #272727\ 86 | }\ 87 | \ 88 | .ace-monokai .ace_marker-layer .ace_selected-word {\ 89 | border: 1px solid #49483E\ 90 | }\ 91 | \ 92 | .ace-monokai .ace_invisible {\ 93 | color: #49483E\ 94 | }\ 95 | \ 96 | .ace-monokai .ace_entity.ace_name.ace_tag,\ 97 | .ace-monokai .ace_keyword,\ 98 | .ace-monokai .ace_meta,\ 99 | .ace-monokai .ace_storage {\ 100 | color: #F92672\ 101 | }\ 102 | \ 103 | .ace-monokai .ace_constant.ace_character,\ 104 | .ace-monokai .ace_constant.ace_language,\ 105 | .ace-monokai .ace_constant.ace_numeric,\ 106 | .ace-monokai .ace_constant.ace_other {\ 107 | color: #AE81FF\ 108 | }\ 109 | \ 110 | .ace-monokai .ace_invalid {\ 111 | color: #F8F8F0;\ 112 | background-color: #F92672\ 113 | }\ 114 | \ 115 | .ace-monokai .ace_invalid.ace_deprecated {\ 116 | color: #F8F8F0;\ 117 | background-color: #AE81FF\ 118 | }\ 119 | \ 120 | .ace-monokai .ace_support.ace_constant,\ 121 | .ace-monokai .ace_support.ace_function {\ 122 | color: #66D9EF\ 123 | }\ 124 | \ 125 | .ace-monokai .ace_fold {\ 126 | background-color: #A6E22E;\ 127 | border-color: #F8F8F2\ 128 | }\ 129 | \ 130 | .ace-monokai .ace_storage.ace_type,\ 131 | .ace-monokai .ace_support.ace_class,\ 132 | .ace-monokai .ace_support.ace_type {\ 133 | font-style: italic;\ 134 | color: #66D9EF\ 135 | }\ 136 | \ 137 | .ace-monokai .ace_entity.ace_name.ace_function,\ 138 | .ace-monokai .ace_entity.ace_other.ace_attribute-name,\ 139 | .ace-monokai .ace_variable {\ 140 | color: #A6E22E\ 141 | }\ 142 | \ 143 | .ace-monokai .ace_variable.ace_parameter {\ 144 | font-style: italic;\ 145 | color: #FD971F\ 146 | }\ 147 | \ 148 | .ace-monokai .ace_string {\ 149 | color: #E6DB74\ 150 | }\ 151 | \ 152 | .ace-monokai .ace_comment {\ 153 | color: #75715E\ 154 | }\ 155 | \ 156 | .ace-monokai .ace_markup.ace_underline {\ 157 | text-decoration: underline\ 158 | }\ 159 | \ 160 | .ace-monokai .ace_indent-guide {\ 161 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ11D6z7Bq1ar/ABCKBG6g04U2AAAAAElFTkSuQmCC) right repeat-y\ 162 | }"; 163 | 164 | var dom = require("../lib/dom"); 165 | dom.importCssString(exports.cssText, exports.cssClass); 166 | }); 167 | -------------------------------------------------------------------------------- /javascripts/lightHarness.js: -------------------------------------------------------------------------------- 1 | // parcial copy from typescript harness.js 2 | 3 | // Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. 4 | define('lightHarness', ['require', 'exports', 'module', 'ace/keyboard/hash_handler'], function(require, exports, module) { 5 | 6 | var __extends = this.__extends || function (d, b) { 7 | function __() { 8 | this.constructor = d; 9 | } 10 | __.prototype = b.prototype; 11 | d.prototype = new __(); 12 | }; 13 | 14 | var ScriptInfo = (function () { 15 | function ScriptInfo(name, content, isResident, maxScriptVersions) { 16 | this.name = name; 17 | this.content = content; 18 | this.isResident = isResident; 19 | this.maxScriptVersions = maxScriptVersions; 20 | this.editRanges = []; 21 | this.version = 1; 22 | } 23 | ScriptInfo.prototype.updateContent = function (content, isResident) { 24 | this.editRanges = []; 25 | this.content = content; 26 | this.isResident = isResident; 27 | this.version++; 28 | }; 29 | ScriptInfo.prototype.editContent = function (minChar, limChar, newText) { 30 | var prefix = this.content.substring(0, minChar); 31 | var middle = newText; 32 | var suffix = this.content.substring(limChar); 33 | this.content = prefix + middle + suffix; 34 | this.editRanges.push({ 35 | length: this.content.length, 36 | editRange: new TypeScript.ScriptEditRange(minChar, limChar, (limChar - minChar) + newText.length) 37 | }); 38 | if(this.editRanges.length > this.maxScriptVersions) { 39 | this.editRanges.splice(0, this.maxScriptVersions - this.editRanges.length); 40 | } 41 | this.version++; 42 | }; 43 | ScriptInfo.prototype.getEditRangeSinceVersion = function (version) { 44 | if(this.version == version) { 45 | return null; 46 | } 47 | var initialEditRangeIndex = this.editRanges.length - (this.version - version); 48 | if(initialEditRangeIndex < 0 || initialEditRangeIndex >= this.editRanges.length) { 49 | return TypeScript.ScriptEditRange.unknown(); 50 | } 51 | var entries = this.editRanges.slice(initialEditRangeIndex); 52 | var minDistFromStart = entries.map(function (x) { 53 | return x.editRange.minChar; 54 | }).reduce(function (prev, current) { 55 | return Math.min(prev, current); 56 | }); 57 | var minDistFromEnd = entries.map(function (x) { 58 | return x.length - x.editRange.limChar; 59 | }).reduce(function (prev, current) { 60 | return Math.min(prev, current); 61 | }); 62 | var aggDelta = entries.map(function (x) { 63 | return x.editRange.delta; 64 | }).reduce(function (prev, current) { 65 | return prev + current; 66 | }); 67 | return new TypeScript.ScriptEditRange(minDistFromStart, entries[0].length - minDistFromEnd, aggDelta); 68 | }; 69 | return ScriptInfo; 70 | })(); 71 | exports.ScriptInfo = ScriptInfo; 72 | var TypeScriptLS = (function () { 73 | function TypeScriptLS() { 74 | this.ls = null; 75 | this.scripts = []; 76 | this.maxScriptVersions = 100; 77 | } 78 | TypeScriptLS.prototype.addDefaultLibrary = function () { 79 | this.addScript("lib.d.ts", Harness.Compiler.libText, true); 80 | }; 81 | TypeScriptLS.prototype.addFile = function (name, isResident) { 82 | if (typeof isResident === "undefined") { isResident = false; } 83 | var code = Harness.CollateralReader.read(name); 84 | this.addScript(name, code, isResident); 85 | }; 86 | TypeScriptLS.prototype.addScript = function (name, content, isResident) { 87 | if (typeof isResident === "undefined") { isResident = false; } 88 | var script = new ScriptInfo(name, content, isResident, this.maxScriptVersions); 89 | this.scripts.push(script); 90 | }; 91 | TypeScriptLS.prototype.updateScript = function (name, content, isResident) { 92 | if (typeof isResident === "undefined") { isResident = false; } 93 | for(var i = 0; i < this.scripts.length; i++) { 94 | if(this.scripts[i].name == name) { 95 | this.scripts[i].updateContent(content, isResident); 96 | return; 97 | } 98 | } 99 | this.addScript(name, content, isResident); 100 | }; 101 | TypeScriptLS.prototype.editScript = function (name, minChar, limChar, newText) { 102 | for(var i = 0; i < this.scripts.length; i++) { 103 | if(this.scripts[i].name == name) { 104 | this.scripts[i].editContent(minChar, limChar, newText); 105 | return; 106 | } 107 | } 108 | throw new Error("No script with name '" + name + "'"); 109 | }; 110 | TypeScriptLS.prototype.getScriptContent = function (scriptIndex) { 111 | return this.scripts[scriptIndex].content; 112 | }; 113 | TypeScriptLS.prototype.information = function () { 114 | return true; 115 | }; 116 | TypeScriptLS.prototype.debug = function () { 117 | return true; 118 | }; 119 | TypeScriptLS.prototype.warning = function () { 120 | return true; 121 | }; 122 | TypeScriptLS.prototype.error = function () { 123 | return true; 124 | }; 125 | TypeScriptLS.prototype.fatal = function () { 126 | return true; 127 | }; 128 | TypeScriptLS.prototype.log = function (s) { 129 | // console.log("TypeScriptLS:" + s); 130 | }; 131 | TypeScriptLS.prototype.getCompilationSettings = function () { 132 | return ""; 133 | }; 134 | TypeScriptLS.prototype.getScriptCount = function () { 135 | return this.scripts.length; 136 | }; 137 | TypeScriptLS.prototype.getScriptSourceText = function (scriptIndex, start, end) { 138 | return this.scripts[scriptIndex].content.substring(start, end); 139 | }; 140 | TypeScriptLS.prototype.getScriptSourceLength = function (scriptIndex) { 141 | return this.scripts[scriptIndex].content.length; 142 | }; 143 | TypeScriptLS.prototype.getScriptId = function (scriptIndex) { 144 | return this.scripts[scriptIndex].name; 145 | }; 146 | TypeScriptLS.prototype.getScriptIsResident = function (scriptIndex) { 147 | return this.scripts[scriptIndex].isResident; 148 | }; 149 | TypeScriptLS.prototype.getScriptVersion = function (scriptIndex) { 150 | return this.scripts[scriptIndex].version; 151 | }; 152 | TypeScriptLS.prototype.getScriptEditRangeSinceVersion = function (scriptIndex, scriptVersion) { 153 | var range = this.scripts[scriptIndex].getEditRangeSinceVersion(scriptVersion); 154 | return (range.minChar + "," + range.limChar + "," + range.delta); 155 | }; 156 | TypeScriptLS.prototype.getLanguageService = function () { 157 | var ls = new Services.TypeScriptServicesFactory().createLanguageServiceShim(this); 158 | ls.refresh(true); 159 | this.ls = ls; 160 | return ls; 161 | }; 162 | TypeScriptLS.prototype.parseSourceText = function (fileName, sourceText) { 163 | var parser = new TypeScript.Parser(); 164 | parser.setErrorRecovery(null, -1, -1); 165 | parser.errorCallback = function (a, b, c, d) { 166 | }; 167 | var script = parser.parse(sourceText, fileName, 0); 168 | return script; 169 | }; 170 | TypeScriptLS.prototype.parseFile = function (fileName) { 171 | var sourceText = new TypeScript.StringSourceText(IO.readFile(fileName)); 172 | return this.parseSourceText(fileName, sourceText); 173 | }; 174 | TypeScriptLS.prototype.lineColToPosition = function (fileName, line, col) { 175 | var script = this.ls.languageService.getScriptAST(fileName); 176 | assert.notNull(script); 177 | assert(line >= 1); 178 | assert(col >= 1); 179 | assert(line < script.locationInfo.lineMap.length); 180 | return TypeScript.getPositionFromLineColumn(script, line, col); 181 | }; 182 | TypeScriptLS.prototype.positionToLineCol = function (fileName, position) { 183 | var script = this.ls.languageService.getScriptAST(fileName); 184 | assert.notNull(script); 185 | var result = TypeScript.getLineColumnFromPosition(script, position); 186 | assert(result.line >= 1); 187 | assert(result.col >= 1); 188 | return result; 189 | }; 190 | TypeScriptLS.prototype.checkEdits = function (sourceFileName, baselineFileName, edits) { 191 | var script = Harness.CollateralReader.read(sourceFileName); 192 | var formattedScript = this.applyEdits(script, edits); 193 | var baseline = Harness.CollateralReader.read(baselineFileName); 194 | assert.noDiff(formattedScript, baseline); 195 | assert.equal(formattedScript, baseline); 196 | }; 197 | TypeScriptLS.prototype.applyEdits = function (content, edits) { 198 | var result = content; 199 | edits = this.normalizeEdits(edits); 200 | for(var i = edits.length - 1; i >= 0; i--) { 201 | var edit = edits[i]; 202 | var prefix = result.substring(0, edit.minChar); 203 | var middle = edit.text; 204 | var suffix = result.substring(edit.limChar); 205 | result = prefix + middle + suffix; 206 | } 207 | return result; 208 | }; 209 | TypeScriptLS.prototype.normalizeEdits = function (edits) { 210 | var result = []; 211 | function mapEdits(edits) { 212 | var result = []; 213 | for(var i = 0; i < edits.length; i++) { 214 | result.push({ 215 | edit: edits[i], 216 | index: i 217 | }); 218 | } 219 | return result; 220 | } 221 | var temp = mapEdits(edits).sort(function (a, b) { 222 | var result = a.edit.minChar - b.edit.minChar; 223 | if(result == 0) { 224 | result = a.index - b.index; 225 | } 226 | return result; 227 | }); 228 | var current = 0; 229 | var next = 1; 230 | while(current < temp.length) { 231 | var currentEdit = temp[current].edit; 232 | if(next >= temp.length) { 233 | result.push(currentEdit); 234 | current++; 235 | continue; 236 | } 237 | var nextEdit = temp[next].edit; 238 | var gap = nextEdit.minChar - currentEdit.limChar; 239 | if(gap >= 0) { 240 | result.push(currentEdit); 241 | current = next; 242 | next++; 243 | continue; 244 | } 245 | if(currentEdit.limChar >= nextEdit.limChar) { 246 | next++; 247 | continue; 248 | } else { 249 | throw new Error("Trying to apply overlapping edits"); 250 | } 251 | } 252 | return result; 253 | }; 254 | return TypeScriptLS; 255 | })(); 256 | exports.TypeScriptLS = TypeScriptLS; 257 | 258 | }); -------------------------------------------------------------------------------- /javascripts/main.js: -------------------------------------------------------------------------------- 1 | var AceRange = require('ace/range').Range; 2 | var AutoComplete = require('autocomplete').AutoComplete; 3 | var lang = require("ace/lib/lang"); 4 | var EditorPosition = require('EditorPosition').EditorPosition; 5 | var CompilationService = require('CompilationService').CompilationService; 6 | var FileService = require('FileService').FileService; 7 | var deferredCall = require("ace/lib/lang").deferredCall; 8 | 9 | var Services = require('typescriptServices').Services; 10 | var TypeScript = require('typescriptServices').TypeScript; 11 | var TypeScriptLS = require('lightHarness').TypeScriptLS; 12 | 13 | var aceEditorPosition = null; 14 | var appFileService = null; 15 | var editor = null; 16 | var outputEditor = null; 17 | var typeCompilationService = null; 18 | var docUpdateCount = 0; 19 | var typeScriptLS = new TypeScriptLS(); 20 | var ServicesFactory = new Services.TypeScriptServicesFactory(); 21 | var serviceShim = ServicesFactory.createLanguageServiceShim(typeScriptLS); 22 | 23 | var selectFileName = ""; 24 | 25 | var syncStop = false; //for stop sync on loadfile 26 | var autoComplete = null; 27 | var refMarkers = []; 28 | var errorMarkers =[]; 29 | 30 | function loadTypeScriptLibrary(){ 31 | var libnames = [ 32 | "typescripts/lib.d.ts" 33 | ]; 34 | 35 | libnames.forEach(function(libname){ 36 | appFileService.readFile(libname, function(content){ 37 | typeScriptLS.addScript(libname, content.replace(/\r\n?/g,"\n"), true); 38 | }); 39 | }); 40 | } 41 | 42 | function loadFile(filename) { 43 | appFileService.readFile(filename, function(content){ 44 | selectFileName = filename; 45 | syncStop = true; 46 | var data= content.replace(/\r\n?/g,"\n"); 47 | editor.setValue(data); 48 | editor.moveCursorTo(0, 0); 49 | typeScriptLS.updateScript(filename, editor.getSession().getDocument().getValue() , false); 50 | syncStop = false; 51 | }); 52 | } 53 | 54 | function startAutoComplete(editor){ 55 | if (autoComplete.isActive() == false){ 56 | autoComplete.setScriptName(selectFileName); 57 | autoComplete.active(); 58 | } 59 | } 60 | 61 | function onUpdateDocument(e){ 62 | if (selectFileName){ 63 | if (!syncStop){ 64 | try{ 65 | syncTypeScriptServiceContent(selectFileName, e); 66 | updateMarker(e); 67 | }catch(ex){ 68 | 69 | } 70 | } 71 | } 72 | } 73 | 74 | // TODO check column 75 | function updateMarker(aceChangeEvent){ 76 | var data = aceChangeEvent.data; 77 | var action = data.action; 78 | var range = data.range; 79 | var markers = editor.getSession().getMarkers(true); 80 | var line_count = 0; 81 | var isNewLine = editor.getSession().getDocument().isNewLine; 82 | 83 | if(action == "insertText"){ 84 | if(isNewLine(data.text)){ 85 | line_count = 1; 86 | } 87 | }else if(action == "insertLines"){ 88 | line_count = data.lines.length; 89 | 90 | }else if (action == "removeText") { 91 | if(isNewLine(data.text)){ 92 | line_count = -1; 93 | } 94 | 95 | }else if (action == "removeLines"){ 96 | line_count = -data.lines.length; 97 | } 98 | 99 | if(line_count != 0){ 100 | 101 | var markerUpdate = function(id){ 102 | var marker = markers[id]; 103 | var row = range.start.row; 104 | 105 | if(line_count > 0){ 106 | row = +1; 107 | } 108 | 109 | if(marker && marker.range.start.row > row ){ 110 | marker.range.start.row += line_count ; 111 | marker.range.end.row += line_count ; 112 | } 113 | }; 114 | 115 | errorMarkers.forEach(markerUpdate); 116 | refMarkers.forEach(markerUpdate); 117 | editor.onChangeFrontMarker(); 118 | } 119 | 120 | } 121 | 122 | //sync LanguageService content and ace editor content 123 | function syncTypeScriptServiceContent(script, aceChangeEvent){ 124 | 125 | var data = aceChangeEvent.data; 126 | var action = data.action; 127 | var range = data.range; 128 | var start = aceEditorPosition.getPositionChars(range.start); 129 | 130 | if(action == "insertText"){ 131 | editLanguageService(script, new Services.TextEdit(start , start, data.text)); 132 | }else if(action == "insertLines"){ 133 | 134 | var text = data.lines.map(function(line) { 135 | return line+ '\n'; //TODO newline hard code 136 | }).join(''); 137 | editLanguageService(script,new Services.TextEdit(start , start, text)); 138 | 139 | }else if (action == "removeText") { 140 | var end = start + data.text.length; 141 | editLanguageService(script, new Services.TextEdit(start, end, "")); 142 | }else if (action == "removeLines"){ 143 | var len = aceEditorPosition.getLinesChars(data.lines); 144 | var end = start + len; 145 | editLanguageService(script, new Services.TextEdit(start, end, "")); 146 | } 147 | }; 148 | 149 | 150 | function editLanguageService(name, textEdit){ 151 | typeScriptLS.editScript(name, textEdit.minChar, textEdit.limChar, textEdit.text); 152 | } 153 | 154 | function onChangeCursor(e){ 155 | if(!syncStop){ 156 | try{ 157 | deferredShowOccurrences.schedule(200); 158 | }catch (ex){ 159 | //TODO 160 | } 161 | } 162 | }; 163 | 164 | function languageServiceIndent(){ 165 | var cursor = editor.getCursorPosition(); 166 | var lineNumber = cursor.row; 167 | 168 | var text = editor.session.getLine(lineNumber); 169 | var matches = text.match(/^[\t ]*/); 170 | var preIndent = 0; 171 | var wordLen = 0; 172 | 173 | if(matches){ 174 | wordLen = matches[0].length; 175 | for(var i = 0; i < matches[0].length; i++){ 176 | var elm = matches[0].charAt(i); 177 | var spaceLen = (elm == " ") ? 1: editor.session.getTabSize(); 178 | preIndent += spaceLen; 179 | }; 180 | } 181 | 182 | var option = new Services.EditorOptions(); 183 | option.NewLineCharacter = "\n"; 184 | 185 | var smartIndent = serviceShim.languageService.getSmartIndentAtLineNumber(selectFileName, lineNumber, option); 186 | 187 | if(preIndent > smartIndent){ 188 | editor.indent(); 189 | }else{ 190 | var indent = smartIndent - preIndent; 191 | 192 | if(indent > 0){ 193 | editor.getSelection().moveCursorLineStart(); 194 | editor.commands.exec("inserttext", editor, {text:" ", times:indent}); 195 | } 196 | 197 | if( cursor.column > wordLen){ 198 | cursor.column += indent; 199 | }else{ 200 | cursor.column = indent + wordLen; 201 | } 202 | 203 | editor.getSelection().moveCursorToPosition(cursor); 204 | } 205 | } 206 | 207 | function refactor(){ 208 | var references = serviceShim.languageService.getOccurrencesAtPosition(selectFileName, aceEditorPosition.getCurrentCharPosition()); 209 | 210 | references.forEach(function(ref){ 211 | var getpos = aceEditorPosition.getAcePositionFromChars; 212 | var start = getpos(ref.ast.minChar); 213 | var end = getpos(ref.ast.limChar); 214 | var range = new AceRange(start.row, start.column, end.row, end.column); 215 | editor.session.multiSelect.addRange(range); 216 | }); 217 | } 218 | 219 | function showOccurrences(){ 220 | var references = serviceShim.languageService.getOccurrencesAtPosition(selectFileName, aceEditorPosition.getCurrentCharPosition()); 221 | var session = editor.getSession(); 222 | refMarkers.forEach(function (id){ 223 | session.removeMarker(id); 224 | }); 225 | references.forEach(function(ref){ 226 | //TODO check script name 227 | // console.log(ref.unitIndex); 228 | var getpos = aceEditorPosition.getAcePositionFromChars; 229 | var start = getpos(ref.ast.minChar); 230 | var end = getpos(ref.ast.limChar); 231 | var range = new AceRange(start.row, start.column, end.row, end.column); 232 | refMarkers.push(session.addMarker(range, "typescript-ref", "text", true)); 233 | }); 234 | } 235 | 236 | var deferredShowOccurrences = deferredCall(showOccurrences); 237 | 238 | function Compile(typeScriptContent){ 239 | var output = ""; 240 | 241 | var outfile = { 242 | Write: function (s) { 243 | output += s; 244 | }, 245 | WriteLine: function (s) { 246 | output += s + "\n"; 247 | }, 248 | Close: function () { 249 | } 250 | }; 251 | 252 | var outerr = { 253 | Write: function (s) { 254 | }, 255 | WriteLine: function (s) { 256 | }, 257 | Close: function () { 258 | } 259 | }; 260 | var compiler = new TypeScript.TypeScriptCompiler(outfile, outerr, new TypeScript.NullLogger(), new TypeScript.CompilationSettings()); 261 | compiler.addUnit(typeScriptContent, "output.js", false); 262 | compiler.typeCheck(); 263 | compiler.emit(false, function (name) { 264 | 265 | }); 266 | return output; 267 | } 268 | 269 | function workerOnCreate(func, timeout){ 270 | if(editor.getSession().$worker){ 271 | func(editor.getSession().$worker); 272 | }else{ 273 | setTimeout(function(){ 274 | workerOnCreate(func, timeout); 275 | }); 276 | } 277 | } 278 | 279 | function javascriptRun(){ 280 | var external = window.open(); 281 | var script = external.window.document.createElement("script"); 282 | script.textContent = outputEditor.getSession().doc.getValue(); 283 | external.window.document.body.appendChild(script); 284 | } 285 | 286 | $(function(){ 287 | appFileService = new FileService($); 288 | editor = ace.edit("editor"); 289 | editor.setTheme("ace/theme/monokai"); 290 | editor.getSession().setMode('ace/mode/typescript'); 291 | 292 | outputEditor = ace.edit("output"); 293 | outputEditor.setTheme("ace/theme/monokai"); 294 | outputEditor.getSession().setMode('ace/mode/javascript'); 295 | document.getElementById('editor').style.fontSize='14px'; 296 | document.getElementById('output').style.fontSize='14px'; 297 | 298 | loadTypeScriptLibrary(); 299 | loadFile("samples/greeter.ts"); 300 | 301 | editor.addEventListener("change", onUpdateDocument); 302 | editor.addEventListener("changeSelection", onChangeCursor); 303 | 304 | editor.commands.addCommands([{ 305 | name:"autoComplete", 306 | bindKey:"Ctrl-Space", 307 | exec:function(editor) { 308 | startAutoComplete(editor); 309 | } 310 | }]); 311 | 312 | editor.commands.addCommands([{ 313 | name:"refactor", 314 | bindKey: "F2", 315 | exec:function(editor) { 316 | refactor(); 317 | } 318 | }]); 319 | 320 | editor.commands.addCommands([{ 321 | name: "indent", 322 | bindKey: "Tab", 323 | exec: function(editor) { 324 | languageServiceIndent(); 325 | }, 326 | multiSelectAction: "forEach" 327 | }]); 328 | 329 | aceEditorPosition = new EditorPosition(editor); 330 | typeCompilationService = new CompilationService(editor, serviceShim); 331 | autoComplete = new AutoComplete(editor, selectFileName, typeCompilationService); 332 | 333 | // override editor onTextInput 334 | var originalTextInput = editor.onTextInput; 335 | editor.onTextInput = function (text){ 336 | originalTextInput.call(editor, text); 337 | if(text == "."){ 338 | editor.commands.exec("autoComplete"); 339 | 340 | }else if (editor.getSession().getDocument().isNewLine(text)) { 341 | var lineNumber = editor.getCursorPosition().row; 342 | var option = new Services.EditorOptions(); 343 | option.NewLineCharacter = "\n"; 344 | var indent = serviceShim.languageService.getSmartIndentAtLineNumber(selectFileName, lineNumber, option); 345 | if(indent > 0) { 346 | editor.commands.exec("inserttext", editor, {text:" ", times:indent}); 347 | } 348 | } 349 | }; 350 | 351 | editor.addEventListener("mousedown", function(e){ 352 | if(autoComplete.isActive()){ 353 | autoComplete.deactivate(); 354 | } 355 | }); 356 | 357 | editor.getSession().on("compiled", function(e){ 358 | outputEditor.getSession().doc.setValue(e.data); 359 | }); 360 | 361 | editor.getSession().on("compileErrors", function(e){ 362 | var session = editor.getSession(); 363 | errorMarkers.forEach(function (id){ 364 | session.removeMarker(id); 365 | }); 366 | e.data.forEach(function(error){ 367 | var getpos = aceEditorPosition.getAcePositionFromChars; 368 | var start = getpos(error.minChar); 369 | var end = getpos(error.limChar); 370 | var range = new AceRange(start.row, start.column, end.row, end.column); 371 | errorMarkers.push(session.addMarker(range, "typescript-error", "text", true)); 372 | }); 373 | }); 374 | 375 | workerOnCreate(function(){//TODO use worker init event 376 | 377 | ["typescripts/lib.d.ts"].forEach(function(libname){ 378 | appFileService.readFile(libname, function(content){ 379 | var params = { 380 | data: { 381 | name:libname, 382 | content:content.replace(/\r\n?/g,"\n") 383 | } 384 | }; 385 | editor.getSession().$worker.emit("addLibrary", params ); 386 | }); 387 | }); 388 | }, 100); 389 | 390 | $("#javascript-run").click(function(e){ 391 | javascriptRun(); 392 | }); 393 | 394 | $("#select-sample").change(function(e){ 395 | var path = "samples/" + $(this).val(); 396 | loadFile(path); 397 | }); 398 | 399 | }); 400 | 401 | 402 | 403 | -------------------------------------------------------------------------------- /samples/animal.ts: -------------------------------------------------------------------------------- 1 | class Animal { 2 | constructor(public name) { } 3 | move(meters) { 4 | alert(this.name + " moved " + meters + "m."); 5 | } 6 | } 7 | 8 | class Snake extends Animal { 9 | constructor(name) { super(name); } 10 | move() { 11 | alert("Slithering..."); 12 | super.move(5); 13 | } 14 | } 15 | 16 | class Horse extends Animal { 17 | constructor(name) { super(name); } 18 | move() { 19 | alert("Galloping..."); 20 | super.move(45); 21 | } 22 | } 23 | 24 | var sam = new Snake("Sammy the Python") 25 | var tom: Animal = new Horse("Tommy the Palomino") 26 | 27 | sam.move() 28 | tom.move(34) -------------------------------------------------------------------------------- /samples/greeter.ts: -------------------------------------------------------------------------------- 1 | 2 | class Greeter { 3 | greeting: string; 4 | constructor (message: string) { 5 | this.greeting = message; 6 | } 7 | greet() { 8 | return "Hello, " + this.greeting; 9 | } 10 | } 11 | 12 | var greeter = new Greeter("world"); 13 | 14 | var button = document.createElement('button') 15 | button.innerText = "Say Hello" 16 | button.onclick = function() { 17 | alert(greeter.greet()) 18 | } 19 | 20 | document.body.appendChild(button) 21 | -------------------------------------------------------------------------------- /samples/raytracer.ts: -------------------------------------------------------------------------------- 1 | 2 | class Vector { 3 | constructor(public x: number, 4 | public y: number, 5 | public z: number) { 6 | } 7 | static times(k: number, v: Vector) { return new Vector(k * v.x, k * v.y, k * v.z); } 8 | static minus(v1: Vector, v2: Vector) { return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); } 9 | static plus(v1: Vector, v2: Vector) { return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } 10 | static dot(v1: Vector, v2: Vector) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } 11 | static mag(v: Vector) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } 12 | static norm(v: Vector) { 13 | var mag = Vector.mag(v); 14 | var div = (mag === 0) ? Infinity : 1.0 / mag; 15 | return Vector.times(div, v); 16 | } 17 | static cross(v1: Vector, v2: Vector) { 18 | return new Vector(v1.y * v2.z - v1.z * v2.y, 19 | v1.z * v2.x - v1.x * v2.z, 20 | v1.x * v2.y - v1.y * v2.x); 21 | } 22 | } 23 | 24 | class Color { 25 | constructor(public r: number, 26 | public g: number, 27 | public b: number) { 28 | } 29 | static scale(k: number, v: Color) { return new Color(k * v.r, k * v.g, k * v.b); } 30 | static plus(v1: Color, v2: Color) { return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); } 31 | static times(v1: Color, v2: Color) { return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); } 32 | static white = new Color(1.0, 1.0, 1.0); 33 | static grey = new Color(0.5, 0.5, 0.5); 34 | static black = new Color(0.0, 0.0, 0.0); 35 | static background = Color.black; 36 | static defaultColor = Color.black; 37 | static toDrawingColor(c: Color) { 38 | var legalize = d => d > 1 ? 1 : d; 39 | return { 40 | r: Math.floor(legalize(c.r) * 255), 41 | g: Math.floor(legalize(c.g) * 255), 42 | b: Math.floor(legalize(c.b) * 255) 43 | } 44 | } 45 | } 46 | 47 | class Camera { 48 | public forward: Vector; 49 | public right: Vector; 50 | public up: Vector; 51 | 52 | constructor(public pos: Vector, lookAt: Vector) { 53 | var down = new Vector(0.0, -1.0, 0.0); 54 | this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); 55 | this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); 56 | this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); 57 | } 58 | } 59 | 60 | interface Ray { 61 | start: Vector; 62 | dir: Vector; 63 | } 64 | 65 | interface Intersection { 66 | thing: Thing; 67 | ray: Ray; 68 | dist: number; 69 | } 70 | 71 | interface Surface { 72 | diffuse: (pos: Vector) => Color; 73 | specular: (pos: Vector) => Color; 74 | reflect: (pos: Vector) => number; 75 | roughness: number; 76 | } 77 | 78 | interface Thing { 79 | intersect: (ray: Ray) => Intersection; 80 | normal: (pos: Vector) => Vector; 81 | surface: Surface; 82 | } 83 | 84 | interface Light { 85 | pos: Vector; 86 | color: Color; 87 | } 88 | 89 | interface Scene { 90 | things: Thing[]; 91 | lights: Light[]; 92 | camera: Camera; 93 | } 94 | 95 | class Sphere implements Thing { 96 | public radius2: number; 97 | 98 | constructor(public center: Vector, radius: number, public surface: Surface) { 99 | this.radius2 = radius * radius; 100 | } 101 | normal(pos: Vector): Vector { return Vector.norm(Vector.minus(pos, this.center)); }; 102 | intersect(ray: Ray) { 103 | var eo = Vector.minus(this.center, ray.start); 104 | var v = Vector.dot(eo, ray.dir); 105 | var dist = 0; 106 | if (v >= 0) { 107 | var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); 108 | if (disc >= 0) { 109 | dist = v - Math.sqrt(disc); 110 | } 111 | } 112 | if (dist === 0) { 113 | return null; 114 | } else { 115 | return { thing: this, ray: ray, dist: dist }; 116 | } 117 | } 118 | } 119 | 120 | class Plane implements Thing { 121 | public normal: (pos: Vector) =>Vector; 122 | public intersect: (ray: Ray) =>Intersection; 123 | constructor(norm: Vector, offset: number, public surface: Surface) { 124 | this.normal = function(pos: Vector) { return norm; } 125 | this.intersect = function(ray: Ray): Intersection { 126 | var denom = Vector.dot(norm, ray.dir); 127 | if (denom > 0) { 128 | return null; 129 | } else { 130 | var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); 131 | return { thing: this, ray: ray, dist: dist }; 132 | } 133 | } 134 | } 135 | } 136 | 137 | module Surfaces { 138 | export var shiny: Surface = { 139 | diffuse: function(pos) { return Color.white; }, 140 | specular: function(pos) { return Color.grey; }, 141 | reflect: function(pos) { return 0.7; }, 142 | roughness: 250 143 | } 144 | export var checkerboard: Surface = { 145 | diffuse: function(pos) { 146 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 147 | return Color.white; 148 | } else { 149 | return Color.black; 150 | } 151 | }, 152 | specular: function(pos) { return Color.white; }, 153 | reflect: function(pos) { 154 | if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { 155 | return 0.1; 156 | } else { 157 | return 0.7; 158 | } 159 | }, 160 | roughness: 150 161 | } 162 | } 163 | 164 | 165 | class RayTracer { 166 | private maxDepth = 5; 167 | 168 | private intersections(ray: Ray, scene: Scene) { 169 | var closest = +Infinity; 170 | var closestInter: Intersection = undefined; 171 | for (var i in scene.things) { 172 | var inter = scene.things[i].intersect(ray); 173 | if (inter != null && inter.dist < closest) { 174 | closestInter = inter; 175 | closest = inter.dist; 176 | } 177 | } 178 | return closestInter; 179 | } 180 | 181 | private testRay(ray: Ray, scene: Scene) { 182 | var isect = this.intersections(ray, scene); 183 | if (isect != null) { 184 | return isect.dist; 185 | } else { 186 | return undefined; 187 | } 188 | } 189 | 190 | private traceRay(ray: Ray, scene: Scene, depth: number): Color { 191 | var isect = this.intersections(ray, scene); 192 | if (isect === undefined) { 193 | return Color.background; 194 | } else { 195 | return this.shade(isect, scene, depth); 196 | } 197 | } 198 | 199 | private shade(isect: Intersection, scene: Scene, depth: number) { 200 | var d = isect.ray.dir; 201 | var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); 202 | var normal = isect.thing.normal(pos); 203 | var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); 204 | var naturalColor = Color.plus(Color.background, 205 | this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); 206 | var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); 207 | return Color.plus(naturalColor, reflectedColor); 208 | } 209 | 210 | private getReflectionColor(thing: Thing, pos: Vector, normal: Vector, rd: Vector, scene: Scene, depth: number) { 211 | return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); 212 | } 213 | 214 | private getNaturalColor(thing: Thing, pos: Vector, norm: Vector, rd: Vector, scene: Scene) { 215 | var addLight = (col, light) => { 216 | var ldis = Vector.minus(light.pos, pos); 217 | var livec = Vector.norm(ldis); 218 | var neatIsect = this.testRay({ start: pos, dir: livec }, scene); 219 | var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); 220 | if (isInShadow) { 221 | return col; 222 | } else { 223 | var illum = Vector.dot(livec, norm); 224 | var lcolor = (illum > 0) ? Color.scale(illum, light.color) 225 | : Color.defaultColor; 226 | var specular = Vector.dot(livec, Vector.norm(rd)); 227 | var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) 228 | : Color.defaultColor; 229 | return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), 230 | Color.times(thing.surface.specular(pos), scolor))); 231 | } 232 | } 233 | return scene.lights.reduce(addLight, Color.defaultColor); 234 | } 235 | 236 | render(scene, ctx, screenWidth, screenHeight) { 237 | var getPoint = (x, y, camera) => { 238 | var recenterX = x =>(x - (screenWidth / 2.0)) / 2.0 / screenWidth; 239 | var recenterY = y => - (y - (screenHeight / 2.0)) / 2.0 / screenHeight; 240 | return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); 241 | } 242 | for (var y = 0; y < screenHeight; y++) { 243 | for (var x = 0; x < screenWidth; x++) { 244 | var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); 245 | var c = Color.toDrawingColor(color); 246 | ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; 247 | ctx.fillRect(x, y, x + 1, y + 1); 248 | } 249 | } 250 | } 251 | } 252 | 253 | 254 | function defaultScene(): Scene { 255 | return { 256 | things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), 257 | new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), 258 | new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)], 259 | lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, 260 | { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, 261 | { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, 262 | { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], 263 | camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) 264 | }; 265 | } 266 | 267 | function exec() { 268 | var canv = document.createElement("canvas"); 269 | canv.width = 256; 270 | canv.height = 256; 271 | document.body.appendChild(canv); 272 | var ctx = canv.getContext("2d"); 273 | var rayTracer = new RayTracer(); 274 | return rayTracer.render(defaultScene(), ctx, 256, 256); 275 | } 276 | 277 | exec(); 278 | -------------------------------------------------------------------------------- /src/coffee/autoCompleteView.coffee: -------------------------------------------------------------------------------- 1 | define('AutoCompleteView', ['require', 'exports', 'module'], (require, exports, module) -> 2 | 3 | selectedClassName = 'ace_autocomplete_selected' 4 | 5 | # 6 | # TODO mouse scrool 7 | # 8 | class AutoCompleteView 9 | constructor:(@editor, @autoComplete) -> 10 | @init() 11 | 12 | init:()=> 13 | @wrap = document.createElement('div') 14 | @listElement = document.createElement('ul') 15 | @wrap.className = 'ace_autocomplete' 16 | @wrap.style.display = 'none' 17 | @listElement.style.listStyleType = 'none' 18 | @wrap.style.position = 'fixed' #TODO use position absolute for scroll 19 | @wrap.style.zIndex = '1000' 20 | @wrap.appendChild(@listElement) 21 | 22 | show:() -> 23 | @wrap.style.display = 'block' 24 | 25 | hide:() -> 26 | @wrap.style.display = 'none' 27 | 28 | # 29 | # TODO hardcode position value 30 | # 31 | setPosition:(coords) -> 32 | top = coords.pageY + 20 33 | editorBottom = $(@editor.container).offset().top + $(@editor.container).height() 34 | bottom = top + $(@wrap).height() 35 | if(bottom < editorBottom) 36 | @wrap.style.top = top + 'px' 37 | @wrap.style.left = coords.pageX + 'px' 38 | else 39 | @wrap.style.top = (top - $(@wrap).height() - 20) + 'px' 40 | @wrap.style.left = coords.pageX + 'px' 41 | 42 | current:()-> 43 | children = @listElement.childNodes 44 | for i, child of children 45 | if(child.className == selectedClassName) 46 | return child 47 | null 48 | 49 | focusNext:()-> 50 | curr = @current() 51 | focus = curr.nextSibling 52 | if(focus) 53 | curr.className = '' 54 | focus.className = selectedClassName 55 | @adjustPosition() 56 | 57 | focusPrev:()-> 58 | curr = @current() 59 | focus = curr.previousSibling 60 | if(focus) 61 | curr.className = '' 62 | focus.className = selectedClassName 63 | @adjustPosition() 64 | 65 | ensureFocus:()-> 66 | if(!@current()) 67 | if(@listElement.firstChild) 68 | @listElement.firstChild.className = selectedClassName 69 | @adjustPosition() 70 | 71 | adjustPosition:()-> 72 | elm = @current() 73 | if(elm) 74 | newMargin = '' 75 | wrapHeight = $(@wrap).height(); 76 | elmOuterHeight = $(elm).outerHeight() 77 | preMargin = $(@listElement).css("margin-top").replace('px', '') 78 | preMargin = parseInt(preMargin) 79 | pos = $(elm).position() 80 | 81 | if(pos.top >= (wrapHeight - elmOuterHeight)) 82 | newMargin = (preMargin - elmOuterHeight) + 'px' 83 | $(@listElement).css("margin-top", newMargin) 84 | 85 | if(pos.top < 0) 86 | newMargin = (-pos.top + preMargin) + 'px' 87 | $(@listElement).css("margin-top", newMargin) 88 | 89 | exports.AutoCompleteView = AutoCompleteView 90 | return exports 91 | ) 92 | -------------------------------------------------------------------------------- /src/coffee/compilationService.coffee: -------------------------------------------------------------------------------- 1 | define('CompilationService', ['require', 'exports', 'module', 'EditorPosition'], (require, exports, module) -> 2 | 3 | EditorPosition = require('EditorPosition').EditorPosition 4 | 5 | class CompilationService 6 | constructor:(@editor, @ServiceShim) -> 7 | @editorPos = new EditorPosition(@editor) 8 | 9 | getCompilation:(script, charpos, isMemberCompletion) => 10 | compInfo = @ServiceShim.languageService.getCompletionsAtPosition(script, charpos, isMemberCompletion); 11 | compInfo 12 | 13 | getCursorCompilation:(script, cursor) => 14 | pos = @editorPos.getPositionChars(cursor) 15 | text = @editor.session.getLine(cursor.row).slice(0, cursor.column) 16 | 17 | isMemberCompletion = false 18 | matches = text.match(/\.([a-zA-Z_0-9\$]*$)/) 19 | 20 | if (matches && matches.length > 0) 21 | @matchText = matches[1] 22 | isMemberCompletion = true 23 | pos -= @matchText.length 24 | else 25 | matches = text.match(/[a-zA-Z_0-9\$]*$/) 26 | @matchText = matches[0] 27 | 28 | @getCompilation(script, pos, isMemberCompletion) 29 | 30 | getCurrentPositionCompilation:(script) => 31 | @getCursorCompilation(script, @editor.getCursorPosition()) 32 | 33 | exports.CompilationService = CompilationService 34 | exports 35 | ) -------------------------------------------------------------------------------- /src/coffee/documentPositionUtil.coffee: -------------------------------------------------------------------------------- 1 | define('DocumentPositionUtil', ['require', 'exports', 'module'], (require, exports, module) -> 2 | class DocumentPositionUtil 3 | 4 | @getLinesChars:(lines)-> 5 | count = 0 6 | lines.forEach((line) => 7 | count += (line.length + 1) 8 | ) 9 | count 10 | 11 | @getChars:(doc, pos) -> 12 | @getLinesChars(doc.getLines(0, pos.row - 1)) + pos.column 13 | 14 | @getPosition:(doc, chars) -> 15 | lines = doc.getAllLines() 16 | count = 0 17 | row = 0 18 | for i,line of lines 19 | if(chars < (count + (line.length + 1))) 20 | return {row: row, column: (chars - count)} 21 | count += (line.length + 1) 22 | row += 1 23 | 24 | {row: row, column: (chars - count)} 25 | 26 | exports.DocumentPositionUtil = DocumentPositionUtil 27 | exports 28 | ) -------------------------------------------------------------------------------- /src/coffee/editorPosition.coffee: -------------------------------------------------------------------------------- 1 | define('EditorPosition', ['require', 'exports', 'module'], (require, exports, module) -> 2 | 3 | DocumentPositionUtil = require('DocumentPositionUtil').DocumentPositionUtil 4 | 5 | class EditorPosition 6 | constructor:(@editor) -> 7 | 8 | getLinesChars:(lines) -> 9 | DocumentPositionUtil.getLinesChars(lines) 10 | 11 | getPositionChars:(pos) => 12 | doc = @editor.getSession().getDocument() 13 | DocumentPositionUtil.getChars(doc, pos) 14 | 15 | getAcePositionFromChars:(chars) => 16 | doc = @editor.getSession().getDocument() 17 | DocumentPositionUtil.getPosition(doc, chars) 18 | 19 | getCurrentCharPosition:() => 20 | @getPositionChars(@editor.getCursorPosition()) 21 | 22 | getCurrentLeftChar:() => 23 | @getPositionLeftChar(@editor.getCursorPosition()) 24 | 25 | getPositionChar:(cursor)=> 26 | range = { 27 | start:{ row: cursor.row, column:cursor.column }, 28 | end:{ row: cursor.row, column:cursor.column + 1 } 29 | } 30 | @editor.getSession().getDocument().getTextRange(range) 31 | 32 | getPositionLeftChar:(cursor) => 33 | range = { 34 | start:{ row: cursor.row, column:cursor.column }, 35 | end:{ row: cursor.row, column:cursor.column - 1 } 36 | } 37 | @editor.getSession().getDocument().getTextRange(range) 38 | 39 | exports.EditorPosition = EditorPosition 40 | exports 41 | ) -------------------------------------------------------------------------------- /src/coffee/fileService.coffee: -------------------------------------------------------------------------------- 1 | define('FileService', ['require', 'exports', 'module' ], (require, exports, module) -> 2 | class FileService 3 | constructor:(@ajaxHost) -> 4 | 5 | readFile:(path, cb) => 6 | @ajaxHost.ajax({ 7 | type: "GET", 8 | url: path, 9 | success: cb 10 | error :((jqXHR, textStatus) => 11 | console.log(textStatus) 12 | )} 13 | ) 14 | 15 | writeFile:(path, content, cb) => 16 | @ajaxHost.ajax({ 17 | type: "POST", 18 | url: path, 19 | data: { content:content} 20 | success: cb 21 | error :((jqXHR, textStatus) => 22 | console.log(textStatus) 23 | )} 24 | ) 25 | 26 | exports.FileService = FileService 27 | exports 28 | ) -------------------------------------------------------------------------------- /src/typescript-mode/typescript.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Distributed under the BSD license: 3 | * 4 | * Copyright (c) 2012, Ajax.org B.V. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Ajax.org B.V. nor the 15 | * names of its contributors may be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | * 30 | * Contributor(s): 31 | * 32 | * 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /* 37 | THIS FILE WAS AUTOGENERATED BY mode.tmpl.js 38 | */ 39 | 40 | define(function(require, exports, module) { 41 | "use strict"; 42 | 43 | var oop = require("../lib/oop"); 44 | var TextMode = require("./text").Mode; 45 | var Tokenizer = require("../tokenizer").Tokenizer; 46 | var TypeScriptHighlightRules = require("./typescript_highlight_rules").TypeScriptHighlightRules; 47 | var WorkerClient = require("../worker/worker_client").WorkerClient; 48 | 49 | var Mode = function() { 50 | var highlighter = new TypeScriptHighlightRules(); 51 | 52 | this.$tokenizer = new Tokenizer(highlighter.getRules()); 53 | }; 54 | oop.inherits(Mode, TextMode); 55 | 56 | (function() { 57 | // Extra logic goes here. 58 | 59 | this.createWorker = function(session) { 60 | var worker = new WorkerClient(["ace"], "ace/mode/typescript_worker", "TypeScriptWorker"); 61 | worker.attachToDocument(session.getDocument()); 62 | 63 | worker.on("terminate", function() { 64 | session.clearAnnotations(); 65 | }); 66 | 67 | worker.on("compileErrors", function(results) { 68 | session.setAnnotations(results.data); 69 | }); 70 | 71 | worker.on("compiled", function(result) { 72 | session._emit("compiled", {data: result.data}); 73 | }); 74 | 75 | return worker; 76 | }; 77 | }).call(Mode.prototype); 78 | 79 | exports.Mode = Mode; 80 | }); -------------------------------------------------------------------------------- /src/typescript-mode/typescript/DocumentPositionUtil.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | define(function(require, exports, module) { 4 | var DocumentPositionUtil; 5 | DocumentPositionUtil = (function() { 6 | 7 | function DocumentPositionUtil() {} 8 | 9 | DocumentPositionUtil.getLinesChars = function(lines) { 10 | var count; 11 | count = 0; 12 | lines.forEach(function(line) { 13 | return count += line.length + 1; 14 | }); 15 | return count; 16 | }; 17 | 18 | DocumentPositionUtil.getChars = function(doc, pos) { 19 | return DocumentPositionUtil.getLinesChars(doc.getLines(0, pos.row - 1)) + pos.column; 20 | }; 21 | 22 | DocumentPositionUtil.getPosition = function(doc, chars) { 23 | var count, i, line, lines, row; 24 | lines = doc.getAllLines(); 25 | count = 0; 26 | row = 0; 27 | for (i in lines) { 28 | line = lines[i]; 29 | if (chars < (count + (line.length + 1))) { 30 | return { 31 | row: row, 32 | column: chars - count 33 | }; 34 | } 35 | count += line.length + 1; 36 | row += 1; 37 | } 38 | return { 39 | row: row, 40 | column: chars - count 41 | }; 42 | }; 43 | 44 | return DocumentPositionUtil; 45 | 46 | }).call(this); 47 | exports.DocumentPositionUtil = DocumentPositionUtil; 48 | return exports; 49 | }); 50 | 51 | }).call(this); 52 | -------------------------------------------------------------------------------- /src/typescript-mode/typescript/lightHarness.js: -------------------------------------------------------------------------------- 1 | // parcial copy from typescript harness.js 2 | define( function(require, exports, module) { 3 | 4 | var __extends = this.__extends || function (d, b) { 5 | function __() { 6 | this.constructor = d; 7 | } 8 | __.prototype = b.prototype; 9 | d.prototype = new __(); 10 | }; 11 | 12 | var Services = require('./typescriptServices').Services; 13 | var TypeScript = require('./typescriptServices').TypeScript; 14 | 15 | var ScriptInfo = (function () { 16 | function ScriptInfo(name, content, isResident, maxScriptVersions) { 17 | this.name = name; 18 | this.content = content; 19 | this.isResident = isResident; 20 | this.maxScriptVersions = maxScriptVersions; 21 | this.editRanges = []; 22 | this.version = 1; 23 | } 24 | ScriptInfo.prototype.updateContent = function (content, isResident) { 25 | this.editRanges = []; 26 | this.content = content; 27 | this.isResident = isResident; 28 | this.version++; 29 | }; 30 | ScriptInfo.prototype.editContent = function (minChar, limChar, newText) { 31 | var prefix = this.content.substring(0, minChar); 32 | var middle = newText; 33 | var suffix = this.content.substring(limChar); 34 | this.content = prefix + middle + suffix; 35 | this.editRanges.push({ 36 | length: this.content.length, 37 | editRange: new TypeScript.ScriptEditRange(minChar, limChar, (limChar - minChar) + newText.length) 38 | }); 39 | if(this.editRanges.length > this.maxScriptVersions) { 40 | this.editRanges.splice(0, this.maxScriptVersions - this.editRanges.length); 41 | } 42 | this.version++; 43 | }; 44 | ScriptInfo.prototype.getEditRangeSinceVersion = function (version) { 45 | if(this.version == version) { 46 | return null; 47 | } 48 | var initialEditRangeIndex = this.editRanges.length - (this.version - version); 49 | if(initialEditRangeIndex < 0 || initialEditRangeIndex >= this.editRanges.length) { 50 | return TypeScript.ScriptEditRange.unknown(); 51 | } 52 | var entries = this.editRanges.slice(initialEditRangeIndex); 53 | var minDistFromStart = entries.map(function (x) { 54 | return x.editRange.minChar; 55 | }).reduce(function (prev, current) { 56 | return Math.min(prev, current); 57 | }); 58 | var minDistFromEnd = entries.map(function (x) { 59 | return x.length - x.editRange.limChar; 60 | }).reduce(function (prev, current) { 61 | return Math.min(prev, current); 62 | }); 63 | var aggDelta = entries.map(function (x) { 64 | return x.editRange.delta; 65 | }).reduce(function (prev, current) { 66 | return prev + current; 67 | }); 68 | return new TypeScript.ScriptEditRange(minDistFromStart, entries[0].length - minDistFromEnd, aggDelta); 69 | }; 70 | return ScriptInfo; 71 | })(); 72 | exports.ScriptInfo = ScriptInfo; 73 | var TypeScriptLS = (function () { 74 | function TypeScriptLS() { 75 | this.ls = null; 76 | this.scripts = []; 77 | this.maxScriptVersions = 100; 78 | } 79 | TypeScriptLS.prototype.addDefaultLibrary = function () { 80 | this.addScript("lib.d.ts", Harness.Compiler.libText, true); 81 | }; 82 | TypeScriptLS.prototype.addFile = function (name, isResident) { 83 | if (typeof isResident === "undefined") { isResident = false; } 84 | var code = Harness.CollateralReader.read(name); 85 | this.addScript(name, code, isResident); 86 | }; 87 | TypeScriptLS.prototype.addScript = function (name, content, isResident) { 88 | if (typeof isResident === "undefined") { isResident = false; } 89 | var script = new ScriptInfo(name, content, isResident, this.maxScriptVersions); 90 | this.scripts.push(script); 91 | }; 92 | TypeScriptLS.prototype.updateScript = function (name, content, isResident) { 93 | if (typeof isResident === "undefined") { isResident = false; } 94 | for(var i = 0; i < this.scripts.length; i++) { 95 | if(this.scripts[i].name == name) { 96 | this.scripts[i].updateContent(content, isResident); 97 | return; 98 | } 99 | } 100 | this.addScript(name, content, isResident); 101 | }; 102 | TypeScriptLS.prototype.editScript = function (name, minChar, limChar, newText) { 103 | for(var i = 0; i < this.scripts.length; i++) { 104 | if(this.scripts[i].name == name) { 105 | this.scripts[i].editContent(minChar, limChar, newText); 106 | return; 107 | } 108 | } 109 | throw new Error("No script with name '" + name + "'"); 110 | }; 111 | TypeScriptLS.prototype.getScriptContent = function (scriptIndex) { 112 | return this.scripts[scriptIndex].content; 113 | }; 114 | TypeScriptLS.prototype.information = function () { 115 | return true; 116 | }; 117 | TypeScriptLS.prototype.debug = function () { 118 | return true; 119 | }; 120 | TypeScriptLS.prototype.warning = function () { 121 | return true; 122 | }; 123 | TypeScriptLS.prototype.error = function () { 124 | return true; 125 | }; 126 | TypeScriptLS.prototype.fatal = function () { 127 | return true; 128 | }; 129 | TypeScriptLS.prototype.log = function (s) { 130 | // console.log("TypeScriptLS:" + s); 131 | }; 132 | TypeScriptLS.prototype.getCompilationSettings = function () { 133 | return ""; 134 | }; 135 | TypeScriptLS.prototype.getScriptCount = function () { 136 | return this.scripts.length; 137 | }; 138 | TypeScriptLS.prototype.getScriptSourceText = function (scriptIndex, start, end) { 139 | return this.scripts[scriptIndex].content.substring(start, end); 140 | }; 141 | TypeScriptLS.prototype.getScriptSourceLength = function (scriptIndex) { 142 | return this.scripts[scriptIndex].content.length; 143 | }; 144 | TypeScriptLS.prototype.getScriptId = function (scriptIndex) { 145 | return this.scripts[scriptIndex].name; 146 | }; 147 | TypeScriptLS.prototype.getScriptIsResident = function (scriptIndex) { 148 | return this.scripts[scriptIndex].isResident; 149 | }; 150 | TypeScriptLS.prototype.getScriptVersion = function (scriptIndex) { 151 | return this.scripts[scriptIndex].version; 152 | }; 153 | TypeScriptLS.prototype.getScriptEditRangeSinceVersion = function (scriptIndex, scriptVersion) { 154 | var range = this.scripts[scriptIndex].getEditRangeSinceVersion(scriptVersion); 155 | return (range.minChar + "," + range.limChar + "," + range.delta); 156 | }; 157 | TypeScriptLS.prototype.getLanguageService = function () { 158 | var ls = new Services.TypeScriptServicesFactory().createLanguageServiceShim(this); 159 | ls.refresh(true); 160 | this.ls = ls; 161 | return ls; 162 | }; 163 | TypeScriptLS.prototype.parseSourceText = function (fileName, sourceText) { 164 | var parser = new TypeScript.Parser(); 165 | parser.setErrorRecovery(null, -1, -1); 166 | parser.errorCallback = function (a, b, c, d) { 167 | }; 168 | var script = parser.parse(sourceText, fileName, 0); 169 | return script; 170 | }; 171 | TypeScriptLS.prototype.parseFile = function (fileName) { 172 | var sourceText = new TypeScript.StringSourceText(IO.readFile(fileName)); 173 | return this.parseSourceText(fileName, sourceText); 174 | }; 175 | TypeScriptLS.prototype.lineColToPosition = function (fileName, line, col) { 176 | var script = this.ls.languageService.getScriptAST(fileName); 177 | assert.notNull(script); 178 | assert(line >= 1); 179 | assert(col >= 1); 180 | assert(line < script.locationInfo.lineMap.length); 181 | return TypeScript.getPositionFromLineColumn(script, line, col); 182 | }; 183 | TypeScriptLS.prototype.positionToLineCol = function (fileName, position) { 184 | var script = this.ls.languageService.getScriptAST(fileName); 185 | assert.notNull(script); 186 | var result = TypeScript.getLineColumnFromPosition(script, position); 187 | assert(result.line >= 1); 188 | assert(result.col >= 1); 189 | return result; 190 | }; 191 | TypeScriptLS.prototype.checkEdits = function (sourceFileName, baselineFileName, edits) { 192 | var script = Harness.CollateralReader.read(sourceFileName); 193 | var formattedScript = this.applyEdits(script, edits); 194 | var baseline = Harness.CollateralReader.read(baselineFileName); 195 | assert.noDiff(formattedScript, baseline); 196 | assert.equal(formattedScript, baseline); 197 | }; 198 | TypeScriptLS.prototype.applyEdits = function (content, edits) { 199 | var result = content; 200 | edits = this.normalizeEdits(edits); 201 | for(var i = edits.length - 1; i >= 0; i--) { 202 | var edit = edits[i]; 203 | var prefix = result.substring(0, edit.minChar); 204 | var middle = edit.text; 205 | var suffix = result.substring(edit.limChar); 206 | result = prefix + middle + suffix; 207 | } 208 | return result; 209 | }; 210 | TypeScriptLS.prototype.normalizeEdits = function (edits) { 211 | var result = []; 212 | function mapEdits(edits) { 213 | var result = []; 214 | for(var i = 0; i < edits.length; i++) { 215 | result.push({ 216 | edit: edits[i], 217 | index: i 218 | }); 219 | } 220 | return result; 221 | } 222 | var temp = mapEdits(edits).sort(function (a, b) { 223 | var result = a.edit.minChar - b.edit.minChar; 224 | if(result == 0) { 225 | result = a.index - b.index; 226 | } 227 | return result; 228 | }); 229 | var current = 0; 230 | var next = 1; 231 | while(current < temp.length) { 232 | var currentEdit = temp[current].edit; 233 | if(next >= temp.length) { 234 | result.push(currentEdit); 235 | current++; 236 | continue; 237 | } 238 | var nextEdit = temp[next].edit; 239 | var gap = nextEdit.minChar - currentEdit.limChar; 240 | if(gap >= 0) { 241 | result.push(currentEdit); 242 | current = next; 243 | next++; 244 | continue; 245 | } 246 | if(currentEdit.limChar >= nextEdit.limChar) { 247 | next++; 248 | continue; 249 | } else { 250 | throw new Error("Trying to apply overlapping edits"); 251 | } 252 | } 253 | return result; 254 | }; 255 | return TypeScriptLS; 256 | })(); 257 | exports.TypeScriptLS = TypeScriptLS; 258 | 259 | }); -------------------------------------------------------------------------------- /stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | 3 | } 4 | 5 | .warp-container{ 6 | float:left; 7 | width:49%; 8 | } 9 | 10 | .editor-container { 11 | position:relative; 12 | /* padding:20px; */ 13 | height:100%; 14 | width:99%; 15 | float:left; 16 | } 17 | #editor { 18 | position:absolute; 19 | max-height:10000px; 20 | top: 6px; 21 | right: 0; 22 | bottom: 0; 23 | left: 0; 24 | } 25 | 26 | #output { 27 | position:absolute; 28 | max-height:10000; 29 | top: 6px; 30 | right: 0; 31 | bottom: 0; 32 | left: 10; 33 | } 34 | 35 | .editor-area{ 36 | height: auto; 37 | padding-bottom: 50px; 38 | height:70%; 39 | /* margin-bottom:20px; */ 40 | } 41 | 42 | .typescript-ref{ 43 | position: absolute; 44 | border:1px solid white; 45 | opacity:0.7; 46 | } 47 | 48 | .typescript-error{ 49 | position: absolute; 50 | border-bottom: 1px solid red; 51 | } 52 | 53 | .langauge-title h2{ 54 | padding: 5px 10px; 55 | font-size:14pt; 56 | background: #eee; 57 | border:1px solid black; 58 | display:block; 59 | margin:0px; 60 | height:30px; 61 | line-height:30px; 62 | } 63 | #javascript-run { 64 | margin:0px; 65 | margin-top:10px; 66 | padding:5px; 67 | background:#999; 68 | color:white; 69 | } 70 | 71 | .ace_autocomplete{ 72 | height:226px; 73 | background:white; 74 | overflow:hidden; 75 | border:1px solid #ccc; 76 | } 77 | 78 | .ace_autocomplete ul{ 79 | width:400px; 80 | margin:0px; 81 | padding:2px; 82 | } 83 | 84 | .ace_autocomplete li:hover{ 85 | 86 | } 87 | 88 | .ace_autocomplete li{ 89 | padding:1px; 90 | line-height:1.2em; 91 | height:1.2em; 92 | overflow:hidden; 93 | } 94 | 95 | .ace_autocomplete_selected{ 96 | background:#eee; 97 | } 98 | 99 | .ace_autocomplete_selected .label-name{ 100 | font-weight:bold; 101 | } 102 | 103 | .label-kind{ 104 | background:#666; 105 | color:white; 106 | padding:0px 3px; 107 | margin-right:3px; 108 | } 109 | 110 | .label-kind-property{ 111 | background:green; 112 | } 113 | 114 | .label-kind-method{ 115 | background:blue; 116 | } 117 | 118 | .label-kind-interface{ 119 | background:#666; 120 | } 121 | 122 | .label-kind-variable{ 123 | background:orangered; 124 | } 125 | 126 | .label-type{ 127 | padding-left:10px; 128 | color:blue; 129 | visibility:hidden; 130 | } 131 | 132 | .ace_autocomplete_selected .label-type{ 133 | visibility:visible; 134 | } --------------------------------------------------------------------------------