Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
import loop-drop-editor/raw directly into project
- Loading branch information
Showing
4 changed files
with
236 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
var safeEval = require('notevil') | ||
|
||
module.exports.parse = function(literal){ | ||
literal = literal.replace(/\{\{([\w\W]*?)\}\}/g, function(_, exp){ | ||
return '{$: ' + JSON.stringify(fixIndent(exp)) + '}' | ||
}) | ||
return safeEval('j = {' + literal + '}') | ||
} | ||
|
||
module.exports.stringify = function(object){ | ||
return getObjectContent(object).trim() | ||
} | ||
|
||
module.exports.eval = xval | ||
|
||
function xval(object, context){ | ||
if (Array.isArray(object)){ | ||
return object.map(function(x){ | ||
return xval(x, context) | ||
}) | ||
} else if (object instanceof Object) { | ||
if (object.$){ | ||
return safeEval(object.$, context) | ||
} else { | ||
var res = {} | ||
Object.keys(object).forEach(function(key){ | ||
res[key] = xval(object[key], context) | ||
}) | ||
return res | ||
} | ||
} else { | ||
return object | ||
} | ||
} | ||
|
||
function getObjectContent(object){ | ||
var result = Object.keys(object).map(function(key){ | ||
return escapeKey(key) + ': ' + getLiteral(object[key]) | ||
}) | ||
return smartWrap(result) | ||
} | ||
|
||
var numberMatch = /^[0-9]/ | ||
|
||
function isNumeric(key){ | ||
return typeof key === 'string' && !!numberMatch.exec(key) | ||
} | ||
|
||
function escapeKey(key){ | ||
if (~key.indexOf(' ') || ~key.indexOf('"') || ~key.indexOf('-') || isNumeric(key)){ | ||
return JSON.stringify(String(key)) | ||
} else { | ||
return key | ||
} | ||
} | ||
|
||
function getArrayContent(array){ | ||
var result = array.map(function(obj){ | ||
return getLiteral(obj) | ||
}) | ||
return smartWrap(result) | ||
} | ||
|
||
function smartWrap(array){ | ||
if (array.join(', ').length>50){ | ||
return '\n' + array.join(',\n') + '\n' | ||
} else { | ||
return ' ' + array.join(', ') + ' ' | ||
} | ||
} | ||
|
||
function indent(text){ | ||
return text.replace(/\n(.)/g, '\n $1') | ||
} | ||
|
||
function getLiteral(value){ | ||
if (!value || typeof value !== 'object'){ | ||
return JSON.stringify(value) | ||
} else if (Array.isArray(value)){ | ||
return '[' + indent(getArrayContent(value)) + ']' | ||
} else if (value && '$' in value){ | ||
return '{{' + value['$'] + '}}' | ||
} else { | ||
return '{' + indent(getObjectContent(value)) + '}' | ||
} | ||
} | ||
|
||
var matchStartSpace = /^(\s+)/ | ||
var matchNewLineWrapper = /^\s*\n|\n\s*$/g | ||
|
||
function fixIndent(text){ | ||
if (text && ~text.indexOf('\n')){ | ||
text = text.replace(matchNewLineWrapper, '') | ||
var match = matchStartSpace.exec(text) | ||
var indent = match && match[1].length | ||
if (indent){ | ||
text = '\n' + text.replace(/(^|\n)(\s+)/g, function(_, start, spaces){ | ||
return start + spaces.slice(indent-2) | ||
}) + '\n' | ||
} | ||
} | ||
|
||
return text | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
|
||
var JSMN = require('../../lib/jsmn.js') | ||
var deepEqual = require('deep-equal') | ||
var watch = require('observ/watch') | ||
|
||
var ace = require('brace') | ||
require('brace/mode/javascript') | ||
require('brace/theme/ambiance') | ||
|
||
var NO_TRANSACTION = {} | ||
|
||
module.exports = RawEditor | ||
|
||
function RawEditor(fileObject){ | ||
if (!(this instanceof RawEditor)){ | ||
return new RawEditor(fileObject) | ||
} | ||
this.fileObject = fileObject | ||
this.file = fileObject && fileObject.file | ||
} | ||
|
||
RawEditor.prototype.type = 'Widget' | ||
|
||
RawEditor.prototype.init = function(){ | ||
var element = document.createElement('div') | ||
element.className = 'RawEditor' | ||
|
||
var el = document.createElement('div') | ||
|
||
var textEditor = this.editor = ace.edit(el) | ||
|
||
window.editors = window.editors || [] | ||
window.editors.push(textEditor) | ||
|
||
textEditor.setTheme('ace/theme/ambiance'); | ||
textEditor.session.setMode('ace/mode/javascript') | ||
textEditor.session.setUseWorker(false) | ||
textEditor.session.setTabSize(2) | ||
textEditor.renderer.setScrollMargin(20,100) | ||
textEditor.renderer.setPadding(20) | ||
textEditor.renderer.setShowGutter(false) | ||
|
||
var currentFile = null | ||
var self = this | ||
|
||
var currentTransaction = NO_TRANSACTION | ||
var currentSaveTransaction = NO_TRANSACTION | ||
|
||
textEditor.setFile = function(fileObject){ | ||
clearTimeout(saveTimer) | ||
|
||
if (self.release){ | ||
self.release() | ||
self.release = null | ||
} | ||
|
||
currentFile = fileObject | ||
|
||
if (fileObject){ | ||
self.release = watch(fileObject, update) | ||
} | ||
} | ||
|
||
function save(){ | ||
var value = textEditor.session.getValue() | ||
if (currentFile){ | ||
try { | ||
var object = JSMN.parse(value) | ||
currentSaveTransaction = object | ||
currentFile.set(object) | ||
currentSaveTransaction = NO_TRANSACTION | ||
} catch (ex) {} | ||
} | ||
} | ||
|
||
function update(){ | ||
var data = currentFile ? currentFile() : null | ||
if (data && currentSaveTransaction !== data._diff && !deepEqual(currentSaveTransaction,data)){ | ||
var newValue = JSMN.stringify(data || {}) | ||
currentTransaction = newValue | ||
textEditor.session.setValue(newValue, -1) | ||
currentTransaction = NO_TRANSACTION | ||
} | ||
} | ||
|
||
var blurTimer = null | ||
textEditor.on('focus', function(){ | ||
clearTimeout(blurTimer) | ||
}) | ||
|
||
textEditor.on('blur', function(){ | ||
clearTimeout(blurTimer) | ||
blurTimer = setTimeout(function(){ | ||
if (!textEditor.isFocused()){ | ||
update() | ||
} | ||
}, 100) | ||
}) | ||
|
||
var saveTimer = null | ||
textEditor.on('change', function(){ | ||
if (currentTransaction === NO_TRANSACTION){ | ||
clearTimeout(saveTimer) | ||
saveTimer = setTimeout(save, 100) | ||
} | ||
}) | ||
|
||
textEditor.setFile(this.fileObject) | ||
|
||
element.appendChild(el) | ||
return element | ||
} | ||
|
||
RawEditor.prototype.update = function(prev, elem){ | ||
this.editor = prev.editor | ||
this.release = prev.release | ||
|
||
if (prev.file !== this.file){ | ||
this.editor.setFile(this.fileObject) | ||
} | ||
return elem | ||
} | ||
|
||
RawEditor.prototype.destroy = function(elem){ | ||
this.editor.destroy() | ||
this.release && this.release() | ||
this.release = null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters