Permalink
Browse files

Callback API (#456)

* Trim whitespace

* Callback for `locateFile` function and throw error if file not exists

* Add callback for create path & save
  • Loading branch information...
1 parent afafbd2 commit 65c2de65bfaf78dcb581bb658eab7d3fa6dbb5af @mrmlnc mrmlnc committed with sergeche Jul 5, 2016
Showing with 119 additions and 78 deletions.
  1. +50 −38 lib/action/base64.js
  2. +22 −20 lib/action/updateImageSize.js
  3. +24 −15 lib/plugin/file.js
  4. +10 −0 test/actions/base64.js
  5. +13 −5 test/actions/updateImageSize.js
View
@@ -13,7 +13,7 @@ define(function(require, exports, module) {
var base64 = require('../utils/base64');
var actionUtils = require('../utils/action');
var editorUtils = require('../utils/editor');
-
+
/**
* Test if <code>text</code> starts with <code>token</code> at <code>pos</code>
* position. If <code>pos</code> is omitted, search from beginning of text
@@ -27,7 +27,7 @@ define(function(require, exports, module) {
pos = pos || 0;
return text.charAt(pos) == token.charAt(0) && text.substr(pos, token.length) == token;
}
-
+
/**
* Encodes image to base64
*
@@ -39,55 +39,67 @@ define(function(require, exports, module) {
function encodeToBase64(editor, imgPath, pos) {
var editorFile = editor.getFilePath();
var defaultMimeType = 'application/octet-stream';
-
+
if (editorFile === null) {
throw "You should save your file before using this action";
}
-
+
// locate real image path
- var realImgPath = file.locateFile(editorFile, imgPath);
- if (realImgPath === null) {
- throw "Can't find " + imgPath + ' file';
- }
-
- file.read(realImgPath, function(err, content) {
- if (err) {
- throw 'Unable to read ' + realImgPath + ': ' + err;
- }
-
- var b64 = base64.encode(String(content));
- if (!b64) {
- throw "Can't encode file content to base64";
+ file.locateFile(editorFile, imgPath, function(realImgPath) {
+ if (realImgPath === null) {
+ throw "Can't find " + imgPath + ' file';
}
-
- b64 = 'data:' + (actionUtils.mimeTypes[String(file.getExt(realImgPath))] || defaultMimeType) +
- ';base64,' + b64;
-
- editor.replaceContent('$0' + b64, pos, pos + imgPath.length);
+
+ file.read(realImgPath, function(err, content) {
+ if (err) {
+ throw 'Unable to read ' + realImgPath + ': ' + err;
+ }
+
+ var b64 = base64.encode(String(content));
+ if (!b64) {
+ throw "Can't encode file content to base64";
+ }
+
+ b64 = 'data:' + (actionUtils.mimeTypes[String(file.getExt(realImgPath))] || defaultMimeType) +
+ ';base64,' + b64;
+
+ editor.replaceContent('$0' + b64, pos, pos + imgPath.length);
+ });
});
-
+
return true;
}
/**
* Decodes base64 string back to file.
* @param {IEmmetEditor} editor
+ * @param {String} filePath to new image
* @param {String} data Base64-encoded file content
* @param {Number} pos Caret position where image is located in the editor
*/
- function decodeFromBase64(editor, data, pos) {
+ function decodeFromBase64(editor, filePath, data, pos) {
// ask user to enter path to file
- var filePath = String(editor.prompt('Enter path to file (absolute or relative)'));
- if (!filePath)
+ filePath = filePath || String(editor.prompt('Enter path to file (absolute or relative)'));
+ if (!filePath) {
return false;
-
- var absPath = file.createPath(editor.getFilePath(), filePath);
- if (!absPath) {
- throw "Can't save file";
}
-
- file.save(absPath, base64.decode( data.replace(/^data\:.+?;.+?,/, '') ));
- editor.replaceContent('$0' + filePath, pos, pos + data.length);
+
+ var editorFile = editor.getFilePath();
+ file.createPath(editorFile, filePath, function(err, absPath) {
+ if (err || !absPath) {
+ throw "Can't save file";
+ }
+
+ var content = data.replace(/^data\:.+?;.+?,/, '');
+ file.save(absPath, base64.decode(content), function(err) {
+ if (err) {
+ throw 'Unable to save ' + absPath + ': ' + err;
+ }
+
+ editor.replaceContent('$0' + filePath, pos, pos + data.length);
+ });
+ });
+
return true;
}
@@ -99,11 +111,11 @@ define(function(require, exports, module) {
* @param {String} profile Output profile name
* @return {Boolean}
*/
- encodeDecodeDataUrlAction: function(editor) {
+ encodeDecodeDataUrlAction: function(editor, filepath) {
var data = String(editor.getSelection());
var caretPos = editor.getCaretPos();
var info = editorUtils.outputInfo(editor);
-
+
if (!data) {
// no selection, try to find image bounds from current caret position
var text = info.content, m;
@@ -123,15 +135,15 @@ define(function(require, exports, module) {
}
}
}
-
+
if (data) {
if (startsWith('data:', data)) {
- return decodeFromBase64(editor, data, caretPos);
+ return decodeFromBase64(editor, filepath, data, caretPos);
} else {
return encodeToBase64(editor, data, caretPos);
}
}
-
+
return false;
}
};
@@ -23,7 +23,7 @@ define(function(require, exports, module) {
*/
function updateImageSizeHTML(editor) {
var offset = editor.getCaretPos();
-
+
// find tag from current caret position
var info = editorUtils.outputInfo(editor);
var xmlElem = xmlEditTree.parseFromPosition(info.content, offset, true);
@@ -33,7 +33,7 @@ define(function(require, exports, module) {
var compoundData = xmlElem.range(true);
xmlElem.value('width', size.width);
xmlElem.value('height', size.height, xmlElem.indexOf('width') + 1);
-
+
actionUtils.compoundUpdate(editor, utils.extend(compoundData, {
data: xmlElem.toString(),
caret: offset
@@ -42,14 +42,14 @@ define(function(require, exports, module) {
});
}
}
-
+
/**
* Updates image size of CSS property
* @param {IEmmetEditor} editor
*/
function updateImageSizeCSS(editor) {
var offset = editor.getCaretPos();
-
+
// find tag from current caret position
var info = editorUtils.outputInfo(editor);
var cssRule = cssEditTree.parseFromPosition(info.content, offset, true);
@@ -62,7 +62,7 @@ define(function(require, exports, module) {
var compoundData = cssRule.range(true);
cssRule.value('width', size.width + 'px');
cssRule.value('height', size.height + 'px', cssRule.indexOf('width') + 1);
-
+
actionUtils.compoundUpdate(editor, utils.extend(compoundData, {
data: cssRule.toString(),
caret: offset
@@ -72,7 +72,7 @@ define(function(require, exports, module) {
}
}
}
-
+
/**
* Returns image dimensions for source
* @param {IEmmetEditor} editor
@@ -86,23 +86,25 @@ define(function(require, exports, module) {
fileContent = base64.decode( src.replace(/^data\:.+?;.+?,/, '') );
return callback(actionUtils.getImageSize(fileContent));
}
-
- var absPath = file.locateFile(editor.getFilePath(), src);
- if (absPath === null) {
- throw "Can't find " + src + ' file';
- }
-
- file.read(absPath, function(err, content) {
- if (err) {
- throw 'Unable to read ' + absPath + ': ' + err;
+
+ var filePath = editor.getFilePath();
+ file.locateFile(filePath, src, function(absPath) {
+ if (absPath === null) {
+ throw "Can't find " + src + ' file';
}
-
- content = String(content);
- callback(actionUtils.getImageSize(content));
+
+ file.read(absPath, function(err, content) {
+ if (err) {
+ throw 'Unable to read ' + absPath + ': ' + err;
+ }
+
+ content = String(content);
+ callback(actionUtils.getImageSize(content));
+ });
});
}
}
-
+
return {
updateImageSizeAction: function(editor) {
// this action will definitely won’t work in SASS dialect,
@@ -112,7 +114,7 @@ define(function(require, exports, module) {
} else {
updateImageSizeHTML(editor);
}
-
+
return true;
}
};
View
@@ -31,7 +31,7 @@ define(function(require, exports, module) {
path = r('path');
_transport.http = r('http');
_transport.https = r('https');
- } catch(e) {}
+ } catch(e) { }
}
})(require);
@@ -156,21 +156,22 @@ define(function(require, exports, module) {
* @param {String} fileName
* @return {String} Returns null if <code>fileName</code> cannot be located
*/
- locateFile: function(editorFile, fileName) {
+ locateFile: function(editorFile, fileName, callback) {
if (isURL(fileName)) {
- return fileName;
+ return callback(fileName);
}
- var dirname = editorFile, f;
+ var dirname = editorFile
+ var filepath;
fileName = fileName.replace(/^\/+/, '');
while (dirname && dirname !== path.dirname(dirname)) {
dirname = path.dirname(dirname);
- f = path.join(dirname, fileName);
- if (fs.existsSync(f))
- return f;
+ filepath = path.join(dirname, fileName);
+ if (fs.existsSync(filepath))
+ return callback(filepath);
}
- return '';
+ callback(null);
},
/**
@@ -181,21 +182,29 @@ define(function(require, exports, module) {
* @return {String}
*/
createPath: function(parent, fileName, callback) {
- var stat = fs.statSync(parent);
- if (stat && !stat.isDirectory()) {
- parent = path.dirname(parent);
- }
+ fs.stat(parent, function(err, stat) {
+ if (err) {
+ return callback(err);
+ }
+
+ if (stat.isFile()) {
+ parent = path.dirname(parent);
+ }
- return callback(path.resolve(parent, fileName));
+ var filepath = path.resolve(parent, fileName);
+ callback(null, filepath);
+ });
},
/**
* Saves <code>content</code> as <code>file</code>
* @param {String} file File's absolute path
* @param {String} content File content
*/
- save: function(file, content) {
- fs.writeFileSync(file, content, 'ascii');
+ save: function(file, content, callback) {
+ fs.writeFile(file, content, 'ascii', function(err) {
+ callback(err ? err : null);
+ });
},
/**
@@ -10,4 +10,14 @@ describe('Base64 encoder/decoder', function() {
action.encodeDecodeDataUrlAction(editor);
assert.equal(editor.getContent(), '<img src="data:image/gif;base64,R0lGODdhAQABAIAAAAAAAAAAACH5BAEAAAEALAAAAAABAAEAAAICTAEAOw==" />');
});
+
+ it('should return an error if the file does not exist', function() {
+ editor.replaceContent('<img src="${0}error.gif" />');
+
+ try {
+ action.encodeDecodeDataUrlAction(editor);
+ } catch (err) {
+ assert.equal(err, 'Can\'t find error.gif file');
+ }
+ });
});
@@ -14,31 +14,39 @@ describe('Update Image Size action', function() {
// insert attributes
run('<img${0} src="data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==" alt="" />');
assert.equal(editor.getContent(), '<img src="data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==" alt="" width="3" height="2" />');
-
+
// update existing attributes
run('<img${0} src="data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==" width="100" height="100" alt="" />');
assert.equal(editor.getContent(), '<img src="data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==" width="3" height="2" alt="" />');
-
+
// update existing attribute and insert new one
run('<img${0} src="data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==" width="100" alt="" />');
assert.equal(editor.getContent(), '<img src="data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==" width="3" height="2" alt="" />');
});
it('should work for CSS', function() {
editor.setSyntax('css');
-
+
// Added "width" and "height" properties
run('.test {\n\tbackgrou${0}nd: url(data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==);\n}');
assert.equal(editor.getContent(), '.test {\n\tbackground: url(data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==);\n\twidth: 3px;\n\theight: 2px;\n}');
// Updated "width" and "height" properties
run('.test {\n\tbackgrou${0}nd: url(data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==);\n\twidth: 100px;\n\theight: 100px;\n}');
assert.equal(editor.getContent(), '.test {\n\tbackground: url(data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==);\n\twidth: 3px;\n\theight: 2px;\n}');
-
+
// Updated "width" property and added "height"
run('.test {\n\tbackgrou${0}nd: url(data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==);\n\twidth: 100px;\n}');
assert.equal(editor.getContent(), '.test {\n\tbackground: url(data:image/gif;base64,R0lGODlhAwACAHAAACH5BAUAAAAALAAAAAADAAIAQAIChF8AOw==);\n\twidth: 3px;\n\theight: 2px;\n}');
-
+
editor.setSyntax('html');
});
+
+ it('should return an error if the file does not exist', function() {
+ try {
+ run('<img src="${0}error.gif" />');
+ } catch (err) {
+ assert.equal(err, 'Can\'t find error.gif file');
+ }
+ });
});

0 comments on commit 65c2de6

Please sign in to comment.