-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathindex.js
127 lines (107 loc) · 3.52 KB
/
index.js
1
2
3
4
5
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
var events = require('events')
var inherits = require('inherits')
var extend = require('extend')
var esprima = require('esprima')
var CodeMirror = require('codemirror')
// load JS support for CodeMirror:
require('./javascript')(CodeMirror)
module.exports = function(opts) {
return new Editor(opts)
}
function Editor(opts) {
var self = this
if (!opts) opts = {}
if (!opts.container) opts.container = document.body
var left = opts.container.querySelector('.left')
var right = opts.container.querySelector('.right')
if (left) opts.container = left
var defaults = {
value: "// hello world\n",
mode: "javascript",
lineNumbers: true,
autofocus: (window === window.top),
matchBrackets: true,
indentWithTabs: false,
smartIndent: true,
tabSize: 2,
indentUnit: 2,
updateInterval: 500,
dragAndDrop: true
}
this.opts = extend({}, defaults, opts)
this.editor = CodeMirror( this.opts.container, this.opts )
this.editor.setOption("theme", "mistakes") // borrowed from mistakes.io
this.editor.setCursor(this.editor.lineCount(), 0)
this.editor.on('change', function (e) {
self.emit('change')
if (self.interval) clearTimeout( self.interval )
self.interval = setTimeout( self.update.bind(self), self.opts.updateInterval )
})
this.element = this.editor.getWrapperElement()
this.errorLines = []
if (right) {
this.results = CodeMirror(right, {
mode: 'javascript',
tabSize: 2,
readOnly: 'nocursor'
})
this.results.setOption("theme", 'mistakes')
}
this.update()
if (this.opts.dragAndDrop) this.addDropHandler()
}
inherits(Editor, events.EventEmitter)
Editor.prototype.update = function() {
var hasErrors = this.validate(this.editor.getValue())
this.emit('valid', hasErrors)
return hasErrors
}
Editor.prototype.validate = function(value) {
var self = this
while ( self.errorLines.length > 0 ) {
self.editor.removeLineClass( self.errorLines.shift().num, 'background', 'errorLine' )
}
try {
var result = esprima.parse( value, { tolerant: true, loc: true } ).errors
for ( var i = 0; i < result.length; i ++ ) {
var error = result[ i ]
var lineNumber = error.lineNumber - 1
self.errorLines.push( {num: lineNumber, message: error.message} )
self.editor.addLineClass( lineNumber, 'background', 'errorLine' )
}
} catch ( error ) {
var lineNumber = error.lineNumber - 1
self.errorLines.push( {num: lineNumber, message: error.message} )
self.editor.addLineClass( lineNumber, 'background', 'errorLine' )
}
if (this.results) {
if (self.errorLines.length === 0) return this.results.setValue('')
var numLines = self.errorLines[self.errorLines.length - 1].num
var lines = []
for (var i = 0; i < numLines; i++) lines[i] = ''
self.errorLines.map(function(errLine) {
lines[errLine.num] = errLine.message
})
this.results.setValue(lines.join('\n'))
}
return self.errorLines.length === 0
}
Editor.prototype.addDropHandler = function () {
var self = this
this.element.addEventListener( 'drop', function ( event ) {
event.preventDefault()
event.stopPropagation()
var file = event.dataTransfer.files[ 0 ]
var reader = new FileReader()
reader.onload = function ( event ) {
self.editor.setValue( event.target.result )
}
reader.readAsText( file )
}, false )
}
Editor.prototype.getValue = function() {
return this.editor.getValue()
}
Editor.prototype.setValue = function(value) {
return this.editor.setValue(value)
}