├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── app.py ├── bot.py ├── composer.json ├── demo ├── fibonacci.js └── fibonacci.py ├── editor.html ├── favicon.ico ├── index.html ├── index.php ├── js ├── app.js ├── editor.html ├── handlers.js ├── index.js ├── mic.js └── parser.js ├── judge.py ├── lib ├── bravey.min.js └── pane1 │ ├── codemirror.css │ ├── codemirror.js │ ├── dialog.css │ ├── dialog.js │ ├── javascript.js │ ├── matchbrackets.js │ ├── python.js │ ├── searchcursor.js │ └── vim.js ├── pane1.html ├── static └── img │ ├── dot.png │ ├── english.svg │ ├── hindi.svg │ ├── js.svg │ ├── logo-alt.svg │ ├── logo.svg │ ├── mic.svg │ ├── python.svg │ ├── run.svg │ ├── text-logo.svg │ └── undo.svg └── styles ├── editor.css ├── editor.scss ├── home.css ├── home.scss ├── lol.html └── reset.css /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teamsudocode/dexter/0ccceac9a97687c39c84eb92ee834021d66767c8/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | styles/home.css.map 2 | styles/editor.css.map 3 | styles/.sass-cache 4 | intermediate.py 5 | intermediate.js 6 | intermediate.js 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dexter 2 | 3 | Ever wondered if you could talk to your computer in your natural language, and it writes the code for you, and that too in your favorite language? 4 | 5 | #### Dexter is an AI-based code editor that allows you to code parallelly in Javascript and Python just by conversing with it. It supports two of the most widely used languages in the country, Hindi and, English. 6 | 7 | Won 1st Prize at Hack36, MNNIT Allahabad. 8 | 9 | [Watch the Demo Video](https://www.youtube.com/watch?v=qFzCyY3lHZE) 10 | 11 | [View the Presentation](https://drive.google.com/file/d/1ziJM2d6zE2I5KthzUSVCVK7HWTWhoQ4A/view?usp=sharing) 12 | 13 | ### How to run 14 | 15 | ``` 16 | $ git clone https://github.com/teamsudocode/dexter.git 17 | $ cd dexter 18 | $ pip install --user flask flask-cors zulip 19 | $ python3 app.py 20 | ``` 21 | 22 | Open another terminal window 23 | 24 | ``` 25 | $ cd dexter 26 | $ python3 -m http.server 27 | ``` 28 | Navigate to localhost:8000. 29 | 30 | **Additional requirement**: 31 | `nodejs` to run `javascript` code. 32 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify 2 | from judge import runProcess 3 | from flask_cors import CORS 4 | import zulip 5 | 6 | # Keyword arguments 'email' and 'api_key' are not required if you are using ~/.zuliprc 7 | client = zulip.Client(email="mydexter-bot@hack36.zulipchat.com", 8 | api_key="gX6ulWhAzExkZcYSAtWgpsAMbrXLjcJn", 9 | site="https://hack36.zulipchat.com") 10 | 11 | app = Flask('dexter') 12 | CORS(app) 13 | 14 | 15 | @app.route('/compile', methods=['POST']) 16 | def compile(): 17 | content = r'' + request.form['content'] 18 | # with open('my.py', 'w') as f: 19 | # print(exec(content)) 20 | with open('intermediate.py', 'w') as f: 21 | # print(repr(content).replace("'", '')) 22 | # new_content = content.replace("'", '') 23 | for i in content: 24 | f.write(i) 25 | 26 | # f.write(repr(content).replace("", '')) 27 | 28 | outBuf, errBuf = runProcess(['python3', 'intermediate.py']) 29 | return jsonify({'out': str(outBuf), 'err': str(errBuf)}) 30 | 31 | 32 | @app.route('/js', methods=['POST']) 33 | def interpret(): 34 | content = r'' + request.form['content'] 35 | # with open('my.py', 'w') as f: 36 | # print(exec(content)) 37 | with open('intermediate.js', 'w') as f: 38 | # print(repr(content).replace("'", '')) 39 | # new_content = content.replace("'", '') 40 | for i in content: 41 | f.write(i) 42 | 43 | # f.write(repr(content).replace("", '')) 44 | 45 | outBuf, errBuf = runProcess(['node', 'intermediate.js']) 46 | return jsonify({'out': str(outBuf), 'err': str(errBuf)}) 47 | 48 | 49 | @app.route('/zulip', methods=['POST']) 50 | def zulip(): 51 | # email = request.form['email'] 52 | email = 'kuchtohtha@gmail.com' 53 | content = request.form['content'] 54 | client.send_message({ 55 | "type": "private", 56 | "to": email, 57 | "content": content, 58 | }) 59 | return 'ok' 60 | 61 | 62 | 63 | if __name__ == '__main__': 64 | app.run(debug=True) 65 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import zulip 4 | 5 | # Keyword arguments 'email' and 'api_key' are not required if you are using ~/.zuliprc 6 | client = zulip.Client(email="mydexter-bot@hack36.zulipchat.com", 7 | api_key="gX6ulWhAzExkZcYSAtWgpsAMbrXLjcJn", 8 | site="https://hack36.zulipchat.com") 9 | 10 | # Send a private message 11 | def send_message(message, email): 12 | client.send_message({ 13 | "type": "private", 14 | "to": email, 15 | "content": message, 16 | }) -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | 2 | {} 3 | -------------------------------------------------------------------------------- /demo/fibonacci.js: -------------------------------------------------------------------------------- 1 | function fibo(n){ 2 | if (n == 1 || n == 0){ 3 | return 1; 4 | } 5 | else{ 6 | return fibo(n-1) + fibo(n-2); 7 | } 8 | 9 | for(let i=0; i <1000; i++){ 10 | console.log(fibo(i)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /demo/fibonacci.py: -------------------------------------------------------------------------------- 1 | def fibo(n): 2 | if n == 1 or n == 0: 3 | return 1 4 | else: 5 | return fibo(n - 1) + fibo(n - 2) 6 | 7 | 8 | for i in range(1000): 9 | print(fibo(i)) 10 | -------------------------------------------------------------------------------- /editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dexter 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 33 | 34 |
35 |
36 |
 
37 |
38 |
index.js
39 |
40 |
41 |
42 |
43 |
44 | 46 |
47 |
48 |
49 |
50 |
51 |
 
52 |
53 |
index.py
54 |
55 |
56 |
57 |
58 | 60 |
61 |
62 |
63 |
64 |
65 |
 
66 |
67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 166 | 167 | 168 | // integration 169 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teamsudocode/dexter/0ccceac9a97687c39c84eb92ee834021d66767c8/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dexter 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 |

Let your talking do the code

18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | var nlp = null; 2 | var mic = null; 3 | 4 | var python = true; 5 | var javascript = true; 6 | 7 | var dexterIsRunning = true; 8 | 9 | function newApp() { 10 | nlp = setUpNlp() 11 | mic = new Mic(micResponseHandler(nlp, python, javascript)) 12 | } 13 | 14 | function typeEffect(element, speed) { 15 | var text = $(element).text(); 16 | $(element).html(''); 17 | 18 | var i = 0; 19 | var timer = setInterval(function () { 20 | if (i < text.length) { 21 | $(element).append(text.charAt(i)); 22 | i++; 23 | } else { 24 | clearInterval(timer); 25 | } 26 | }, speed); 27 | } 28 | 29 | 30 | function micResponseHandler(nlp, python, javascript) { 31 | return (text) => { 32 | console.log('response handler says', text) 33 | let entities = nlp.test(text) 34 | if (!entities) { 35 | return 36 | } 37 | if (IsKnownCommand(entities.intent)) { 38 | commandHandlers(entities.intent) 39 | return 40 | } 41 | 42 | if (!dexterIsRunning) { 43 | return 44 | } 45 | let py_result = py_handler(entities) 46 | let js_result = js_handler(entities) 47 | if (javascript) { 48 | _insertTextAtCursor(editor1, js_result.entity) 49 | } 50 | if (python) { 51 | _insertTextAtCursor(editor2, py_result.entity) 52 | } 53 | $('#text').html(text); 54 | typeEffect($('#text'), 75); 55 | } 56 | } 57 | 58 | function runPython() { 59 | let content = editor2.getValue() 60 | 61 | let showPyResult = (result) => { 62 | $('#pyfile').html('output') 63 | editor2.setValue(result.out.replace('b\'', '')) 64 | } 65 | 66 | $.ajax({ 67 | url: 'http://localhost:5000/compile', 68 | type: 'POST', 69 | crossDomain: true, 70 | data: { content:content }, 71 | success: showPyResult, 72 | error: showPyResult, 73 | }) 74 | 75 | } 76 | 77 | function runJavascript() { 78 | let content = editor1.getValue() 79 | 80 | let showJsResult = (result) => { 81 | $('#jsfile').html('output') 82 | console.log(result) 83 | editor1.setValue(result.out.replace('b\'', '')) 84 | } 85 | $.ajax({ 86 | url: 'http://localhost:5000/js', 87 | type: 'POST', 88 | crossDomain: true, 89 | data: { content:content }, 90 | success: showJsResult, 91 | error: showJsResult, 92 | }) 93 | } 94 | 95 | function runZulip() { 96 | let content = editor1.getValue() 97 | $.ajax({ 98 | url: 'http://localhost:5000/zulip', 99 | type: 'POST', 100 | crossDomain: true, 101 | data: { content:content }, 102 | success: console.log, 103 | error: console.log, 104 | }) 105 | } 106 | 107 | function commandHandlers(command) { 108 | if (command == 'dexter_start') { 109 | dexterIsRunning = true 110 | } else if (command == 'dexter_stop') { 111 | dexterIsRunning = false 112 | } 113 | 114 | else if (command == 'py_move_left') { 115 | if (python) _wmoveleft(editor2) 116 | } else if (command == 'py_move_right') { 117 | if (python) _wmoveright(editor2) 118 | } else if (command == 'py_move_up') { 119 | if (python) _lineUp(editor2) 120 | } else if (command == 'py_move_down') { 121 | if (python) _lineDown(editor2) 122 | } 123 | 124 | else if (command == 'js_move_left') { 125 | if (javascript) _wmoveleft(editor1) 126 | } else if (command == 'js_move_right') { 127 | if (javascript) _wmoveright(editor1) 128 | } else if (command == 'js_move_up') { 129 | if (javascript) _lineUp(editor1) 130 | } else if (command == 'js_move_down') { 131 | if (javascript) _lineDown(editor1) 132 | } else if (command === 'dexter_javascript'){ 133 | python = false 134 | javascript = true 135 | console.log("Calling jsView") 136 | $('#editorspane').css('grid-template-columns', '100% 0% 0%'); 137 | }else if (command === 'dexter_python'){ 138 | python = true 139 | javascript = false 140 | $('#editorspane').css('grid-template-columns', '0% 0% 100%'); 141 | } else if (command === 'dexter_full'){ 142 | python = true 143 | javascript = true 144 | $('#editorspane').css('grid-template-columns', '49.75% 0.5% 49.75%'); 145 | } else if (command == 'dexter_run') { 146 | runPython() 147 | runJavascript() 148 | } else if (command == 'dexter_run_py') { 149 | runPython() 150 | } else if (command == 'dexter_run_js') { 151 | runJavascript() 152 | } else if (command == 'dexter_zulip') { 153 | runZulip() 154 | } else if (command == 'dexter_clear') { 155 | editor2.setValue('') 156 | $('#jsfile').html('index.js') 157 | $('#pyfile').html('index.py') 158 | editor1.setValue('') 159 | } else if (command == 'dexter_redo') { 160 | _undo() 161 | } else if (command == 'dexter_redo') { 162 | _redo() 163 | } else if (command == 'dexter_add_closing_bracket') { 164 | 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /js/editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Brython 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 123 | 124 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
144 | 145 |
Brython version: 146 |
147 | 148 | 149 |
150 |
151 |
152 | 153 | 154 |
155 |
156 |
157 | 158 |
159 |
160 |
161 | 162 | 163 | Debug 164 |
165 | 166 |
167 | 168 | 169 |
170 |
171 |
172 | 173 |
174 |
175 | 176 |
177 | 178 | Report a bug 179 |
180 | 181 | Built-in test suite 182 |
183 | 184 | CPython tests 185 |
186 |
187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /js/handlers.js: -------------------------------------------------------------------------------- 1 | function js_handler(result){ 2 | const js_handler_literal = { 3 | "declare_string": declare_string_js, 4 | "declare_integer": declare_integer_js, 5 | "create_function": create_function_js, 6 | "create_loop": create_loop_js, 7 | "move_cursor_to_line": move_cursor_to_line, 8 | "if_condition": if_condition_js, 9 | "print": print_js, 10 | }; 11 | 12 | let entity = result.intent; 13 | let function_handler = js_handler_literal[entity]; 14 | let entities = {}; 15 | for (let i of result.entities){ 16 | entities[i.id] = i; 17 | } 18 | return function_handler(entities); 19 | } 20 | 21 | function py_handler(result){ 22 | const py_handler_literal = { 23 | "declare_string": declare_string_py, 24 | "declare_integer": declare_integer_py, 25 | "create_function": create_function_py, 26 | "create_loop": create_loop_py, 27 | "move_cursor_to_line": move_cursor_to_line, 28 | "if_condition": if_condition_py, 29 | "print": print_py, 30 | }; 31 | 32 | let entity = result.intent; 33 | let function_handler = py_handler_literal[entity]; 34 | let entities = {}; 35 | for (let i of result.entities){ 36 | entities[i.id] = i; 37 | } 38 | return function_handler(entities); 39 | } 40 | 41 | function move_cursor_to_line(entities){ 42 | const lineno = entities['move_cursor_to_line_number'].value; 43 | return ({ 44 | intent: "move", 45 | entity: `M-g g ${lineno}` 46 | }); 47 | } 48 | function create_function_js(entities){ 49 | const name = entities['create_function_name'].value; 50 | const arg = entities['create_function_argument'].value; 51 | return ({ 52 | intent: "insert", 53 | entity: `function ${name}(${arg}){\n\n}`, 54 | movement_callback: ["_lineUp"] 55 | }); 56 | } 57 | 58 | function create_function_py(entities){ 59 | const name = entities['create_function_name'].value; 60 | const arg = entities['create_function_argument'].value; 61 | return ({ 62 | intent: "insert", 63 | entity: `def ${name}(${arg}):\n`, 64 | movement_callback: [] 65 | 66 | }); 67 | } 68 | function create_loop_py(entities){ 69 | const upper_bound = entities['create_loop_counts'].value; 70 | return ({ 71 | intent: "insert", 72 | entity: `for i in range(${upper_bound}):\n\t`, 73 | movement_callback: [] 74 | }); 75 | } 76 | 77 | function create_loop_js(entities){ 78 | const upper_bound = entities['create_loop_counts'].value; 79 | return ({ 80 | intent: "insert", 81 | entity: `for (i = 0; i < ${upper_bound}; i++){\n\n}`, 82 | movement_callback: [_lineUp] 83 | }); 84 | } 85 | 86 | function declare_integer_js(entities){ 87 | const name = entities["declare_integer_var_name"].value; 88 | const value = entities["declare_integer_var_value"].value; 89 | return ({ 90 | intent: "insert", 91 | entity: `var ${name} = ${value};\n`, 92 | movement_callback: [] 93 | }); 94 | } 95 | 96 | function declare_integer_py(entities){ 97 | const name = entities["declare_integer_var_name"].value 98 | const value = entities["declare_integer_var_value"].value 99 | return ({ 100 | intent: "insert", 101 | entity: `${name} = ${value}\n`, 102 | movement_callback: [] 103 | }); 104 | } 105 | function declare_string_js(entities){ 106 | const name = entities["declare_string_var_name"].value 107 | const value = entities["declare_string_var_value"].value 108 | return ({ 109 | intent: "insert", 110 | entity: `var ${name} = ${value};\n`, 111 | movement_callback: [] 112 | }); 113 | } 114 | 115 | function declare_string_py(entities){ 116 | const name = entities["declare_string_var_name"].value 117 | const value = entities["declare_string_var_value"].value 118 | return ({ 119 | intent: "insert", 120 | entity: `${name} = ${value}\n`, 121 | movement_callback: [] 122 | }); 123 | } 124 | 125 | function print_js(entities){ 126 | const name = entities[""]; 127 | } 128 | 129 | function if_condition_js(){ 130 | 131 | } 132 | 133 | function if_condition_py(){ 134 | 135 | } 136 | function print_js(entities){ 137 | const arg = (entities["argument"] === undefined) ? (entities['number'].value) : (entities['argument'].value) 138 | return ({ 139 | intent: "insert", 140 | entity: `console.log(${arg})\n` 141 | }); 142 | } 143 | 144 | function print_py(entities){ 145 | const arg = (entities["argument"] === undefined) ? (entities['number'].value) : (entities['argument'].value) 146 | return ({ 147 | intent: "insert", 148 | entity: `print(${arg})\n` 149 | }); 150 | } 151 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | var toggleHindi = function () { 2 | $('#hindi').css('opacity', '1'); 3 | $('#english').css('opacity', '0.3'); 4 | }; 5 | 6 | var toggleEnglish = function () { 7 | $('#hindi').css('opacity', '0.3'); 8 | $('#english').css('opacity', '1'); 9 | }; 10 | 11 | 12 | $('#hindi').click(toggleHindi); 13 | $('#english').click(toggleEnglish); 14 | 15 | 16 | var fullView = function () { 17 | $('#editorspane').css('grid-template-columns', '49.75% 0.5% 49.75%'); 18 | } 19 | 20 | var jsView = function () { 21 | $('#editorspane').css('grid-template-columns', '100% 0% 0%'); 22 | } 23 | 24 | var pyView = function () { 25 | $('#editorspane').css('grid-template-columns', '0% 0% 100%'); 26 | } 27 | -------------------------------------------------------------------------------- /js/mic.js: -------------------------------------------------------------------------------- 1 | class Mic { 2 | constructor(resultReceiver) { 3 | this.langs = [ 4 | ['English (India)', 'en-IN'], 5 | ['Hindi', 'hi-IN'] 6 | ]; 7 | 8 | this.final_transcript = ''; 9 | this.current_transcript = ''; 10 | this.recognition = null; 11 | this.compatible = false; 12 | this.listening = false; 13 | this.languageSelector = null; 14 | this.currentLanguage = this.langs[0][1]; 15 | this.resultReceiver = resultReceiver; 16 | } 17 | 18 | static capitalize(s) { 19 | let first_char = /\S/; 20 | return s.replace(first_char, function (m) { return m.toUpperCase(); }); 21 | } 22 | 23 | static checkCompatibility() { 24 | return 'webkitSpeechRecognition' in window || 25 | 'SpeechRecognition' in window; 26 | } 27 | 28 | setupRecognitionHandlers() { 29 | if (!this.recognition) { 30 | console.log("Recognition not set up. This should not happen."); 31 | return; 32 | } 33 | this.recognition.onstart = () => { 34 | this.listening = true; 35 | }; 36 | this.recognition.onerror = (event) => { 37 | console.log("recognition says: wtf " + event.error); 38 | }; 39 | this.recognition.onend = () => { 40 | if (this.listening && this.recognition !== undefined) { 41 | console.log('restarting mic') 42 | this.recognition.start(); 43 | } 44 | }; 45 | this.recognition.onresult = (event) => { 46 | for (var i = event.resultIndex; i < event.results.length; ++i) { 47 | if (event.results[i].isFinal) { 48 | this.current_transcript = event.results[i][0].transcript; 49 | // this.final_transcript += event.results[i][0].transcript + '. '; 50 | } 51 | } 52 | console.log('mic says:', this.current_transcript.toLowerCase()) 53 | this.resultReceiver(this.current_transcript.toLowerCase()) 54 | 55 | // this.final_transcript = Mic.capitalize(this.final_transcript); 56 | // askWatson(current_transcript, change); 57 | // console.log(this.current_transcript, '--', this.final_transcript); 58 | // if (this.resultDisplay) 59 | // this.resultDisplay.innerText = this.current_transcript; 60 | // final_span.innerHTML = linebreak(final_transcript); 61 | }; 62 | } 63 | 64 | // garbage 65 | setupMic(resultReceiver) { 66 | this.resultReceiver = resultReceiver 67 | } 68 | 69 | // setupMic(micElem, outputElem, languageSelect, errorHandlerDiv) { 70 | // // setup language selectors 71 | // if (languageSelect) { 72 | // languageSelector = languageSelect; 73 | // while (languageSelect.options.length > 0) 74 | // languageSelect.options.remove(0); 75 | // for (let i = 0; i < this.langs.length; i++) 76 | // languageSelect.options.add(new Option(this.langs[i][0], this.langs[i][1])); 77 | // } 78 | 79 | // // setup mic elem 80 | // micElem.onclick = micClicked; 81 | // resultDisplay = outputElem; 82 | // } 83 | 84 | setLang(lang) { 85 | if (lang == 'en') this.currentLanguage = 'en-IN'; 86 | else if (lang == 'hi') this.currentLanguage = 'hi-IN'; 87 | } 88 | 89 | micClicked(event) { 90 | if (this.listening) { 91 | this.stopListening(); 92 | return; 93 | } 94 | try { 95 | if (en == 1) this.setLang('en'); 96 | else if (hi == 1) this.setLang('hi'); 97 | } catch (e) { } 98 | this.startListening(); 99 | } 100 | 101 | 102 | startListening() { 103 | if (!this.recognition) { 104 | this.recognition = new webkitSpeechRecognition(); 105 | this.setupRecognitionHandlers(); 106 | } 107 | this.listening = true; 108 | this.final_transcript = ''; 109 | this.recognition.lang = this.currentLanguage; 110 | this.recognition.start(); 111 | } 112 | 113 | stopListening() { 114 | if (this.recognition) 115 | this.listening = false; 116 | this.recognition = null; 117 | } 118 | 119 | } 120 | 121 | 122 | // function askWatson(text, callback) { 123 | // if (window.jQuery === undefined) { 124 | // console.log("i need to do ajax. import jquery before me"); 125 | // } 126 | // if (currentLanguage == 'en-IN') 127 | // $.get('/askWatson/' + encodeURIComponent(text), callback); 128 | // else if (currentLanguage == 'hi-IN') { 129 | // $.get('http://api.mymemory.translated.net/get?q=' + current_transcript + '&langpair=hi|en', function (data) { 130 | // console.log(data.responseData.translatedText); 131 | // $.get('/askWatson/' + encodeURIComponent(data.responseData.translatedText), callback); 132 | // }); 133 | // } 134 | // } 135 | 136 | -------------------------------------------------------------------------------- /js/parser.js: -------------------------------------------------------------------------------- 1 | var allowed_variable_names = [ 2 | { id: 'alpha', text: 'alpha' }, 3 | { id: 'beta', text: 'beta' }, 4 | { id: 'gamma', text: 'gamma' }, 5 | { id: 'my_variable', text: 'my variable' }, 6 | { id: 'random_number', text: 'random number' }, 7 | { id: 'x', text: 'x' }, 8 | { id: 'y', text: 'y' }, 9 | { id: 'z', text: 'z' }, 10 | { id: 'i', text: 'i' }, 11 | ] 12 | 13 | var allowed_relational_operators = [ 14 | { id: 'equal_to', text: 'equal to' }, 15 | { id: 'equal_to', text: 'equal to' }, 16 | { id: 'equal_to', text: 'equals to' }, 17 | { id: 'equal_to', text: 'equals' }, 18 | { id: 'greater_than', text: 'greater than' }, 19 | { id: 'greater_than', text: 'is greater than' }, 20 | { id: 'less_than', text: 'less than' }, 21 | { id: 'less_than', text: 'is less than' }, 22 | ] 23 | 24 | // var allowed_logical_operators = [ 'and', 'or', 'not' ] 25 | var allowed_logical_operators = [ 26 | { id: 'and', text: 'and' }, 27 | { id: 'or', text: 'or' }, 28 | { id: 'not', text: 'not' }, 29 | ] 30 | 31 | var allowed_arithmetic_operators = [ 32 | { id: 'sum', text: 'sum' }, 33 | { id: 'difference', text: 'difference' }, 34 | { id: 'product', text: 'product' }, 35 | { id: 'division', text: 'division' }, 36 | ] 37 | 38 | var allowed_numbers = [ 39 | { id: 'zero', text: 'zero' }, 40 | { id: 'one', text: 'one' }, 41 | { id: 'two', text: 'two' }, 42 | { id: 'three', text: 'three' }, 43 | { id: 'four', text: 'four' }, 44 | { id: 'five', text: 'five' }, 45 | ] 46 | 47 | var allowed_function_names = [ 48 | { id: 'fibonacci', text: 'fibonacci' }, 49 | { id: 'factorial', text: 'factorial' }, 50 | { id: 'prime_finder', text: 'prime finder' }, 51 | ] 52 | 53 | var known_commands = [ 54 | { id: 'js_move_up', text: 'javascript move up' }, 55 | { id: 'js_move_down', text: 'javascript move down' }, 56 | { id: 'js_move_left', text: 'javascript move left' }, 57 | { id: 'js_move_right', text: 'javascript move right' }, 58 | 59 | { id: 'py_move_up', text: 'python move up' }, 60 | { id: 'py_move_down', text: 'python move down' }, 61 | { id: 'py_move_left', text: 'python move left' }, 62 | { id: 'py_move_right', text: 'python move right' }, 63 | 64 | { id: 'dexter_start', text: 'dexter start' }, 65 | { id: 'dexter_stop', text: 'dexter stop' }, 66 | { id: 'dexter_javascript', text: 'dexter javascript'}, 67 | { id: 'dexter_python', text: 'dexter python'}, 68 | { id: 'dexter_full', text: 'dexter full'}, 69 | 70 | { id: 'dexter_clear', text: 'dexter clear' }, 71 | 72 | // { id: 'dexter_run', text: 'dexter run code' }, 73 | // { id: 'dexter_run', text: 'code chala do bhai' }, 74 | { id: 'dexter_run_py', text: 'arey bhai bhai bhai' }, 75 | { id: 'dexter_run_py', text: 'dexter run python' }, 76 | { id: 'dexter_run_js', text: 'dexter run javascript' }, 77 | { id: 'dexter_zulip', text: 'zulip pe bhej do' }, 78 | { id: 'dexter_zulip', text: 'dexter save' }, 79 | 80 | { id: 'dexter_undo', text: 'dexter undo' }, 81 | { id: 'dexter_redo', text: 'dexter redo'}, 82 | 83 | { id: 'dexter_add_closing_bracket', text: 'dexter add closing bracket' }, 84 | ] 85 | 86 | function IsKnownCommand(command) { 87 | for (let each of known_commands) { 88 | if (each.id == command) return true 89 | } 90 | return false 91 | } 92 | 93 | 94 | function setUpNlp() { 95 | if (window.Bravey === undefined) { 96 | throw "Bravey is not available"; 97 | } 98 | 99 | var nlp = new Bravey.Nlp.Fuzzy(); 100 | 101 | // adding intents one by one 102 | 103 | // declare_integer 104 | { 105 | nlp.addIntent('declare_integer', [ 106 | { entity: 'declare_integer_var_name', id: 'declare_integer_var_name' }, 107 | { entity: 'declare_integer_var_value', id: 'declare_integer_var_value' }, 108 | ]); 109 | 110 | let declare_integer_var_name = new Bravey.StringEntityRecognizer('declare_integer_var_name'); 111 | 112 | for (let each of allowed_variable_names) { 113 | declare_integer_var_name.addMatch(each.id, each.text) 114 | } 115 | nlp.addEntity(declare_integer_var_name); 116 | 117 | let declare_integer_var_value = new Bravey.NumberEntityRecognizer('declare_integer_var_value'); 118 | nlp.addEntity(declare_integer_var_value); 119 | 120 | // train with some examples 121 | nlp.addDocument( 122 | 'Declare an integer {declare_integer_var_name} with value {declare_integer_var_value}', 123 | 'declare_integer' 124 | ); 125 | 126 | nlp.addDocument( 127 | 'Create an integer {declare_integer_var_name} with value {declare_integer_var_value}', 128 | 'declare_integer' 129 | ); 130 | 131 | // test it 132 | showResults(nlp.test('declare an integer alpha with value 100')); 133 | // nlp.test('Declare an integer with value 100') 134 | } 135 | 136 | //create_function 137 | { 138 | nlp.addIntent('create_function', [ 139 | { entity: 'create_function_name', id: 'create_function_name' }, 140 | { entity: 'create_function_argument', id: 'create_function_argument' }, 141 | ]); 142 | // let create_function_name = new Bravey.StringEntityRecognizer('create_function_name') 143 | // create_function_name.addMatch('fibonacci', 'fibonacci') 144 | // nlp.addEntity(create_function_name) 145 | 146 | let create_function_name = new Bravey.StringEntityRecognizer('create_function_name') 147 | for (let each of allowed_function_names) { 148 | create_function_name.addMatch(each.id, each.text) 149 | } 150 | nlp.addEntity(create_function_name) 151 | 152 | let create_function_argument = new Bravey.StringEntityRecognizer('create_function_argument') 153 | for (let each of allowed_variable_names) { 154 | create_function_argument.addMatch(each.id, each.text) 155 | } 156 | 157 | nlp.addEntity(create_function_argument); 158 | 159 | nlp.addDocument( 160 | 'Create a function {create_function_name} with argument {create_function_argument}', 161 | 'create_function' 162 | ) 163 | 164 | showResults(nlp.test('create function fibonacci with argument alpha.')); 165 | } 166 | 167 | // declare_string 168 | { 169 | nlp.addIntent('declare_string', [ 170 | { entity: 'declare_string_var_name', id: 'declare_string_var_name' }, 171 | { entity: 'declare_string_var_value', id: 'declare_string_var_value' }, 172 | ]); 173 | 174 | let declare_string_var_name = new Bravey.StringEntityRecognizer('declare_string_var_name'); 175 | for (let each of allowed_variable_names) { 176 | declare_string_var_name.addMatch(each.id, each.text) 177 | } 178 | nlp.addEntity(declare_string_var_name); 179 | 180 | let declare_string_var_value = new Bravey.NumberEntityRecognizer('declare_string_var_value'); 181 | nlp.addEntity(declare_string_var_value); 182 | 183 | // train with some examples 184 | nlp.addDocument( 185 | 'Declare an string {declare_string_var_name} with value {declare_string_var_value}', 186 | 'declare_string' 187 | ); 188 | 189 | // test it 190 | showResults(nlp.test('declare an string alpha with value tomato')); 191 | // nlp.test('Declare an integer with value 100') 192 | } 193 | 194 | // create loop 195 | { 196 | nlp.addIntent('create_loop', [ 197 | { entity: 'create_loop_counts', id: 'create_loop_counts' }, 198 | ]); 199 | 200 | let create_loop_counts = new Bravey.NumberEntityRecognizer('create_loop_counts'); 201 | nlp.addEntity(create_loop_counts); 202 | 203 | // train with some examples 204 | nlp.addDocument( 205 | 'Create a loop for {create_loop_counts} counts', 206 | 'create_loop' 207 | ); 208 | 209 | // test it 210 | showResults(nlp.test('run a loop for 100 counts')); 211 | showResults(nlp.test('make a loop for 20 counts')); 212 | } 213 | 214 | // move cursor to line 215 | // { 216 | // nlp.addIntent('move_cursor_to_line', [ 217 | // { entity: 'move_cursor_to_line_number', id: 'move_cursor_to_line_number' }, 218 | // ]); 219 | 220 | // let move_cursor_to_line_number = new Bravey.NumberEntityRecognizer('move_cursor_to_line_number'); 221 | // nlp.addEntity(move_cursor_to_line_number); 222 | // // train with some examples; 223 | // nlp.addDocument( 224 | // 'Move cursor to line {move_cursor_to_line_number}', 225 | // 'move_cursor_to_line' 226 | // ); 227 | 228 | // // test it 229 | // showResults(nlp.test('move cursor to line 100')); 230 | // showResults(nlp.test('place cursor on line 343')); 231 | // } 232 | 233 | // if_else 234 | { 235 | nlp.addIntent('if_condition', [ 236 | { entity: 'if_condition_1_lhs', id: 'if_condition_1_lhs' }, 237 | { entity: 'if_condition_1_op', id: 'if_condition_1_op' }, 238 | { entity: 'if_condition_1_rhs', id: 'if_condition_1_rhs' }, 239 | 240 | { entity: 'if_condition_join_op', id: 'if_condition_join_op' }, 241 | 242 | { entity: 'if_condition_2_lhs', id: 'if_condition_2_lhs' }, 243 | { entity: 'if_condition_2_op', id: 'if_condition_2_op' }, 244 | { entity: 'if_condition_2_rhs', id: 'if_condition_2_rhs' }, 245 | ]); 246 | 247 | // for lhs, match with variable names 248 | for (let target of ['if_condition_1_lhs', 'if_condition_2_lhs']) { 249 | let variable_name = new Bravey.StringEntityRecognizer(target) 250 | for (let each of allowed_variable_names) { 251 | variable_name.addMatch(each.id, each.text) 252 | } 253 | nlp.addEntity(variable_name) 254 | } 255 | 256 | // for rhs, match with numbers 257 | for (let target of ['if_condition_1_rhs', 'if_condition_2_rhs']) { 258 | let number = new Bravey.StringEntityRecognizer(target) 259 | for (let each of allowed_numbers) { 260 | number.addMatch(each.id, each.text) 261 | } 262 | nlp.addEntity(number) 263 | } 264 | 265 | // for lhs, rhs, the relational operators 266 | for (let target of ['if_condition_1_op', 'if_condition_2_op']) { 267 | let operator = new Bravey.StringEntityRecognizer(target) 268 | for (let each of allowed_relational_operators) { 269 | operator.addMatch(each.id, each.text) 270 | } 271 | nlp.addEntity(operator) 272 | } 273 | 274 | // for the two clauses 275 | { 276 | let operator = new Bravey.StringEntityRecognizer('if_condition_join_op') 277 | for (let each of allowed_logical_operators) { 278 | operator.addMatch(each.id, each.text) 279 | } 280 | nlp.addEntity(operator) 281 | } 282 | 283 | // lets train it 284 | nlp.addDocument( 285 | 'if alpha equals one and alpha equals two', 286 | 'if_condition', 287 | { fromFullSentence: true, expandIntent: true }, 288 | ) 289 | 290 | nlp.addDocument( 291 | 'if alpha equals one or beta equals one', 292 | 'if_condition', 293 | { fromFullSentence: true, expandIntent: true }, 294 | ) 295 | 296 | nlp.addDocument( 297 | 'if alpha equals one and x equals zero', 298 | 'if_condition', 299 | { fromFullSentence: true, expandIntent: true }, 300 | ) 301 | 302 | // nlp.addDocument( 303 | // 'if with condition {if_condition_1_lhs} {if_condition_1_op} {if_condition_1_rhs} {if_condition_join_op} {if_condition_2_lhs} {if_condition_2_op} {if_condition_2_rhs}', 304 | // 'if_condition' 305 | // ) 306 | 307 | // nlp.addDocument( 308 | // 'if {if_condition_1_lhs} {if_condition_1_op} {if_condition_1_rhs}', 309 | // 'if_condition' 310 | // ) 311 | 312 | // testing some examples 313 | // showResults(nlp.test('if alpha is greater than 5')) 314 | showResults(nlp.test('if alpha equals one or beta equals two')) 315 | } 316 | 317 | // arithmetic operations 318 | { 319 | nlp.addIntent('arithmetic_operation', [ 320 | { entity: 'arithmetic_operand_1', id: 'arithmetic_operand_1' }, 321 | { entity: 'arithmetic_operand_2', id: 'arithmetic_operand_2' }, 322 | { entity: 'arithmetic_operator', id: 'arithmetic_operator' }, 323 | { entity: 'arithmetic_lhs', id: 'arithmetic_lhs' }, 324 | ]) 325 | 326 | nlp.addEntity(new Bravey.NumberEntityRecognizer('arithmetic_operand_2')) 327 | let arithmetc_operator = new Bravey.StringEntityRecognizer('arithmetic_operator') 328 | for (let each of allowed_arithmetic_operators) { 329 | arithmetc_operator.addMatch(each.id, each.text) 330 | } 331 | nlp.addEntity(arithmetc_operator) 332 | 333 | for (let target of ['arithmetic_operand_1', 'arithmetic_lhs']) { 334 | let variable_name = new Bravey.StringEntityRecognizer(target) 335 | for (let each of allowed_variable_names) { 336 | variable_name.addMatch(each.id, each.text) 337 | } 338 | nlp.addEntity(variable_name) 339 | } 340 | 341 | // train with some examples 342 | // nlp.addDocument( 343 | // '{arithmetic_operator} {arithmetic_operand_1} and {arithmetic_operand_2} and store it in {arithmetic_lhs}', 344 | // 'arithmetic_operation' 345 | // ) 346 | nlp.addDocument( 347 | 'store sum of x and 3 in alpha', 348 | 'arithmetic_operation', 349 | { fromFullSentence: true, expandIntent: true } 350 | ) 351 | 352 | nlp.addDocument( 353 | 'store product of alpha and 30 in beta', 354 | 'arithmetic_operation', 355 | { fromFullSentence: true, expandIntent: true } 356 | ) 357 | 358 | nlp.addDocument( 359 | 'store difference of gamma and 10 in x', 360 | 'arithmetic_operation', 361 | { fromFullSentence: true, expandIntent: true } 362 | ) 363 | 364 | nlp.addDocument( 365 | 'store the division of y and 8 in y', 366 | 'arithmetic_operation', 367 | { fromFullSentence: true, expandIntent: true } 368 | ) 369 | // some tests 370 | showResults(nlp.test('store the sum of z and 20 in z')) 371 | 372 | } 373 | 374 | // some custom commands 375 | 376 | for (let command of known_commands) { 377 | nlp.addDocument(command.text, command.id, { fromFullSentence: true, expandIntent: true }) 378 | } 379 | 380 | 381 | // print function 382 | { 383 | nlp.addIntent('print', [ 384 | { entity: 'argument', id: 'argument' }, 385 | { entity: 'number', id: 'number' }, 386 | ]); 387 | 388 | let argument = new Bravey.StringEntityRecognizer('argument'); 389 | for (let each of allowed_variable_names) { 390 | argument.addMatch(each.id, each.text) 391 | } 392 | nlp.addEntity(argument); 393 | 394 | nlp.addEntity(new Bravey.NumberEntityRecognizer('number')) 395 | 396 | // train with some examples 397 | nlp.addDocument( 398 | 'print {argument}', 399 | 'print' 400 | ); 401 | 402 | nlp.addDocument( 403 | 'print {number}', 404 | 'print' 405 | ) 406 | 407 | // test it 408 | showResults(nlp.test('print alpha')); 409 | showResults(nlp.test('print 100')) 410 | // nlp.test('Declare an integer with value 100') 411 | } 412 | 413 | 414 | 415 | return nlp; 416 | } 417 | 418 | function showResults(result) { 419 | if (result) { 420 | for (let entity of result.entities) { 421 | console.log(entity.id, entity.value); 422 | } 423 | } else { 424 | console.log('something failed here') 425 | } 426 | } 427 | -------------------------------------------------------------------------------- /judge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Reference 4 | # https://stackoverflow.com/a/31867499 5 | # https://docs.python.org/3/library/threading.html 6 | # https://docs.python.org/3/library/subprocess.html 7 | 8 | 9 | from subprocess import Popen, PIPE 10 | from threading import Thread 11 | import queue # Python 2 12 | 13 | def reader(pipe, q): 14 | try: 15 | for line in iter(pipe.readline, b''): 16 | q.put((pipe, line)) 17 | finally: 18 | q.put(None) 19 | 20 | 21 | def runProcess(command, timeout=10): 22 | process = Popen(command, stdout=PIPE, stderr=PIPE, bufsize=1) 23 | q = queue.Queue() 24 | outTh = Thread(target=reader, args=[process.stdout, q]) 25 | errTh = Thread(target=reader, args=[process.stderr, q]) 26 | outTh.start() 27 | errTh.start() 28 | outTh.join(timeout=timeout) 29 | errTh.join(timeout=timeout) 30 | 31 | outBuf, errBuf = b'', b'' 32 | for _ in range(2): 33 | for source, line in iter(q.get, None): 34 | # print ("%s: %s" % (source, line)) 35 | if source == process.stdout: 36 | outBuf += line 37 | elif source == process.stderr: 38 | errBuf += line 39 | 40 | return outBuf, errBuf 41 | 42 | 43 | if __name__ == '__main__': 44 | # outBuf, errBuf = runProcess(["python3", "sample.py"]) 45 | outBuf, errBuf = runProcess(["gcc", "sample.c"]) 46 | print("stdout:") 47 | print(outBuf) 48 | print() 49 | print("stderr:") 50 | print(errBuf) 51 | 52 | outBuf, errBuf = runProcess(["./a.out"]) 53 | print("stdout:") 54 | print(outBuf) 55 | print() 56 | print("stderr:") 57 | print(errBuf) 58 | -------------------------------------------------------------------------------- /lib/pane1/codemirror.css: -------------------------------------------------------------------------------- 1 | /* BASICS */ 2 | 3 | .CodeMirror { 4 | /* Set height, width, borders, and global font properties here */ 5 | font-family: 'Roboto Mono'; 6 | line-height: 1.5em; 7 | color: white; 8 | direction: ltr; 9 | } 10 | 11 | /* PADDING */ 12 | 13 | .CodeMirror-lines { 14 | padding: 0.5em 0; /* Vertical padding around content */ 15 | } 16 | .CodeMirror pre { 17 | padding: 0 1.5em; /* Horizontal padding of content */ 18 | } 19 | 20 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 21 | background-color: white; /* The little square between H and V scrollbars */ 22 | } 23 | 24 | /* GUTTER */ 25 | 26 | .CodeMirror-gutters { 27 | /* Rectangle 8: */ 28 | background: transparent; 29 | white-space: nowrap; 30 | } 31 | .CodeMirror-linenumbers {} 32 | .CodeMirror-linenumber { 33 | padding: 0 4px 0 4px; 34 | min-width: 2em; 35 | text-align: right; 36 | color: #475174; 37 | white-space: nowrap; 38 | } 39 | 40 | .CodeMirror-guttermarker { color: black; } 41 | .CodeMirror-guttermarker-subtle { color: #475174; } 42 | 43 | /* CURSOR */ 44 | 45 | .CodeMirror-cursor { 46 | border-left: 1px solid black; 47 | border-right: none; 48 | width: 0; 49 | } 50 | /* Shown when moving in bi-directional text */ 51 | .CodeMirror div.CodeMirror-secondarycursor { 52 | border-left: 1px solid silver; 53 | } 54 | .cm-fat-cursor .CodeMirror-cursor { 55 | width: auto; 56 | border: 0 !important; 57 | background: #7e7; 58 | } 59 | .cm-fat-cursor div.CodeMirror-cursors { 60 | z-index: 1; 61 | } 62 | .cm-fat-cursor-mark { 63 | background-color: rgba(20, 255, 20, 0.5); 64 | -webkit-animation: blink 1.06s steps(1) infinite; 65 | -moz-animation: blink 1.06s steps(1) infinite; 66 | animation: blink 1.06s steps(1) infinite; 67 | } 68 | .cm-animate-fat-cursor { 69 | width: auto; 70 | border: 0; 71 | -webkit-animation: blink 1.06s steps(1) infinite; 72 | -moz-animation: blink 1.06s steps(1) infinite; 73 | animation: blink 1.06s steps(1) infinite; 74 | background-color: #7e7; 75 | } 76 | @-moz-keyframes blink { 77 | 0% {} 78 | 50% { background-color: transparent; } 79 | 100% {} 80 | } 81 | @-webkit-keyframes blink { 82 | 0% {} 83 | 50% { background-color: transparent; } 84 | 100% {} 85 | } 86 | @keyframes blink { 87 | 0% {} 88 | 50% { background-color: transparent; } 89 | 100% {} 90 | } 91 | 92 | /* Can style cursor different in overwrite (non-insert) mode */ 93 | .CodeMirror-overwrite .CodeMirror-cursor {} 94 | 95 | .cm-tab { display: inline-block; text-decoration: inherit; } 96 | 97 | .CodeMirror-rulers { 98 | position: absolute; 99 | left: 0; right: 0; top: -50px; bottom: -20px; 100 | overflow: hidden; 101 | } 102 | .CodeMirror-ruler { 103 | border-left: 1px solid #ccc; 104 | top: 0; bottom: 0; 105 | position: absolute; 106 | } 107 | 108 | /* DEFAULT THEME */ 109 | 110 | .cm-s-default .cm-header {color: blue;} 111 | .cm-s-default .cm-quote {color: #090;} 112 | .cm-negative {color: #FF2759;} 113 | .cm-positive {color: #42A15E;} 114 | .cm-header, .cm-strong {font-weight: bold;} 115 | .cm-em {font-style: italic;} 116 | .cm-link {text-decoration: underline;} 117 | .cm-strikethrough {text-decoration: line-through;} 118 | 119 | .cm-s-default .cm-keyword {color: #FF309D;} 120 | .cm-s-default .cm-atom {color: #00C1F9;} 121 | .cm-s-default .cm-number {color: white;} 122 | .cm-s-default .cm-def {color: #00B2F7;} 123 | .cm-s-default .cm-variable, 124 | .cm-s-default .cm-punctuation, 125 | .cm-s-default .cm-property, 126 | .cm-s-default .cm-operator {color: } 127 | .cm-s-default .cm-variable-2 {color: #0669A8;} 128 | .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #42A15E;} 129 | .cm-s-default .cm-comment {color: #5762B9;} 130 | .cm-s-default .cm-string {color: #a11;} 131 | .cm-s-default .cm-string-2 {color: #f50;} 132 | .cm-s-default .cm-meta {color: #555;} 133 | .cm-s-default .cm-qualifier {color: #555;} 134 | .cm-s-default .cm-builtin {color: #FF2759;} 135 | .cm-s-default .cm-bracket {color: #997;} 136 | .cm-s-default .cm-tag {color: #170;} 137 | .cm-s-default .cm-attribute {color: #00c;} 138 | .cm-s-default .cm-hr {color: #999;} 139 | .cm-s-default .cm-link {color: #00c;} 140 | 141 | .cm-s-default .cm-error {color: #FF2759;} 142 | .cm-invalidchar {color: #FF2759;} 143 | 144 | .CodeMirror-composing { border-bottom: 2px solid; } 145 | 146 | /* Default styles for common addons */ 147 | 148 | div.CodeMirror span.CodeMirror-matchingbracket {color: #00FFFF;} 149 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} 150 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } 151 | .CodeMirror-activeline-background {background: #e8f2ff;} 152 | 153 | /* STOP */ 154 | 155 | /* The rest of this file contains styles related to the mechanics of 156 | the editor. You probably shouldn't touch them. */ 157 | 158 | .CodeMirror { 159 | position: relative; 160 | overflow: hidden; 161 | /* Rectangle 8: */ 162 | background: transparent; 163 | } 164 | 165 | .CodeMirror-scroll { 166 | overflow: scroll !important; /* Things will break if this is overridden */ 167 | /* 30px is the magic margin used to hide the element's real scrollbars */ 168 | /* See overflow: hidden in .CodeMirror */ 169 | margin-bottom: -30px; margin-right: -30px; 170 | padding-bottom: 30px; 171 | height: 100%; 172 | outline: none; /* Prevent dragging from highlighting the element */ 173 | position: relative; 174 | } 175 | .CodeMirror-sizer { 176 | position: relative; 177 | border-right: 30px solid transparent; 178 | } 179 | 180 | /* The fake, visible scrollbars. Used to force redraw during scrolling 181 | before actual scrolling happens, thus preventing shaking and 182 | flickering artifacts. */ 183 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 184 | position: absolute; 185 | z-index: 6; 186 | display: none; 187 | } 188 | .CodeMirror-vscrollbar { 189 | right: 0; top: 0; 190 | overflow-x: hidden; 191 | overflow-y: scroll; 192 | } 193 | .CodeMirror-hscrollbar { 194 | bottom: 0; left: 0; 195 | overflow-y: hidden; 196 | overflow-x: scroll; 197 | } 198 | .CodeMirror-scrollbar-filler { 199 | right: 0; bottom: 0; 200 | } 201 | .CodeMirror-gutter-filler { 202 | left: 0; bottom: 0; 203 | } 204 | 205 | .CodeMirror-gutters { 206 | position: absolute; left: 0; top: 0; 207 | min-height: 100%; 208 | z-index: 3; 209 | } 210 | .CodeMirror-gutter { 211 | white-space: normal; 212 | height: 100%; 213 | display: inline-block; 214 | vertical-align: top; 215 | margin-bottom: -30px; 216 | } 217 | .CodeMirror-gutter-wrapper { 218 | position: absolute; 219 | z-index: 4; 220 | background: none !important; 221 | border: none !important; 222 | } 223 | .CodeMirror-gutter-background { 224 | position: absolute; 225 | top: 0; bottom: 0; 226 | z-index: 4; 227 | } 228 | .CodeMirror-gutter-elt { 229 | position: absolute; 230 | cursor: default; 231 | z-index: 4; 232 | } 233 | .CodeMirror-gutter-wrapper ::selection { background-color: transparent } 234 | .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } 235 | 236 | .CodeMirror-lines { 237 | cursor: text; 238 | min-height: 1px; /* prevents collapsing before first draw */ 239 | } 240 | .CodeMirror pre { 241 | /* Reset some styles that the rest of the page might have set */ 242 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; 243 | border-width: 0; 244 | background: transparent; 245 | font-family: inherit; 246 | font-size: inherit; 247 | margin: 0; 248 | white-space: pre; 249 | word-wrap: normal; 250 | line-height: inherit; 251 | color: inherit; 252 | z-index: 2; 253 | position: relative; 254 | overflow: visible; 255 | -webkit-tap-highlight-color: transparent; 256 | -webkit-font-variant-ligatures: contextual; 257 | font-variant-ligatures: contextual; 258 | } 259 | .CodeMirror-wrap pre { 260 | word-wrap: break-word; 261 | white-space: pre-wrap; 262 | word-break: normal; 263 | } 264 | 265 | .CodeMirror-linebackground { 266 | position: absolute; 267 | left: 0; right: 0; top: 0; bottom: 0; 268 | z-index: 0; 269 | } 270 | 271 | .CodeMirror-linewidget { 272 | position: relative; 273 | z-index: 2; 274 | padding: 0.1px; /* Force widget margins to stay inside of the container */ 275 | } 276 | 277 | .CodeMirror-widget {} 278 | 279 | .CodeMirror-rtl pre { direction: rtl; } 280 | 281 | .CodeMirror-code { 282 | outline: none; 283 | } 284 | 285 | /* Force content-box sizing for the elements where we expect it */ 286 | .CodeMirror-scroll, 287 | .CodeMirror-sizer, 288 | .CodeMirror-gutter, 289 | .CodeMirror-gutters, 290 | .CodeMirror-linenumber { 291 | -moz-box-sizing: content-box; 292 | box-sizing: content-box; 293 | } 294 | 295 | .CodeMirror-measure { 296 | position: absolute; 297 | width: 100%; 298 | height: 0; 299 | overflow: hidden; 300 | visibility: hidden; 301 | } 302 | 303 | .CodeMirror-cursor { 304 | position: absolute; 305 | pointer-events: none; 306 | } 307 | .CodeMirror-measure pre { position: static; } 308 | 309 | div.CodeMirror-cursors { 310 | visibility: hidden; 311 | position: relative; 312 | z-index: 3; 313 | } 314 | div.CodeMirror-dragcursors { 315 | visibility: visible; 316 | } 317 | 318 | .CodeMirror-focused div.CodeMirror-cursors { 319 | visibility: visible; 320 | } 321 | 322 | .CodeMirror-selected { background: #d9d9d9; } 323 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 324 | .CodeMirror-crosshair { cursor: crosshair; } 325 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } 326 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } 327 | 328 | .cm-searching { 329 | background-color: #ffa; 330 | background-color: rgba(255, 255, 0, .4); 331 | } 332 | 333 | /* Used to force a border model for a node */ 334 | .cm-force-border { padding-right: .1px; } 335 | 336 | @media print { 337 | /* Hide the cursor when printing */ 338 | .CodeMirror div.CodeMirror-cursors { 339 | visibility: hidden; 340 | } 341 | } 342 | 343 | /* See issue #2901 */ 344 | .cm-tab-wrap-hack:after { content: ''; } 345 | 346 | /* Help users use markselection to safely style text background */ 347 | span.CodeMirror-selectedtext { background: none; } 348 | -------------------------------------------------------------------------------- /lib/pane1/dialog.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-dialog { 2 | position: absolute; 3 | left: 0; right: 0; 4 | background: inherit; 5 | z-index: 15; 6 | padding: .1em .8em; 7 | overflow: hidden; 8 | color: inherit; 9 | } 10 | 11 | .CodeMirror-dialog-top { 12 | border-bottom: 1px solid #eee; 13 | top: 0; 14 | } 15 | 16 | .CodeMirror-dialog-bottom { 17 | border-top: 1px solid #eee; 18 | bottom: 0; 19 | } 20 | 21 | .CodeMirror-dialog input { 22 | border: none; 23 | outline: none; 24 | background: transparent; 25 | width: 20em; 26 | color: inherit; 27 | font-family: monospace; 28 | } 29 | 30 | .CodeMirror-dialog button { 31 | font-size: 70%; 32 | } 33 | -------------------------------------------------------------------------------- /lib/pane1/dialog.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | // Open simple dialogs on top of an editor. Relies on dialog.css. 5 | 6 | (function(mod) { 7 | if (typeof exports == "object" && typeof module == "object") // CommonJS 8 | mod(require("../../lib/codemirror")); 9 | else if (typeof define == "function" && define.amd) // AMD 10 | define(["../../lib/codemirror"], mod); 11 | else // Plain browser env 12 | mod(CodeMirror); 13 | })(function(CodeMirror) { 14 | function dialogDiv(cm, template, bottom) { 15 | var wrap = cm.getWrapperElement(); 16 | var dialog; 17 | dialog = wrap.appendChild(document.createElement("div")); 18 | if (bottom) 19 | dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; 20 | else 21 | dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; 22 | 23 | if (typeof template == "string") { 24 | dialog.innerHTML = template; 25 | } else { // Assuming it's a detached DOM element. 26 | dialog.appendChild(template); 27 | } 28 | return dialog; 29 | } 30 | 31 | function closeNotification(cm, newVal) { 32 | if (cm.state.currentNotificationClose) 33 | cm.state.currentNotificationClose(); 34 | cm.state.currentNotificationClose = newVal; 35 | } 36 | 37 | CodeMirror.defineExtension("openDialog", function(template, callback, options) { 38 | if (!options) options = {}; 39 | 40 | closeNotification(this, null); 41 | 42 | var dialog = dialogDiv(this, template, options.bottom); 43 | var closed = false, me = this; 44 | function close(newVal) { 45 | if (typeof newVal == 'string') { 46 | inp.value = newVal; 47 | } else { 48 | if (closed) return; 49 | closed = true; 50 | dialog.parentNode.removeChild(dialog); 51 | me.focus(); 52 | 53 | if (options.onClose) options.onClose(dialog); 54 | } 55 | } 56 | 57 | var inp = dialog.getElementsByTagName("input")[0], button; 58 | if (inp) { 59 | inp.focus(); 60 | 61 | if (options.value) { 62 | inp.value = options.value; 63 | if (options.selectValueOnOpen !== false) { 64 | inp.select(); 65 | } 66 | } 67 | 68 | if (options.onInput) 69 | CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); 70 | if (options.onKeyUp) 71 | CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); 72 | 73 | CodeMirror.on(inp, "keydown", function(e) { 74 | if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } 75 | if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { 76 | inp.blur(); 77 | CodeMirror.e_stop(e); 78 | close(); 79 | } 80 | if (e.keyCode == 13) callback(inp.value, e); 81 | }); 82 | 83 | if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); 84 | } else if (button = dialog.getElementsByTagName("button")[0]) { 85 | CodeMirror.on(button, "click", function() { 86 | close(); 87 | me.focus(); 88 | }); 89 | 90 | if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); 91 | 92 | button.focus(); 93 | } 94 | return close; 95 | }); 96 | 97 | CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { 98 | closeNotification(this, null); 99 | var dialog = dialogDiv(this, template, options && options.bottom); 100 | var buttons = dialog.getElementsByTagName("button"); 101 | var closed = false, me = this, blurring = 1; 102 | function close() { 103 | if (closed) return; 104 | closed = true; 105 | dialog.parentNode.removeChild(dialog); 106 | me.focus(); 107 | } 108 | buttons[0].focus(); 109 | for (var i = 0; i < buttons.length; ++i) { 110 | var b = buttons[i]; 111 | (function(callback) { 112 | CodeMirror.on(b, "click", function(e) { 113 | CodeMirror.e_preventDefault(e); 114 | close(); 115 | if (callback) callback(me); 116 | }); 117 | })(callbacks[i]); 118 | CodeMirror.on(b, "blur", function() { 119 | --blurring; 120 | setTimeout(function() { if (blurring <= 0) close(); }, 200); 121 | }); 122 | CodeMirror.on(b, "focus", function() { ++blurring; }); 123 | } 124 | }); 125 | 126 | /* 127 | * openNotification 128 | * Opens a notification, that can be closed with an optional timer 129 | * (default 5000ms timer) and always closes on click. 130 | * 131 | * If a notification is opened while another is opened, it will close the 132 | * currently opened one and open the new one immediately. 133 | */ 134 | CodeMirror.defineExtension("openNotification", function(template, options) { 135 | closeNotification(this, close); 136 | var dialog = dialogDiv(this, template, options && options.bottom); 137 | var closed = false, doneTimer; 138 | var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; 139 | 140 | function close() { 141 | if (closed) return; 142 | closed = true; 143 | clearTimeout(doneTimer); 144 | dialog.parentNode.removeChild(dialog); 145 | } 146 | 147 | CodeMirror.on(dialog, 'click', function(e) { 148 | CodeMirror.e_preventDefault(e); 149 | close(); 150 | }); 151 | 152 | if (duration) 153 | doneTimer = setTimeout(close, duration); 154 | 155 | return close; 156 | }); 157 | }); 158 | -------------------------------------------------------------------------------- /lib/pane1/javascript.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.defineMode("javascript", function(config, parserConfig) { 15 | var indentUnit = config.indentUnit; 16 | var statementIndent = parserConfig.statementIndent; 17 | var jsonldMode = parserConfig.jsonld; 18 | var jsonMode = parserConfig.json || jsonldMode; 19 | var isTS = parserConfig.typescript; 20 | var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; 21 | 22 | // Tokenizer 23 | 24 | var keywords = function(){ 25 | function kw(type) {return {type: type, style: "keyword"};} 26 | var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d"); 27 | var operator = kw("operator"), atom = {type: "atom", style: "atom"}; 28 | 29 | return { 30 | "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, 31 | "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C, 32 | "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"), 33 | "function": kw("function"), "catch": kw("catch"), 34 | "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), 35 | "in": operator, "typeof": operator, "instanceof": operator, 36 | "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, 37 | "this": kw("this"), "class": kw("class"), "super": kw("atom"), 38 | "yield": C, "export": kw("export"), "import": kw("import"), "extends": C, 39 | "await": C 40 | }; 41 | }(); 42 | 43 | var isOperatorChar = /[+\-*&%=<>!?|~^@]/; 44 | var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; 45 | 46 | function readRegexp(stream) { 47 | var escaped = false, next, inSet = false; 48 | while ((next = stream.next()) != null) { 49 | if (!escaped) { 50 | if (next == "/" && !inSet) return; 51 | if (next == "[") inSet = true; 52 | else if (inSet && next == "]") inSet = false; 53 | } 54 | escaped = !escaped && next == "\\"; 55 | } 56 | } 57 | 58 | // Used as scratch variables to communicate multiple values without 59 | // consing up tons of objects. 60 | var type, content; 61 | function ret(tp, style, cont) { 62 | type = tp; content = cont; 63 | return style; 64 | } 65 | function tokenBase(stream, state) { 66 | var ch = stream.next(); 67 | if (ch == '"' || ch == "'") { 68 | state.tokenize = tokenString(ch); 69 | return state.tokenize(stream, state); 70 | } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { 71 | return ret("number", "number"); 72 | } else if (ch == "." && stream.match("..")) { 73 | return ret("spread", "meta"); 74 | } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { 75 | return ret(ch); 76 | } else if (ch == "=" && stream.eat(">")) { 77 | return ret("=>", "operator"); 78 | } else if (ch == "0" && stream.eat(/x/i)) { 79 | stream.eatWhile(/[\da-f]/i); 80 | return ret("number", "number"); 81 | } else if (ch == "0" && stream.eat(/o/i)) { 82 | stream.eatWhile(/[0-7]/i); 83 | return ret("number", "number"); 84 | } else if (ch == "0" && stream.eat(/b/i)) { 85 | stream.eatWhile(/[01]/i); 86 | return ret("number", "number"); 87 | } else if (/\d/.test(ch)) { 88 | stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); 89 | return ret("number", "number"); 90 | } else if (ch == "/") { 91 | if (stream.eat("*")) { 92 | state.tokenize = tokenComment; 93 | return tokenComment(stream, state); 94 | } else if (stream.eat("/")) { 95 | stream.skipToEnd(); 96 | return ret("comment", "comment"); 97 | } else if (expressionAllowed(stream, state, 1)) { 98 | readRegexp(stream); 99 | stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); 100 | return ret("regexp", "string-2"); 101 | } else { 102 | stream.eat("="); 103 | return ret("operator", "operator", stream.current()); 104 | } 105 | } else if (ch == "`") { 106 | state.tokenize = tokenQuasi; 107 | return tokenQuasi(stream, state); 108 | } else if (ch == "#") { 109 | stream.skipToEnd(); 110 | return ret("error", "error"); 111 | } else if (isOperatorChar.test(ch)) { 112 | if (ch != ">" || !state.lexical || state.lexical.type != ">") { 113 | if (stream.eat("=")) { 114 | if (ch == "!" || ch == "=") stream.eat("=") 115 | } else if (/[<>*+\-]/.test(ch)) { 116 | stream.eat(ch) 117 | if (ch == ">") stream.eat(ch) 118 | } 119 | } 120 | return ret("operator", "operator", stream.current()); 121 | } else if (wordRE.test(ch)) { 122 | stream.eatWhile(wordRE); 123 | var word = stream.current() 124 | if (state.lastType != ".") { 125 | if (keywords.propertyIsEnumerable(word)) { 126 | var kw = keywords[word] 127 | return ret(kw.type, kw.style, word) 128 | } 129 | if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\(\w]/, false)) 130 | return ret("async", "keyword", word) 131 | } 132 | return ret("variable", "variable", word) 133 | } 134 | } 135 | 136 | function tokenString(quote) { 137 | return function(stream, state) { 138 | var escaped = false, next; 139 | if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ 140 | state.tokenize = tokenBase; 141 | return ret("jsonld-keyword", "meta"); 142 | } 143 | while ((next = stream.next()) != null) { 144 | if (next == quote && !escaped) break; 145 | escaped = !escaped && next == "\\"; 146 | } 147 | if (!escaped) state.tokenize = tokenBase; 148 | return ret("string", "string"); 149 | }; 150 | } 151 | 152 | function tokenComment(stream, state) { 153 | var maybeEnd = false, ch; 154 | while (ch = stream.next()) { 155 | if (ch == "/" && maybeEnd) { 156 | state.tokenize = tokenBase; 157 | break; 158 | } 159 | maybeEnd = (ch == "*"); 160 | } 161 | return ret("comment", "comment"); 162 | } 163 | 164 | function tokenQuasi(stream, state) { 165 | var escaped = false, next; 166 | while ((next = stream.next()) != null) { 167 | if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { 168 | state.tokenize = tokenBase; 169 | break; 170 | } 171 | escaped = !escaped && next == "\\"; 172 | } 173 | return ret("quasi", "string-2", stream.current()); 174 | } 175 | 176 | var brackets = "([{}])"; 177 | // This is a crude lookahead trick to try and notice that we're 178 | // parsing the argument patterns for a fat-arrow function before we 179 | // actually hit the arrow token. It only works if the arrow is on 180 | // the same line as the arguments and there's no strange noise 181 | // (comments) in between. Fallback is to only notice when we hit the 182 | // arrow, and not declare the arguments as locals for the arrow 183 | // body. 184 | function findFatArrow(stream, state) { 185 | if (state.fatArrowAt) state.fatArrowAt = null; 186 | var arrow = stream.string.indexOf("=>", stream.start); 187 | if (arrow < 0) return; 188 | 189 | if (isTS) { // Try to skip TypeScript return type declarations after the arguments 190 | var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow)) 191 | if (m) arrow = m.index 192 | } 193 | 194 | var depth = 0, sawSomething = false; 195 | for (var pos = arrow - 1; pos >= 0; --pos) { 196 | var ch = stream.string.charAt(pos); 197 | var bracket = brackets.indexOf(ch); 198 | if (bracket >= 0 && bracket < 3) { 199 | if (!depth) { ++pos; break; } 200 | if (--depth == 0) { if (ch == "(") sawSomething = true; break; } 201 | } else if (bracket >= 3 && bracket < 6) { 202 | ++depth; 203 | } else if (wordRE.test(ch)) { 204 | sawSomething = true; 205 | } else if (/["'\/]/.test(ch)) { 206 | return; 207 | } else if (sawSomething && !depth) { 208 | ++pos; 209 | break; 210 | } 211 | } 212 | if (sawSomething && !depth) state.fatArrowAt = pos; 213 | } 214 | 215 | // Parser 216 | 217 | var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; 218 | 219 | function JSLexical(indented, column, type, align, prev, info) { 220 | this.indented = indented; 221 | this.column = column; 222 | this.type = type; 223 | this.prev = prev; 224 | this.info = info; 225 | if (align != null) this.align = align; 226 | } 227 | 228 | function inScope(state, varname) { 229 | for (var v = state.localVars; v; v = v.next) 230 | if (v.name == varname) return true; 231 | for (var cx = state.context; cx; cx = cx.prev) { 232 | for (var v = cx.vars; v; v = v.next) 233 | if (v.name == varname) return true; 234 | } 235 | } 236 | 237 | function parseJS(state, style, type, content, stream) { 238 | var cc = state.cc; 239 | // Communicate our context to the combinators. 240 | // (Less wasteful than consing up a hundred closures on every call.) 241 | cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; 242 | 243 | if (!state.lexical.hasOwnProperty("align")) 244 | state.lexical.align = true; 245 | 246 | while(true) { 247 | var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; 248 | if (combinator(type, content)) { 249 | while(cc.length && cc[cc.length - 1].lex) 250 | cc.pop()(); 251 | if (cx.marked) return cx.marked; 252 | if (type == "variable" && inScope(state, content)) return "variable-2"; 253 | return style; 254 | } 255 | } 256 | } 257 | 258 | // Combinator utils 259 | 260 | var cx = {state: null, column: null, marked: null, cc: null}; 261 | function pass() { 262 | for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); 263 | } 264 | function cont() { 265 | pass.apply(null, arguments); 266 | return true; 267 | } 268 | function register(varname) { 269 | function inList(list) { 270 | for (var v = list; v; v = v.next) 271 | if (v.name == varname) return true; 272 | return false; 273 | } 274 | var state = cx.state; 275 | cx.marked = "def"; 276 | if (state.context) { 277 | if (inList(state.localVars)) return; 278 | state.localVars = {name: varname, next: state.localVars}; 279 | } else { 280 | if (inList(state.globalVars)) return; 281 | if (parserConfig.globalVars) 282 | state.globalVars = {name: varname, next: state.globalVars}; 283 | } 284 | } 285 | 286 | function isModifier(name) { 287 | return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly" 288 | } 289 | 290 | // Combinators 291 | 292 | var defaultVars = {name: "this", next: {name: "arguments"}}; 293 | function pushcontext() { 294 | cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; 295 | cx.state.localVars = defaultVars; 296 | } 297 | function popcontext() { 298 | cx.state.localVars = cx.state.context.vars; 299 | cx.state.context = cx.state.context.prev; 300 | } 301 | function pushlex(type, info) { 302 | var result = function() { 303 | var state = cx.state, indent = state.indented; 304 | if (state.lexical.type == "stat") indent = state.lexical.indented; 305 | else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) 306 | indent = outer.indented; 307 | state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); 308 | }; 309 | result.lex = true; 310 | return result; 311 | } 312 | function poplex() { 313 | var state = cx.state; 314 | if (state.lexical.prev) { 315 | if (state.lexical.type == ")") 316 | state.indented = state.lexical.indented; 317 | state.lexical = state.lexical.prev; 318 | } 319 | } 320 | poplex.lex = true; 321 | 322 | function expect(wanted) { 323 | function exp(type) { 324 | if (type == wanted) return cont(); 325 | else if (wanted == ";") return pass(); 326 | else return cont(exp); 327 | }; 328 | return exp; 329 | } 330 | 331 | function statement(type, value) { 332 | if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); 333 | if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); 334 | if (type == "keyword b") return cont(pushlex("form"), statement, poplex); 335 | if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex); 336 | if (type == "debugger") return cont(expect(";")); 337 | if (type == "{") return cont(pushlex("}"), block, poplex); 338 | if (type == ";") return cont(); 339 | if (type == "if") { 340 | if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) 341 | cx.state.cc.pop()(); 342 | return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); 343 | } 344 | if (type == "function") return cont(functiondef); 345 | if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); 346 | if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), className, poplex); } 347 | if (type == "variable") { 348 | if (isTS && value == "type") { 349 | cx.marked = "keyword" 350 | return cont(typeexpr, expect("operator"), typeexpr, expect(";")); 351 | } else if (isTS && value == "declare") { 352 | cx.marked = "keyword" 353 | return cont(statement) 354 | } else if (isTS && (value == "module" || value == "enum") && cx.stream.match(/^\s*\w/, false)) { 355 | cx.marked = "keyword" 356 | return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex) 357 | } else if (isTS && value == "namespace") { 358 | cx.marked = "keyword" 359 | return cont(pushlex("form"), expression, block, poplex) 360 | } else { 361 | return cont(pushlex("stat"), maybelabel); 362 | } 363 | } 364 | if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), 365 | block, poplex, poplex); 366 | if (type == "case") return cont(expression, expect(":")); 367 | if (type == "default") return cont(expect(":")); 368 | if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), 369 | statement, poplex, popcontext); 370 | if (type == "export") return cont(pushlex("stat"), afterExport, poplex); 371 | if (type == "import") return cont(pushlex("stat"), afterImport, poplex); 372 | if (type == "async") return cont(statement) 373 | if (value == "@") return cont(expression, statement) 374 | return pass(pushlex("stat"), expression, expect(";"), poplex); 375 | } 376 | function expression(type, value) { 377 | return expressionInner(type, value, false); 378 | } 379 | function expressionNoComma(type, value) { 380 | return expressionInner(type, value, true); 381 | } 382 | function parenExpr(type) { 383 | if (type != "(") return pass() 384 | return cont(pushlex(")"), expression, expect(")"), poplex) 385 | } 386 | function expressionInner(type, value, noComma) { 387 | if (cx.state.fatArrowAt == cx.stream.start) { 388 | var body = noComma ? arrowBodyNoComma : arrowBody; 389 | if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext); 390 | else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); 391 | } 392 | 393 | var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; 394 | if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); 395 | if (type == "function") return cont(functiondef, maybeop); 396 | if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); } 397 | if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression); 398 | if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); 399 | if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); 400 | if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); 401 | if (type == "{") return contCommasep(objprop, "}", null, maybeop); 402 | if (type == "quasi") return pass(quasi, maybeop); 403 | if (type == "new") return cont(maybeTarget(noComma)); 404 | return cont(); 405 | } 406 | function maybeexpression(type) { 407 | if (type.match(/[;\}\)\],]/)) return pass(); 408 | return pass(expression); 409 | } 410 | 411 | function maybeoperatorComma(type, value) { 412 | if (type == ",") return cont(expression); 413 | return maybeoperatorNoComma(type, value, false); 414 | } 415 | function maybeoperatorNoComma(type, value, noComma) { 416 | var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; 417 | var expr = noComma == false ? expression : expressionNoComma; 418 | if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); 419 | if (type == "operator") { 420 | if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me); 421 | if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false)) 422 | return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me); 423 | if (value == "?") return cont(expression, expect(":"), expr); 424 | return cont(expr); 425 | } 426 | if (type == "quasi") { return pass(quasi, me); } 427 | if (type == ";") return; 428 | if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); 429 | if (type == ".") return cont(property, me); 430 | if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); 431 | if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) } 432 | if (type == "regexp") { 433 | cx.state.lastType = cx.marked = "operator" 434 | cx.stream.backUp(cx.stream.pos - cx.stream.start - 1) 435 | return cont(expr) 436 | } 437 | } 438 | function quasi(type, value) { 439 | if (type != "quasi") return pass(); 440 | if (value.slice(value.length - 2) != "${") return cont(quasi); 441 | return cont(expression, continueQuasi); 442 | } 443 | function continueQuasi(type) { 444 | if (type == "}") { 445 | cx.marked = "string-2"; 446 | cx.state.tokenize = tokenQuasi; 447 | return cont(quasi); 448 | } 449 | } 450 | function arrowBody(type) { 451 | findFatArrow(cx.stream, cx.state); 452 | return pass(type == "{" ? statement : expression); 453 | } 454 | function arrowBodyNoComma(type) { 455 | findFatArrow(cx.stream, cx.state); 456 | return pass(type == "{" ? statement : expressionNoComma); 457 | } 458 | function maybeTarget(noComma) { 459 | return function(type) { 460 | if (type == ".") return cont(noComma ? targetNoComma : target); 461 | else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma) 462 | else return pass(noComma ? expressionNoComma : expression); 463 | }; 464 | } 465 | function target(_, value) { 466 | if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); } 467 | } 468 | function targetNoComma(_, value) { 469 | if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); } 470 | } 471 | function maybelabel(type) { 472 | if (type == ":") return cont(poplex, statement); 473 | return pass(maybeoperatorComma, expect(";"), poplex); 474 | } 475 | function property(type) { 476 | if (type == "variable") {cx.marked = "property"; return cont();} 477 | } 478 | function objprop(type, value) { 479 | if (type == "async") { 480 | cx.marked = "property"; 481 | return cont(objprop); 482 | } else if (type == "variable" || cx.style == "keyword") { 483 | cx.marked = "property"; 484 | if (value == "get" || value == "set") return cont(getterSetter); 485 | var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params 486 | if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) 487 | cx.state.fatArrowAt = cx.stream.pos + m[0].length 488 | return cont(afterprop); 489 | } else if (type == "number" || type == "string") { 490 | cx.marked = jsonldMode ? "property" : (cx.style + " property"); 491 | return cont(afterprop); 492 | } else if (type == "jsonld-keyword") { 493 | return cont(afterprop); 494 | } else if (isTS && isModifier(value)) { 495 | cx.marked = "keyword" 496 | return cont(objprop) 497 | } else if (type == "[") { 498 | return cont(expression, maybetype, expect("]"), afterprop); 499 | } else if (type == "spread") { 500 | return cont(expressionNoComma, afterprop); 501 | } else if (value == "*") { 502 | cx.marked = "keyword"; 503 | return cont(objprop); 504 | } else if (type == ":") { 505 | return pass(afterprop) 506 | } 507 | } 508 | function getterSetter(type) { 509 | if (type != "variable") return pass(afterprop); 510 | cx.marked = "property"; 511 | return cont(functiondef); 512 | } 513 | function afterprop(type) { 514 | if (type == ":") return cont(expressionNoComma); 515 | if (type == "(") return pass(functiondef); 516 | } 517 | function commasep(what, end, sep) { 518 | function proceed(type, value) { 519 | if (sep ? sep.indexOf(type) > -1 : type == ",") { 520 | var lex = cx.state.lexical; 521 | if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; 522 | return cont(function(type, value) { 523 | if (type == end || value == end) return pass() 524 | return pass(what) 525 | }, proceed); 526 | } 527 | if (type == end || value == end) return cont(); 528 | return cont(expect(end)); 529 | } 530 | return function(type, value) { 531 | if (type == end || value == end) return cont(); 532 | return pass(what, proceed); 533 | }; 534 | } 535 | function contCommasep(what, end, info) { 536 | for (var i = 3; i < arguments.length; i++) 537 | cx.cc.push(arguments[i]); 538 | return cont(pushlex(end, info), commasep(what, end), poplex); 539 | } 540 | function block(type) { 541 | if (type == "}") return cont(); 542 | return pass(statement, block); 543 | } 544 | function maybetype(type, value) { 545 | if (isTS) { 546 | if (type == ":") return cont(typeexpr); 547 | if (value == "?") return cont(maybetype); 548 | } 549 | } 550 | function mayberettype(type) { 551 | if (isTS && type == ":") { 552 | if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr) 553 | else return cont(typeexpr) 554 | } 555 | } 556 | function isKW(_, value) { 557 | if (value == "is") { 558 | cx.marked = "keyword" 559 | return cont() 560 | } 561 | } 562 | function typeexpr(type, value) { 563 | if (type == "variable" || value == "void") { 564 | if (value == "keyof") { 565 | cx.marked = "keyword" 566 | return cont(typeexpr) 567 | } else { 568 | cx.marked = "type" 569 | return cont(afterType) 570 | } 571 | } 572 | if (type == "string" || type == "number" || type == "atom") return cont(afterType); 573 | if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType) 574 | if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) 575 | if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) 576 | } 577 | function maybeReturnType(type) { 578 | if (type == "=>") return cont(typeexpr) 579 | } 580 | function typeprop(type, value) { 581 | if (type == "variable" || cx.style == "keyword") { 582 | cx.marked = "property" 583 | return cont(typeprop) 584 | } else if (value == "?") { 585 | return cont(typeprop) 586 | } else if (type == ":") { 587 | return cont(typeexpr) 588 | } else if (type == "[") { 589 | return cont(expression, maybetype, expect("]"), typeprop) 590 | } 591 | } 592 | function typearg(type) { 593 | if (type == "variable") return cont(typearg) 594 | else if (type == ":") return cont(typeexpr) 595 | } 596 | function afterType(type, value) { 597 | if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) 598 | if (value == "|" || type == ".") return cont(typeexpr) 599 | if (type == "[") return cont(expect("]"), afterType) 600 | if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) } 601 | } 602 | function maybeTypeArgs(_, value) { 603 | if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) 604 | } 605 | function typeparam() { 606 | return pass(typeexpr, maybeTypeDefault) 607 | } 608 | function maybeTypeDefault(_, value) { 609 | if (value == "=") return cont(typeexpr) 610 | } 611 | function vardef() { 612 | return pass(pattern, maybetype, maybeAssign, vardefCont); 613 | } 614 | function pattern(type, value) { 615 | if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) } 616 | if (type == "variable") { register(value); return cont(); } 617 | if (type == "spread") return cont(pattern); 618 | if (type == "[") return contCommasep(pattern, "]"); 619 | if (type == "{") return contCommasep(proppattern, "}"); 620 | } 621 | function proppattern(type, value) { 622 | if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { 623 | register(value); 624 | return cont(maybeAssign); 625 | } 626 | if (type == "variable") cx.marked = "property"; 627 | if (type == "spread") return cont(pattern); 628 | if (type == "}") return pass(); 629 | return cont(expect(":"), pattern, maybeAssign); 630 | } 631 | function maybeAssign(_type, value) { 632 | if (value == "=") return cont(expressionNoComma); 633 | } 634 | function vardefCont(type) { 635 | if (type == ",") return cont(vardef); 636 | } 637 | function maybeelse(type, value) { 638 | if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); 639 | } 640 | function forspec(type) { 641 | if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); 642 | } 643 | function forspec1(type) { 644 | if (type == "var") return cont(vardef, expect(";"), forspec2); 645 | if (type == ";") return cont(forspec2); 646 | if (type == "variable") return cont(formaybeinof); 647 | return pass(expression, expect(";"), forspec2); 648 | } 649 | function formaybeinof(_type, value) { 650 | if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } 651 | return cont(maybeoperatorComma, forspec2); 652 | } 653 | function forspec2(type, value) { 654 | if (type == ";") return cont(forspec3); 655 | if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } 656 | return pass(expression, expect(";"), forspec3); 657 | } 658 | function forspec3(type) { 659 | if (type != ")") cont(expression); 660 | } 661 | function functiondef(type, value) { 662 | if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} 663 | if (type == "variable") {register(value); return cont(functiondef);} 664 | if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext); 665 | if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef) 666 | } 667 | function funarg(type, value) { 668 | if (value == "@") cont(expression, funarg) 669 | if (type == "spread") return cont(funarg); 670 | if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); } 671 | return pass(pattern, maybetype, maybeAssign); 672 | } 673 | function classExpression(type, value) { 674 | // Class expressions may have an optional name. 675 | if (type == "variable") return className(type, value); 676 | return classNameAfter(type, value); 677 | } 678 | function className(type, value) { 679 | if (type == "variable") {register(value); return cont(classNameAfter);} 680 | } 681 | function classNameAfter(type, value) { 682 | if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter) 683 | if (value == "extends" || value == "implements" || (isTS && type == ",")) 684 | return cont(isTS ? typeexpr : expression, classNameAfter); 685 | if (type == "{") return cont(pushlex("}"), classBody, poplex); 686 | } 687 | function classBody(type, value) { 688 | if (type == "async" || 689 | (type == "variable" && 690 | (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) && 691 | cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) { 692 | cx.marked = "keyword"; 693 | return cont(classBody); 694 | } 695 | if (type == "variable" || cx.style == "keyword") { 696 | cx.marked = "property"; 697 | return cont(isTS ? classfield : functiondef, classBody); 698 | } 699 | if (type == "[") 700 | return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody) 701 | if (value == "*") { 702 | cx.marked = "keyword"; 703 | return cont(classBody); 704 | } 705 | if (type == ";") return cont(classBody); 706 | if (type == "}") return cont(); 707 | if (value == "@") return cont(expression, classBody) 708 | } 709 | function classfield(type, value) { 710 | if (value == "?") return cont(classfield) 711 | if (type == ":") return cont(typeexpr, maybeAssign) 712 | if (value == "=") return cont(expressionNoComma) 713 | return pass(functiondef) 714 | } 715 | function afterExport(type, value) { 716 | if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } 717 | if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } 718 | if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";")); 719 | return pass(statement); 720 | } 721 | function exportField(type, value) { 722 | if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); } 723 | if (type == "variable") return pass(expressionNoComma, exportField); 724 | } 725 | function afterImport(type) { 726 | if (type == "string") return cont(); 727 | return pass(importSpec, maybeMoreImports, maybeFrom); 728 | } 729 | function importSpec(type, value) { 730 | if (type == "{") return contCommasep(importSpec, "}"); 731 | if (type == "variable") register(value); 732 | if (value == "*") cx.marked = "keyword"; 733 | return cont(maybeAs); 734 | } 735 | function maybeMoreImports(type) { 736 | if (type == ",") return cont(importSpec, maybeMoreImports) 737 | } 738 | function maybeAs(_type, value) { 739 | if (value == "as") { cx.marked = "keyword"; return cont(importSpec); } 740 | } 741 | function maybeFrom(_type, value) { 742 | if (value == "from") { cx.marked = "keyword"; return cont(expression); } 743 | } 744 | function arrayLiteral(type) { 745 | if (type == "]") return cont(); 746 | return pass(commasep(expressionNoComma, "]")); 747 | } 748 | 749 | function isContinuedStatement(state, textAfter) { 750 | return state.lastType == "operator" || state.lastType == "," || 751 | isOperatorChar.test(textAfter.charAt(0)) || 752 | /[,.]/.test(textAfter.charAt(0)); 753 | } 754 | 755 | function expressionAllowed(stream, state, backUp) { 756 | return state.tokenize == tokenBase && 757 | /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) || 758 | (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) 759 | } 760 | 761 | // Interface 762 | 763 | return { 764 | startState: function(basecolumn) { 765 | var state = { 766 | tokenize: tokenBase, 767 | lastType: "sof", 768 | cc: [], 769 | lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), 770 | localVars: parserConfig.localVars, 771 | context: parserConfig.localVars && {vars: parserConfig.localVars}, 772 | indented: basecolumn || 0 773 | }; 774 | if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") 775 | state.globalVars = parserConfig.globalVars; 776 | return state; 777 | }, 778 | 779 | token: function(stream, state) { 780 | if (stream.sol()) { 781 | if (!state.lexical.hasOwnProperty("align")) 782 | state.lexical.align = false; 783 | state.indented = stream.indentation(); 784 | findFatArrow(stream, state); 785 | } 786 | if (state.tokenize != tokenComment && stream.eatSpace()) return null; 787 | var style = state.tokenize(stream, state); 788 | if (type == "comment") return style; 789 | state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; 790 | return parseJS(state, style, type, content, stream); 791 | }, 792 | 793 | indent: function(state, textAfter) { 794 | if (state.tokenize == tokenComment) return CodeMirror.Pass; 795 | if (state.tokenize != tokenBase) return 0; 796 | var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top 797 | // Kludge to prevent 'maybelse' from blocking lexical scope pops 798 | if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { 799 | var c = state.cc[i]; 800 | if (c == poplex) lexical = lexical.prev; 801 | else if (c != maybeelse) break; 802 | } 803 | while ((lexical.type == "stat" || lexical.type == "form") && 804 | (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) && 805 | (top == maybeoperatorComma || top == maybeoperatorNoComma) && 806 | !/^[,\.=+\-*:?[\(]/.test(textAfter)))) 807 | lexical = lexical.prev; 808 | if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") 809 | lexical = lexical.prev; 810 | var type = lexical.type, closing = firstChar == type; 811 | 812 | if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); 813 | else if (type == "form" && firstChar == "{") return lexical.indented; 814 | else if (type == "form") return lexical.indented + indentUnit; 815 | else if (type == "stat") 816 | return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); 817 | else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) 818 | return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); 819 | else if (lexical.align) return lexical.column + (closing ? 0 : 1); 820 | else return lexical.indented + (closing ? 0 : indentUnit); 821 | }, 822 | 823 | electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, 824 | blockCommentStart: jsonMode ? null : "/*", 825 | blockCommentEnd: jsonMode ? null : "*/", 826 | blockCommentContinue: jsonMode ? null : " * ", 827 | lineComment: jsonMode ? null : "//", 828 | fold: "brace", 829 | closeBrackets: "()[]{}''\"\"``", 830 | 831 | helperType: jsonMode ? "json" : "javascript", 832 | jsonldMode: jsonldMode, 833 | jsonMode: jsonMode, 834 | 835 | expressionAllowed: expressionAllowed, 836 | 837 | skipExpression: function(state) { 838 | var top = state.cc[state.cc.length - 1] 839 | if (top == expression || top == expressionNoComma) state.cc.pop() 840 | } 841 | }; 842 | }); 843 | 844 | CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); 845 | 846 | CodeMirror.defineMIME("text/javascript", "javascript"); 847 | CodeMirror.defineMIME("text/ecmascript", "javascript"); 848 | CodeMirror.defineMIME("application/javascript", "javascript"); 849 | CodeMirror.defineMIME("application/x-javascript", "javascript"); 850 | CodeMirror.defineMIME("application/ecmascript", "javascript"); 851 | CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); 852 | CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); 853 | CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); 854 | CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); 855 | CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); 856 | 857 | }); 858 | -------------------------------------------------------------------------------- /lib/pane1/matchbrackets.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && 13 | (document.documentMode == null || document.documentMode < 8); 14 | 15 | var Pos = CodeMirror.Pos; 16 | 17 | var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; 18 | 19 | function findMatchingBracket(cm, where, config) { 20 | var line = cm.getLineHandle(where.line), pos = where.ch - 1; 21 | var afterCursor = config && config.afterCursor 22 | if (afterCursor == null) 23 | afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className) 24 | 25 | // A cursor is defined as between two characters, but in in vim command mode 26 | // (i.e. not insert mode), the cursor is visually represented as a 27 | // highlighted box on top of the 2nd character. Otherwise, we allow matches 28 | // from before or after the cursor. 29 | var match = (!afterCursor && pos >= 0 && matching[line.text.charAt(pos)]) || 30 | matching[line.text.charAt(++pos)]; 31 | if (!match) return null; 32 | var dir = match.charAt(1) == ">" ? 1 : -1; 33 | if (config && config.strict && (dir > 0) != (pos == where.ch)) return null; 34 | var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); 35 | 36 | var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); 37 | if (found == null) return null; 38 | return {from: Pos(where.line, pos), to: found && found.pos, 39 | match: found && found.ch == match.charAt(0), forward: dir > 0}; 40 | } 41 | 42 | // bracketRegex is used to specify which type of bracket to scan 43 | // should be a regexp, e.g. /[[\]]/ 44 | // 45 | // Note: If "where" is on an open bracket, then this bracket is ignored. 46 | // 47 | // Returns false when no bracket was found, null when it reached 48 | // maxScanLines and gave up 49 | function scanForBracket(cm, where, dir, style, config) { 50 | var maxScanLen = (config && config.maxScanLineLength) || 10000; 51 | var maxScanLines = (config && config.maxScanLines) || 1000; 52 | 53 | var stack = []; 54 | var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; 55 | var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) 56 | : Math.max(cm.firstLine() - 1, where.line - maxScanLines); 57 | for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { 58 | var line = cm.getLine(lineNo); 59 | if (!line) continue; 60 | var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; 61 | if (line.length > maxScanLen) continue; 62 | if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); 63 | for (; pos != end; pos += dir) { 64 | var ch = line.charAt(pos); 65 | if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { 66 | var match = matching[ch]; 67 | if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); 68 | else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; 69 | else stack.pop(); 70 | } 71 | } 72 | } 73 | return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; 74 | } 75 | 76 | function matchBrackets(cm, autoclear, config) { 77 | // Disable brace matching in long lines, since it'll cause hugely slow updates 78 | var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; 79 | var marks = [], ranges = cm.listSelections(); 80 | for (var i = 0; i < ranges.length; i++) { 81 | var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config); 82 | if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { 83 | var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; 84 | marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); 85 | if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) 86 | marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); 87 | } 88 | } 89 | 90 | if (marks.length) { 91 | // Kludge to work around the IE bug from issue #1193, where text 92 | // input stops going to the textare whever this fires. 93 | if (ie_lt8 && cm.state.focused) cm.focus(); 94 | 95 | var clear = function() { 96 | cm.operation(function() { 97 | for (var i = 0; i < marks.length; i++) marks[i].clear(); 98 | }); 99 | }; 100 | if (autoclear) setTimeout(clear, 800); 101 | else return clear; 102 | } 103 | } 104 | 105 | var currentlyHighlighted = null; 106 | function doMatchBrackets(cm) { 107 | cm.operation(function() { 108 | if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} 109 | currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); 110 | }); 111 | } 112 | 113 | CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { 114 | if (old && old != CodeMirror.Init) { 115 | cm.off("cursorActivity", doMatchBrackets); 116 | if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} 117 | } 118 | if (val) { 119 | cm.state.matchBrackets = typeof val == "object" ? val : {}; 120 | cm.on("cursorActivity", doMatchBrackets); 121 | } 122 | }); 123 | 124 | CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); 125 | CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){ 126 | // Backwards-compatibility kludge 127 | if (oldConfig || typeof config == "boolean") { 128 | if (!oldConfig) { 129 | config = config ? {strict: true} : null 130 | } else { 131 | oldConfig.strict = config 132 | config = oldConfig 133 | } 134 | } 135 | return findMatchingBracket(this, pos, config) 136 | }); 137 | CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ 138 | return scanForBracket(this, pos, dir, style, config); 139 | }); 140 | }); 141 | -------------------------------------------------------------------------------- /lib/pane1/python.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | function wordRegexp(words) { 15 | return new RegExp("^((" + words.join(")|(") + "))\\b"); 16 | } 17 | 18 | var wordOperators = wordRegexp(["and", "or", "not", "is"]); 19 | var commonKeywords = ["as", "assert", "break", "class", "continue", 20 | "def", "del", "elif", "else", "except", "finally", 21 | "for", "from", "global", "if", "import", 22 | "lambda", "pass", "raise", "return", 23 | "try", "while", "with", "yield", "in"]; 24 | var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr", 25 | "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod", 26 | "enumerate", "eval", "filter", "float", "format", "frozenset", 27 | "getattr", "globals", "hasattr", "hash", "help", "hex", "id", 28 | "input", "int", "isinstance", "issubclass", "iter", "len", 29 | "list", "locals", "map", "max", "memoryview", "min", "next", 30 | "object", "oct", "open", "ord", "pow", "property", "range", 31 | "repr", "reversed", "round", "set", "setattr", "slice", 32 | "sorted", "staticmethod", "str", "sum", "super", "tuple", 33 | "type", "vars", "zip", "__import__", "NotImplemented", 34 | "Ellipsis", "__debug__"]; 35 | CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins)); 36 | 37 | function top(state) { 38 | return state.scopes[state.scopes.length - 1]; 39 | } 40 | 41 | CodeMirror.defineMode("python", function(conf, parserConf) { 42 | var ERRORCLASS = "error"; 43 | 44 | var delimiters = parserConf.delimiters || parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/; 45 | // (Backwards-compatiblity with old, cumbersome config system) 46 | var operators = [parserConf.singleOperators, parserConf.doubleOperators, parserConf.doubleDelimiters, parserConf.tripleDelimiters, 47 | parserConf.operators || /^([-+*/%\/&|^]=?|[<>=]+|\/\/=?|\*\*=?|!=|[~!@])/] 48 | for (var i = 0; i < operators.length; i++) if (!operators[i]) operators.splice(i--, 1) 49 | 50 | var hangingIndent = parserConf.hangingIndent || conf.indentUnit; 51 | 52 | var myKeywords = commonKeywords, myBuiltins = commonBuiltins; 53 | if (parserConf.extra_keywords != undefined) 54 | myKeywords = myKeywords.concat(parserConf.extra_keywords); 55 | 56 | if (parserConf.extra_builtins != undefined) 57 | myBuiltins = myBuiltins.concat(parserConf.extra_builtins); 58 | 59 | var py3 = !(parserConf.version && Number(parserConf.version) < 3) 60 | if (py3) { 61 | // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator 62 | var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/; 63 | myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]); 64 | myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]); 65 | var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i"); 66 | } else { 67 | var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/; 68 | myKeywords = myKeywords.concat(["exec", "print"]); 69 | myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile", 70 | "file", "intern", "long", "raw_input", "reduce", "reload", 71 | "unichr", "unicode", "xrange", "False", "True", "None"]); 72 | var stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i"); 73 | } 74 | var keywords = wordRegexp(myKeywords); 75 | var builtins = wordRegexp(myBuiltins); 76 | 77 | // tokenizers 78 | function tokenBase(stream, state) { 79 | if (stream.sol()) state.indent = stream.indentation() 80 | // Handle scope changes 81 | if (stream.sol() && top(state).type == "py") { 82 | var scopeOffset = top(state).offset; 83 | if (stream.eatSpace()) { 84 | var lineOffset = stream.indentation(); 85 | if (lineOffset > scopeOffset) 86 | pushPyScope(state); 87 | else if (lineOffset < scopeOffset && dedent(stream, state) && stream.peek() != "#") 88 | state.errorToken = true; 89 | return null; 90 | } else { 91 | var style = tokenBaseInner(stream, state); 92 | if (scopeOffset > 0 && dedent(stream, state)) 93 | style += " " + ERRORCLASS; 94 | return style; 95 | } 96 | } 97 | return tokenBaseInner(stream, state); 98 | } 99 | 100 | function tokenBaseInner(stream, state) { 101 | if (stream.eatSpace()) return null; 102 | 103 | var ch = stream.peek(); 104 | 105 | // Handle Comments 106 | if (ch == "#") { 107 | stream.skipToEnd(); 108 | return "comment"; 109 | } 110 | 111 | // Handle Number Literals 112 | if (stream.match(/^[0-9\.]/, false)) { 113 | var floatLiteral = false; 114 | // Floats 115 | if (stream.match(/^[\d_]*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; } 116 | if (stream.match(/^[\d_]+\.\d*/)) { floatLiteral = true; } 117 | if (stream.match(/^\.\d+/)) { floatLiteral = true; } 118 | if (floatLiteral) { 119 | // Float literals may be "imaginary" 120 | stream.eat(/J/i); 121 | return "number"; 122 | } 123 | // Integers 124 | var intLiteral = false; 125 | // Hex 126 | if (stream.match(/^0x[0-9a-f_]+/i)) intLiteral = true; 127 | // Binary 128 | if (stream.match(/^0b[01_]+/i)) intLiteral = true; 129 | // Octal 130 | if (stream.match(/^0o[0-7_]+/i)) intLiteral = true; 131 | // Decimal 132 | if (stream.match(/^[1-9][\d_]*(e[\+\-]?[\d_]+)?/)) { 133 | // Decimal literals may be "imaginary" 134 | stream.eat(/J/i); 135 | // TODO - Can you have imaginary longs? 136 | intLiteral = true; 137 | } 138 | // Zero by itself with no other piece of number. 139 | if (stream.match(/^0(?![\dx])/i)) intLiteral = true; 140 | if (intLiteral) { 141 | // Integer literals may be "long" 142 | stream.eat(/L/i); 143 | return "number"; 144 | } 145 | } 146 | 147 | // Handle Strings 148 | if (stream.match(stringPrefixes)) { 149 | state.tokenize = tokenStringFactory(stream.current()); 150 | return state.tokenize(stream, state); 151 | } 152 | 153 | for (var i = 0; i < operators.length; i++) 154 | if (stream.match(operators[i])) return "operator" 155 | 156 | if (stream.match(delimiters)) return "punctuation"; 157 | 158 | if (state.lastToken == "." && stream.match(identifiers)) 159 | return "property"; 160 | 161 | if (stream.match(keywords) || stream.match(wordOperators)) 162 | return "keyword"; 163 | 164 | if (stream.match(builtins)) 165 | return "builtin"; 166 | 167 | if (stream.match(/^(self|cls)\b/)) 168 | return "variable-2"; 169 | 170 | if (stream.match(identifiers)) { 171 | if (state.lastToken == "def" || state.lastToken == "class") 172 | return "def"; 173 | return "variable"; 174 | } 175 | 176 | // Handle non-detected items 177 | stream.next(); 178 | return ERRORCLASS; 179 | } 180 | 181 | function tokenStringFactory(delimiter) { 182 | while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0) 183 | delimiter = delimiter.substr(1); 184 | 185 | var singleline = delimiter.length == 1; 186 | var OUTCLASS = "string"; 187 | 188 | function tokenString(stream, state) { 189 | while (!stream.eol()) { 190 | stream.eatWhile(/[^'"\\]/); 191 | if (stream.eat("\\")) { 192 | stream.next(); 193 | if (singleline && stream.eol()) 194 | return OUTCLASS; 195 | } else if (stream.match(delimiter)) { 196 | state.tokenize = tokenBase; 197 | return OUTCLASS; 198 | } else { 199 | stream.eat(/['"]/); 200 | } 201 | } 202 | if (singleline) { 203 | if (parserConf.singleLineStringErrors) 204 | return ERRORCLASS; 205 | else 206 | state.tokenize = tokenBase; 207 | } 208 | return OUTCLASS; 209 | } 210 | tokenString.isString = true; 211 | return tokenString; 212 | } 213 | 214 | function pushPyScope(state) { 215 | while (top(state).type != "py") state.scopes.pop() 216 | state.scopes.push({offset: top(state).offset + conf.indentUnit, 217 | type: "py", 218 | align: null}) 219 | } 220 | 221 | function pushBracketScope(stream, state, type) { 222 | var align = stream.match(/^([\s\[\{\(]|#.*)*$/, false) ? null : stream.column() + 1 223 | state.scopes.push({offset: state.indent + hangingIndent, 224 | type: type, 225 | align: align}) 226 | } 227 | 228 | function dedent(stream, state) { 229 | var indented = stream.indentation(); 230 | while (state.scopes.length > 1 && top(state).offset > indented) { 231 | if (top(state).type != "py") return true; 232 | state.scopes.pop(); 233 | } 234 | return top(state).offset != indented; 235 | } 236 | 237 | function tokenLexer(stream, state) { 238 | if (stream.sol()) state.beginningOfLine = true; 239 | 240 | var style = state.tokenize(stream, state); 241 | var current = stream.current(); 242 | 243 | // Handle decorators 244 | if (state.beginningOfLine && current == "@") 245 | return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS; 246 | 247 | if (/\S/.test(current)) state.beginningOfLine = false; 248 | 249 | if ((style == "variable" || style == "builtin") 250 | && state.lastToken == "meta") 251 | style = "meta"; 252 | 253 | // Handle scope changes. 254 | if (current == "pass" || current == "return") 255 | state.dedent += 1; 256 | 257 | if (current == "lambda") state.lambda = true; 258 | if (current == ":" && !state.lambda && top(state).type == "py") 259 | pushPyScope(state); 260 | 261 | var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1; 262 | if (delimiter_index != -1) 263 | pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); 264 | 265 | delimiter_index = "])}".indexOf(current); 266 | if (delimiter_index != -1) { 267 | if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent 268 | else return ERRORCLASS; 269 | } 270 | if (state.dedent > 0 && stream.eol() && top(state).type == "py") { 271 | if (state.scopes.length > 1) state.scopes.pop(); 272 | state.dedent -= 1; 273 | } 274 | 275 | return style; 276 | } 277 | 278 | var external = { 279 | startState: function(basecolumn) { 280 | return { 281 | tokenize: tokenBase, 282 | scopes: [{offset: basecolumn || 0, type: "py", align: null}], 283 | indent: basecolumn || 0, 284 | lastToken: null, 285 | lambda: false, 286 | dedent: 0 287 | }; 288 | }, 289 | 290 | token: function(stream, state) { 291 | var addErr = state.errorToken; 292 | if (addErr) state.errorToken = false; 293 | var style = tokenLexer(stream, state); 294 | 295 | if (style && style != "comment") 296 | state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style; 297 | if (style == "punctuation") style = null; 298 | 299 | if (stream.eol() && state.lambda) 300 | state.lambda = false; 301 | return addErr ? style + " " + ERRORCLASS : style; 302 | }, 303 | 304 | indent: function(state, textAfter) { 305 | if (state.tokenize != tokenBase) 306 | return state.tokenize.isString ? CodeMirror.Pass : 0; 307 | 308 | var scope = top(state), closing = scope.type == textAfter.charAt(0) 309 | if (scope.align != null) 310 | return scope.align - (closing ? 1 : 0) 311 | else 312 | return scope.offset - (closing ? hangingIndent : 0) 313 | }, 314 | 315 | electricInput: /^\s*[\}\]\)]$/, 316 | closeBrackets: {triples: "'\""}, 317 | lineComment: "#", 318 | fold: "indent" 319 | }; 320 | return external; 321 | }); 322 | 323 | CodeMirror.defineMIME("text/x-python", "python"); 324 | 325 | var words = function(str) { return str.split(" "); }; 326 | 327 | CodeMirror.defineMIME("text/x-cython", { 328 | name: "python", 329 | extra_keywords: words("by cdef cimport cpdef ctypedef enum except "+ 330 | "extern gil include nogil property public "+ 331 | "readonly struct union DEF IF ELIF ELSE") 332 | }); 333 | 334 | }); -------------------------------------------------------------------------------- /lib/pane1/searchcursor.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")) 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod) 9 | else // Plain browser env 10 | mod(CodeMirror) 11 | })(function(CodeMirror) { 12 | "use strict" 13 | var Pos = CodeMirror.Pos 14 | 15 | function regexpFlags(regexp) { 16 | var flags = regexp.flags 17 | return flags != null ? flags : (regexp.ignoreCase ? "i" : "") 18 | + (regexp.global ? "g" : "") 19 | + (regexp.multiline ? "m" : "") 20 | } 21 | 22 | function ensureGlobal(regexp) { 23 | return regexp.global ? regexp : new RegExp(regexp.source, regexpFlags(regexp) + "g") 24 | } 25 | 26 | function maybeMultiline(regexp) { 27 | return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source) 28 | } 29 | 30 | function searchRegexpForward(doc, regexp, start) { 31 | regexp = ensureGlobal(regexp) 32 | for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) { 33 | regexp.lastIndex = ch 34 | var string = doc.getLine(line), match = regexp.exec(string) 35 | if (match) 36 | return {from: Pos(line, match.index), 37 | to: Pos(line, match.index + match[0].length), 38 | match: match} 39 | } 40 | } 41 | 42 | function searchRegexpForwardMultiline(doc, regexp, start) { 43 | if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start) 44 | 45 | regexp = ensureGlobal(regexp) 46 | var string, chunk = 1 47 | for (var line = start.line, last = doc.lastLine(); line <= last;) { 48 | // This grows the search buffer in exponentially-sized chunks 49 | // between matches, so that nearby matches are fast and don't 50 | // require concatenating the whole document (in case we're 51 | // searching for something that has tons of matches), but at the 52 | // same time, the amount of retries is limited. 53 | for (var i = 0; i < chunk; i++) { 54 | var curLine = doc.getLine(line++) 55 | string = string == null ? curLine : string + "\n" + curLine 56 | } 57 | chunk = chunk * 2 58 | regexp.lastIndex = start.ch 59 | var match = regexp.exec(string) 60 | if (match) { 61 | var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") 62 | var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length 63 | return {from: Pos(startLine, startCh), 64 | to: Pos(startLine + inside.length - 1, 65 | inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), 66 | match: match} 67 | } 68 | } 69 | } 70 | 71 | function lastMatchIn(string, regexp) { 72 | var cutOff = 0, match 73 | for (;;) { 74 | regexp.lastIndex = cutOff 75 | var newMatch = regexp.exec(string) 76 | if (!newMatch) return match 77 | match = newMatch 78 | cutOff = match.index + (match[0].length || 1) 79 | if (cutOff == string.length) return match 80 | } 81 | } 82 | 83 | function searchRegexpBackward(doc, regexp, start) { 84 | regexp = ensureGlobal(regexp) 85 | for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) { 86 | var string = doc.getLine(line) 87 | if (ch > -1) string = string.slice(0, ch) 88 | var match = lastMatchIn(string, regexp) 89 | if (match) 90 | return {from: Pos(line, match.index), 91 | to: Pos(line, match.index + match[0].length), 92 | match: match} 93 | } 94 | } 95 | 96 | function searchRegexpBackwardMultiline(doc, regexp, start) { 97 | regexp = ensureGlobal(regexp) 98 | var string, chunk = 1 99 | for (var line = start.line, first = doc.firstLine(); line >= first;) { 100 | for (var i = 0; i < chunk; i++) { 101 | var curLine = doc.getLine(line--) 102 | string = string == null ? curLine.slice(0, start.ch) : curLine + "\n" + string 103 | } 104 | chunk *= 2 105 | 106 | var match = lastMatchIn(string, regexp) 107 | if (match) { 108 | var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") 109 | var startLine = line + before.length, startCh = before[before.length - 1].length 110 | return {from: Pos(startLine, startCh), 111 | to: Pos(startLine + inside.length - 1, 112 | inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), 113 | match: match} 114 | } 115 | } 116 | } 117 | 118 | var doFold, noFold 119 | if (String.prototype.normalize) { 120 | doFold = function(str) { return str.normalize("NFD").toLowerCase() } 121 | noFold = function(str) { return str.normalize("NFD") } 122 | } else { 123 | doFold = function(str) { return str.toLowerCase() } 124 | noFold = function(str) { return str } 125 | } 126 | 127 | // Maps a position in a case-folded line back to a position in the original line 128 | // (compensating for codepoints increasing in number during folding) 129 | function adjustPos(orig, folded, pos, foldFunc) { 130 | if (orig.length == folded.length) return pos 131 | for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) { 132 | if (min == max) return min 133 | var mid = (min + max) >> 1 134 | var len = foldFunc(orig.slice(0, mid)).length 135 | if (len == pos) return mid 136 | else if (len > pos) max = mid 137 | else min = mid + 1 138 | } 139 | } 140 | 141 | function searchStringForward(doc, query, start, caseFold) { 142 | // Empty string would match anything and never progress, so we 143 | // define it to match nothing instead. 144 | if (!query.length) return null 145 | var fold = caseFold ? doFold : noFold 146 | var lines = fold(query).split(/\r|\n\r?/) 147 | 148 | search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) { 149 | var orig = doc.getLine(line).slice(ch), string = fold(orig) 150 | if (lines.length == 1) { 151 | var found = string.indexOf(lines[0]) 152 | if (found == -1) continue search 153 | var start = adjustPos(orig, string, found, fold) + ch 154 | return {from: Pos(line, adjustPos(orig, string, found, fold) + ch), 155 | to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)} 156 | } else { 157 | var cutFrom = string.length - lines[0].length 158 | if (string.slice(cutFrom) != lines[0]) continue search 159 | for (var i = 1; i < lines.length - 1; i++) 160 | if (fold(doc.getLine(line + i)) != lines[i]) continue search 161 | var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1] 162 | if (endString.slice(0, lastLine.length) != lastLine) continue search 163 | return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch), 164 | to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))} 165 | } 166 | } 167 | } 168 | 169 | function searchStringBackward(doc, query, start, caseFold) { 170 | if (!query.length) return null 171 | var fold = caseFold ? doFold : noFold 172 | var lines = fold(query).split(/\r|\n\r?/) 173 | 174 | search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) { 175 | var orig = doc.getLine(line) 176 | if (ch > -1) orig = orig.slice(0, ch) 177 | var string = fold(orig) 178 | if (lines.length == 1) { 179 | var found = string.lastIndexOf(lines[0]) 180 | if (found == -1) continue search 181 | return {from: Pos(line, adjustPos(orig, string, found, fold)), 182 | to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))} 183 | } else { 184 | var lastLine = lines[lines.length - 1] 185 | if (string.slice(0, lastLine.length) != lastLine) continue search 186 | for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++) 187 | if (fold(doc.getLine(start + i)) != lines[i]) continue search 188 | var top = doc.getLine(line + 1 - lines.length), topString = fold(top) 189 | if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search 190 | return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)), 191 | to: Pos(line, adjustPos(orig, string, lastLine.length, fold))} 192 | } 193 | } 194 | } 195 | 196 | function SearchCursor(doc, query, pos, options) { 197 | this.atOccurrence = false 198 | this.doc = doc 199 | pos = pos ? doc.clipPos(pos) : Pos(0, 0) 200 | this.pos = {from: pos, to: pos} 201 | 202 | var caseFold 203 | if (typeof options == "object") { 204 | caseFold = options.caseFold 205 | } else { // Backwards compat for when caseFold was the 4th argument 206 | caseFold = options 207 | options = null 208 | } 209 | 210 | if (typeof query == "string") { 211 | if (caseFold == null) caseFold = false 212 | this.matches = function(reverse, pos) { 213 | return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold) 214 | } 215 | } else { 216 | query = ensureGlobal(query) 217 | if (!options || options.multiline !== false) 218 | this.matches = function(reverse, pos) { 219 | return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos) 220 | } 221 | else 222 | this.matches = function(reverse, pos) { 223 | return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos) 224 | } 225 | } 226 | } 227 | 228 | SearchCursor.prototype = { 229 | findNext: function() {return this.find(false)}, 230 | findPrevious: function() {return this.find(true)}, 231 | 232 | find: function(reverse) { 233 | var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to)) 234 | 235 | // Implements weird auto-growing behavior on null-matches for 236 | // backwards-compatiblity with the vim code (unfortunately) 237 | while (result && CodeMirror.cmpPos(result.from, result.to) == 0) { 238 | if (reverse) { 239 | if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1) 240 | else if (result.from.line == this.doc.firstLine()) result = null 241 | else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1))) 242 | } else { 243 | if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1) 244 | else if (result.to.line == this.doc.lastLine()) result = null 245 | else result = this.matches(reverse, Pos(result.to.line + 1, 0)) 246 | } 247 | } 248 | 249 | if (result) { 250 | this.pos = result 251 | this.atOccurrence = true 252 | return this.pos.match || true 253 | } else { 254 | var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0) 255 | this.pos = {from: end, to: end} 256 | return this.atOccurrence = false 257 | } 258 | }, 259 | 260 | from: function() {if (this.atOccurrence) return this.pos.from}, 261 | to: function() {if (this.atOccurrence) return this.pos.to}, 262 | 263 | replace: function(newText, origin) { 264 | if (!this.atOccurrence) return 265 | var lines = CodeMirror.splitLines(newText) 266 | this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin) 267 | this.pos.to = Pos(this.pos.from.line + lines.length - 1, 268 | lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)) 269 | } 270 | } 271 | 272 | CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { 273 | return new SearchCursor(this.doc, query, pos, caseFold) 274 | }) 275 | CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { 276 | return new SearchCursor(this, query, pos, caseFold) 277 | }) 278 | 279 | CodeMirror.defineExtension("selectMatches", function(query, caseFold) { 280 | var ranges = [] 281 | var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold) 282 | while (cur.findNext()) { 283 | if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break 284 | ranges.push({anchor: cur.from(), head: cur.to()}) 285 | } 286 | if (ranges.length) 287 | this.setSelections(ranges, 0) 288 | }) 289 | }); 290 | -------------------------------------------------------------------------------- /pane1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 |
38 | 39 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /static/img/dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teamsudocode/dexter/0ccceac9a97687c39c84eb92ee834021d66767c8/static/img/dot.png -------------------------------------------------------------------------------- /static/img/english.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 3 Copy 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /static/img/hindi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 3 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/img/js.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {} 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/img/logo-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /static/img/mic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mic - material 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/img/python.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ion-social-python - Ionicons 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /static/img/run.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6:6 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /static/img/text-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DEXTER 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/img/undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | replay - material 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /styles/editor.css: -------------------------------------------------------------------------------- 1 | @import url(reset.css); 2 | body { 3 | max-height: 100%; 4 | overflow-y: hidden; } 5 | 6 | .container { 7 | display: grid; 8 | height: 100vh; 9 | grid-template-rows: 10% 65% 25%; } 10 | .container .nav { 11 | padding: 2em; 12 | display: grid; 13 | grid-template-columns: 20% 60% 20%; 14 | background: #121E4A; 15 | box-shadow: 0 5px 4px 0 rgba(3, 16, 64, 0.54); } 16 | .container .nav span { 17 | font-family: 'Roboto'; 18 | font-size: 14px; 19 | text-transform: uppercase; 20 | color: rgba(255, 255, 255, 0.5); 21 | letter-spacing: 6px; 22 | text-align: center; } 23 | .container .nav .language { 24 | display: flex; 25 | justify-content: flex-end; 26 | align-items: center; } 27 | .container .nav .language p { 28 | display: inline-block; 29 | font-family: 'Roboto'; 30 | font-size: 14px; 31 | font-weight: 400; 32 | color: #5762B9; } 33 | .container .nav .language img { 34 | margin-left: 1.5em; 35 | cursor: pointer; 36 | transition: all 0.2s ease-in-out; } 37 | .container .nav .language #hindi { 38 | opacity: 0.3; } 39 | .container .editors { 40 | display: grid; 41 | grid-template-columns: 49.75% 0.5% 49.75%; } 42 | .container .editors #js .title .filename { 43 | border-bottom: 2px solid #FF309D; } 44 | .container .editors #python .title .filename { 45 | border-bottom: 2px solid #00B2F7; } 46 | .container .editors .pane { 47 | display: grid; 48 | grid-template-columns: 1% 99%; 49 | grid-template-rows: 10% 90%; 50 | background-image: linear-gradient(-180deg, #2E3478 0%, #0F1C46 100%); } 51 | .container .editors .pane .title { 52 | display: flex; 53 | flex-direction: row; 54 | justify-content: space-between; 55 | padding: 1em; 56 | height: 1.7em; } 57 | .container .editors .pane .title .filename { 58 | display: inline-block; } 59 | .container .editors .pane .title .filename img { 60 | vertical-align: middle; 61 | margin-right: 0.5em; } 62 | .container .editors .pane .title .filename span { 63 | font-family: 'Roboto'; 64 | font-size: 1em; 65 | font-weight: 500; 66 | vertical-align: middle; 67 | color: #FFFFFF; 68 | letter-spacing: 0.44px; } 69 | .container .editors .pane .title .actions { 70 | display: flex; 71 | padding: 0 1em; } 72 | .container .editors .pane .title .actions #undo { 73 | cursor: pointer; } 74 | .container .editors .pane .title .actions button { 75 | margin-left: 2em; 76 | cursor: pointer; 77 | background: #42A15E; 78 | border-radius: 2px; 79 | font-family: Roboto; 80 | font-weight: 500; 81 | border: none; 82 | padding: 0.5em; 83 | font-size: 0.8em; 84 | color: #FFFFFF; } 85 | .container .editors .pane .title .actions button img { 86 | margin-left: 0.5em; } 87 | .container .editors .pane .index { 88 | padding: 0px 1em 1em 1em; 89 | font-family: 'Roboto Mono'; 90 | text-align: center; 91 | font-size: 1em; 92 | color: rgba(255, 255, 255, 0.22); 93 | line-height: 1.55em; } 94 | .container .editors .pane .editor { 95 | background-color: transparent; 96 | border: none; 97 | font-family: 'Roboto Mono'; 98 | font-size: 1em; 99 | color: #FFF; 100 | line-height: 1.55em; } 101 | .container .editors .pane .editor:focus { 102 | outline: none; } 103 | .container .editors .divider { 104 | background-color: #495297; } 105 | .container .preview { 106 | display: flex; 107 | justify-content: center; 108 | align-items: center; 109 | flex-direction: column; 110 | background-image: linear-gradient(-180deg, #122256 0%, #0B164B 100%); } 111 | .container .preview div { 112 | font-family: 'Roboto Mono'; 113 | font-size: 1.2em; 114 | letter-spacing: 0.2em; 115 | text-transform: uppercase; 116 | text-align: center; 117 | line-height: 1.5em; 118 | color: #00B2F7; 119 | position: relative; } 120 | .container .preview .Loader { 121 | position: relative; 122 | display: flex; 123 | align-items: center; 124 | justify-content: center; 125 | width: 100%; 126 | max-width: 3.4rem; 127 | margin-top: 1.7rem; 128 | margin-bottom: 3.4rem; } 129 | .container .preview .Loader:before, .container .preview .Loader:after { 130 | content: ""; 131 | position: absolute; 132 | border-radius: 50%; 133 | animation-duration: 1.8s; 134 | animation-iteration-count: infinite; 135 | animation-timing-function: ease-in-out; 136 | filter: drop-shadow(0 0 0.08889rem rgba(0, 208, 250, 0.75)); } 137 | .container .preview .Loader:before { 138 | width: 100%; 139 | padding-bottom: 100%; 140 | box-shadow: inset 0 0 0 0.2rem #00D0FA; 141 | animation-name: pulsA; } 142 | .container .preview .Loader:after { 143 | width: calc(100% - 0.2rem*2); 144 | padding-bottom: calc(100% - 0.2rem*2); 145 | box-shadow: 0 0 0 0 #00D0FA; 146 | animation-name: pulsB; } 147 | .container .preview .Loader img:before, .container .preview .Loader img:after { 148 | animation-duration: 1.8s; 149 | animation-iteration-count: infinite; 150 | animation-timing-function: ease-in-out; } 151 | .container .preview .Loader img:before { 152 | animation-name: pulsA; } 153 | .container .preview .Loader img:after { 154 | animation-name: pulsB; } 155 | .container .preview #rec-btn { 156 | cursor: pointer; } 157 | .container .preview .alive { 158 | display: visible; } 159 | .container .preview .dead { 160 | margin-bottom: 3em; 161 | margin-top: 1.5em; 162 | display: none; } 163 | @keyframes pulsA { 164 | 0% { 165 | box-shadow: inset 0 0 0 0.2rem #00D0FA; 166 | opacity: 1; } 167 | 50%, 168 | 100% { 169 | box-shadow: inset 0 0 0 0 #00D0FA; 170 | opacity: 0; } } 171 | @keyframes pulsB { 172 | 0%, 173 | 50% { 174 | box-shadow: 0 0 0 0 #00D0FA; 175 | opacity: 0; } 176 | 100% { 177 | box-shadow: 0 0 0 0.2rem #00D0FA; 178 | opacity: 1; } } 179 | 180 | /*# sourceMappingURL=editor.css.map */ 181 | -------------------------------------------------------------------------------- /styles/editor.scss: -------------------------------------------------------------------------------- 1 | @import 'reset.css'; 2 | body { 3 | max-height: 100%; 4 | overflow-y: hidden; 5 | } 6 | 7 | .container { 8 | display: grid; 9 | height: 100vh; 10 | grid-template-rows: 10% 65% 25%; 11 | .nav { 12 | padding: 2em; 13 | display: grid; 14 | grid-template-columns: 20% 60% 20%; 15 | background: #121E4A; 16 | box-shadow: 0 5px 4px 0 rgba(3, 16, 64, 0.54); 17 | span { 18 | font-family: 'Roboto'; 19 | font-size: 14px; 20 | text-transform: uppercase; 21 | color: rgba(255, 255, 255, 0.50); 22 | letter-spacing: 6px; 23 | text-align: center; 24 | } 25 | .language { 26 | display: flex; 27 | justify-content: flex-end; 28 | align-items: center; 29 | p { 30 | display: inline-block; 31 | font-family: 'Roboto'; 32 | font-size: 14px; 33 | font-weight: 400; 34 | color: #5762B9; 35 | } 36 | img { 37 | margin-left: 1.5em; 38 | cursor: pointer; 39 | transition: all 0.2s ease-in-out; 40 | } 41 | #hindi{ 42 | opacity: 0.3; 43 | } 44 | } 45 | } 46 | .editors { 47 | display: grid; 48 | grid-template-columns: 49.75% 0.5% 49.75%; 49 | #js { 50 | .title { 51 | .filename { 52 | border-bottom: 2px solid #FF309D; 53 | } 54 | } 55 | } 56 | #python { 57 | .title { 58 | .filename { 59 | border-bottom: 2px solid #00B2F7; 60 | } 61 | } 62 | } 63 | .pane { 64 | display: grid; 65 | grid-template-columns: 1% 99%; 66 | grid-template-rows: 10% 90%; 67 | background-image: linear-gradient(-180deg, #2E3478 0%, #0F1C46 100%); 68 | .title { 69 | display: flex; 70 | flex-direction: row; 71 | justify-content: space-between; 72 | padding: 1em; 73 | height: 1.7em; 74 | .filename { 75 | display: inline-block; 76 | img { 77 | vertical-align: middle; 78 | margin-right: 0.5em; 79 | } 80 | span { 81 | font-family: 'Roboto'; 82 | font-size: 1em; 83 | font-weight: 500; 84 | vertical-align: middle; 85 | color: #FFFFFF; 86 | letter-spacing: 0.44px; 87 | } 88 | } 89 | .actions { 90 | display: flex; 91 | padding: 0 1em; 92 | #undo { 93 | cursor: pointer; 94 | } 95 | button { 96 | margin-left: 2em; 97 | cursor: pointer; 98 | background: #42A15E; 99 | border-radius: 2px; 100 | font-family: Roboto; 101 | font-weight: 500; 102 | border: none; 103 | padding: 0.5em; 104 | font-size: 0.8em; 105 | color: #FFFFFF; 106 | img { 107 | margin-left: 0.5em; 108 | } 109 | } 110 | } 111 | } 112 | .index { 113 | padding: 0px 1em 1em 1em; 114 | font-family: 'Roboto Mono'; 115 | text-align: center; 116 | font-size: 1em; 117 | color: rgba(255, 255, 255, 0.22); 118 | line-height: 1.55em; 119 | } 120 | .editor { 121 | background-color: transparent; 122 | border: none; 123 | font-family: 'Roboto Mono'; 124 | font-size: 1em; 125 | color: #FFF; 126 | line-height: 1.55em; 127 | &:focus { 128 | outline: none; 129 | } 130 | } 131 | } 132 | .divider { 133 | background-color: #495297; 134 | } 135 | } 136 | .preview { 137 | display: flex; 138 | justify-content: center; 139 | align-items: center; 140 | flex-direction: column; 141 | background-image: linear-gradient(-180deg, #122256 0%, #0B164B 100%); 142 | div { 143 | font-family: 'Roboto Mono'; 144 | font-size: 1.2em; 145 | letter-spacing: 0.2em; 146 | text-transform: uppercase; 147 | text-align: center; 148 | line-height: 1.5em; 149 | color: #00B2F7; 150 | position: relative; 151 | } 152 | $Loader-color: #00D0FA; 153 | $Loader-size: 3.4rem; 154 | $Loader-offset: 0.2rem; 155 | $Loader-timing: ease-in-out; 156 | .Loader { 157 | position: relative; 158 | display: flex; 159 | align-items: center; 160 | justify-content: center; 161 | width: 100%; 162 | max-width: $Loader-size; 163 | margin-top: $Loader-size/2; 164 | margin-bottom: $Loader-size; 165 | &:before, 166 | &:after { 167 | content: ""; 168 | position: absolute; 169 | border-radius: 50%; 170 | animation-duration: 1.8s; 171 | animation-iteration-count: infinite; 172 | animation-timing-function: $Loader-timing; 173 | filter: drop-shadow(0 0 $Loader-offset/2.25 rgba($Loader-color, 0.75)); 174 | } 175 | &:before { 176 | width: 100%; 177 | padding-bottom: 100%; 178 | box-shadow: inset 0 0 0 $Loader-offset $Loader-color; 179 | animation-name: pulsA; 180 | } 181 | &:after { 182 | width: calc(100% - #{$Loader-offset}*2); 183 | padding-bottom: calc(100% - #{$Loader-offset}*2); 184 | box-shadow: 0 0 0 0 $Loader-color; 185 | animation-name: pulsB; 186 | } 187 | img { 188 | &:before, 189 | &:after { 190 | animation-duration: 1.8s; 191 | animation-iteration-count: infinite; 192 | animation-timing-function: $Loader-timing;; 193 | } 194 | &:before { 195 | animation-name: pulsA; 196 | } 197 | &:after { 198 | animation-name: pulsB; 199 | } 200 | } 201 | } 202 | #rec-btn{ 203 | cursor: pointer; 204 | } 205 | .alive{ 206 | display: visible; 207 | } 208 | .dead{ 209 | margin-bottom: 3em; 210 | margin-top: 1.5em; 211 | display: none; 212 | } 213 | @keyframes pulsA { 214 | 0% { 215 | box-shadow: inset 0 0 0 $Loader-offset $Loader-color; 216 | opacity: 1; 217 | } 218 | 50%, 219 | 100% { 220 | box-shadow: inset 0 0 0 0 $Loader-color; 221 | opacity: 0; 222 | } 223 | } 224 | @keyframes pulsB { 225 | 0%, 226 | 50% { 227 | box-shadow: 0 0 0 0 $Loader-color; 228 | opacity: 0; 229 | } 230 | 100% { 231 | box-shadow: 0 0 0 $Loader-offset $Loader-color; 232 | opacity: 1; 233 | } 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /styles/home.css: -------------------------------------------------------------------------------- 1 | @import url(reset.css); 2 | body { 3 | background: linear-gradient(-180deg, #252C70 0%, #0F1C46 100%); 4 | height: 100vh; 5 | overflow-y: hidden; } 6 | 7 | .container { 8 | margin-top: 10%; 9 | display: flex; 10 | flex-direction: column; 11 | text-align: center; } 12 | .container .logo { 13 | height: 9em; } 14 | .container .textlogo { 15 | margin: 2em 0 2.5em 0; 16 | height: 3.5em; } 17 | .container h1 { 18 | font-family: 'Roboto'; 19 | font-size: 1.2em; 20 | color: #FFFFFF; 21 | letter-spacing: 0.3em; 22 | margin-bottom: 2em; 23 | text-transform: uppercase; } 24 | .container .video-play-button { 25 | position: absolute; 26 | z-index: 10; 27 | bottom: 25vh; 28 | left: 50%; 29 | transform: translateX(-50%) translateY(-50%); 30 | box-sizing: content-box; 31 | display: block; 32 | width: 28px; 33 | height: 48px; 34 | border-radius: 50%; 35 | transition-duration: 0.15s; 36 | transition-timing-function: ease-in-out; 37 | transition-property: background; 38 | padding: 18px 20px 18px 28px; } 39 | .container .video-play-button:before { 40 | content: ""; 41 | position: absolute; 42 | z-index: 0; 43 | left: 50%; 44 | top: 50%; 45 | transform: translateX(-50%) translateY(-50%); 46 | display: block; 47 | width: 120px; 48 | height: 120px; 49 | background: #114276; 50 | border-radius: 50%; 51 | animation: pulse-border 1500ms ease-out infinite; } 52 | .container .video-play-button:after { 53 | content: ""; 54 | position: absolute; 55 | z-index: 1; 56 | left: 50%; 57 | top: 50%; 58 | transform: translateX(-50%) translateY(-50%); 59 | display: block; 60 | width: 120px; 61 | height: 120px; 62 | background: #00B2F7; 63 | border-radius: 50%; 64 | transition: all 200ms; } 65 | .container .video-play-button:hover:after { 66 | background-color: #00a0de; } 67 | .container .video-play-button img { 68 | position: relative; 69 | z-index: 3; 70 | max-width: 100%; 71 | width: auto; 72 | height: auto; } 73 | .container .video-play-button span { 74 | display: block; 75 | position: relative; 76 | z-index: 3; 77 | width: 0; 78 | height: 0; 79 | border-left: 32px solid #fff; 80 | border-top: 22px solid transparent; 81 | border-bottom: 22px solid transparent; } 82 | @keyframes pulse-border { 83 | 0% { 84 | transform: translateX(-50%) translateY(-50%) translateZ(0) scale(1); 85 | opacity: 1; } 86 | 100% { 87 | transform: translateX(-50%) translateY(-50%) translateZ(0) scale(1.5); 88 | opacity: 0; } } 89 | 90 | /*# sourceMappingURL=home.css.map */ 91 | -------------------------------------------------------------------------------- /styles/home.scss: -------------------------------------------------------------------------------- 1 | @import 'reset.css'; 2 | body { 3 | background: linear-gradient(-180deg, #252C70 0%, #0F1C46 100%); 4 | height: 100vh; 5 | overflow-y: hidden; 6 | } 7 | 8 | .container { 9 | margin-top: 10%; 10 | display: flex; 11 | flex-direction: column; 12 | text-align: center; 13 | .logo { 14 | height: 9em; 15 | } 16 | .textlogo { 17 | margin: 2em 0 2.5em 0; 18 | height: 3.5em; 19 | } 20 | h1 { 21 | font-family: 'Roboto'; 22 | font-size: 1.2em; 23 | color: #FFFFFF; 24 | letter-spacing: 0.3em; 25 | margin-bottom: 2em; 26 | text-transform: uppercase; 27 | } 28 | .video-play-button { 29 | position: absolute; 30 | z-index: 10; 31 | bottom: 25vh; 32 | left: 50%; 33 | transform: translateX(-50%) translateY(-50%); 34 | box-sizing: content-box; 35 | display: block; 36 | width: 28px; 37 | height: 48px; 38 | border-radius: 50%; 39 | transition-duration: 0.15s; 40 | transition-timing-function: ease-in-out; 41 | transition-property: background; 42 | padding: 18px 20px 18px 28px; 43 | } 44 | .video-play-button:before { 45 | content: ""; 46 | position: absolute; 47 | z-index: 0; 48 | left: 50%; 49 | top: 50%; 50 | transform: translateX(-50%) translateY(-50%); 51 | display: block; 52 | width: 120px; 53 | height: 120px; 54 | background: #114276; 55 | border-radius: 50%; 56 | animation: pulse-border 1500ms ease-out infinite; 57 | } 58 | .video-play-button:after { 59 | content: ""; 60 | position: absolute; 61 | z-index: 1; 62 | left: 50%; 63 | top: 50%; 64 | transform: translateX(-50%) translateY(-50%); 65 | display: block; 66 | width: 120px; 67 | height: 120px; 68 | background: #00B2F7; 69 | border-radius: 50%; 70 | transition: all 200ms; 71 | } 72 | .video-play-button:hover:after { 73 | background-color: darken(#00B2F7, 5%); 74 | } 75 | .video-play-button img { 76 | position: relative; 77 | z-index: 3; 78 | max-width: 100%; 79 | width: auto; 80 | height: auto; 81 | } 82 | .video-play-button span { 83 | display: block; 84 | position: relative; 85 | z-index: 3; 86 | width: 0; 87 | height: 0; 88 | border-left: 32px solid #fff; 89 | border-top: 22px solid transparent; 90 | border-bottom: 22px solid transparent; 91 | } 92 | @keyframes pulse-border { 93 | 0% { 94 | transform: translateX(-50%) translateY(-50%) translateZ(0) scale(1); 95 | opacity: 1; 96 | } 97 | 100% { 98 | transform: translateX(-50%) translateY(-50%) translateZ(0) scale(1.5); 99 | opacity: 0; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /styles/lol.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Rich Text Editor 5 | 57 | 76 | 77 | 78 |
79 | 80 |
81 | 92 | 99 | 109 | 116 | 122 |
123 |
124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 |
145 |

Lorem ipsum

146 |

147 |

148 |
149 | 150 | -------------------------------------------------------------------------------- /styles/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } --------------------------------------------------------------------------------