Skip to content

Commit

Permalink
Feature: Nodejs as a Web Service - pt. 6. (madskristensen#381)
Browse files Browse the repository at this point in the history
* Server: Adds services: CoffeeLint, JSCS, JsHint
  and TSLint.
* Server: Fixes error messages.
* Server: Uses Regex for error parsing.
* Server: Removes debug messages.
* Server: Robust port discovery method.
* Server: Removed Dispose().
* Client: Adds AsyncLock to NodeServer.
* PreBuild: Adds XRegExp package for named
  capturing groups.
  • Loading branch information
am11 authored and nycdotnet committed Jul 16, 2014
1 parent 7487b05 commit 9314818
Show file tree
Hide file tree
Showing 17 changed files with 466 additions and 94 deletions.
3 changes: 2 additions & 1 deletion EditorExtensions/PreBuildTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public override bool Execute()
InstallModuleAsync("iced", "iced-coffee-script"),
InstallModuleAsync("LiveScript", "LiveScript"),
InstallModuleAsync("coffeelint", "coffeelint"),
InstallModuleAsync("sjs", "sweet.js")
InstallModuleAsync("sjs", "sweet.js"),
InstallModuleAsync("xregexp", "xregexp")
).Result.Where(r => r != ModuleInstallResult.AlreadyPresent);

if (moduleResults.Contains(ModuleInstallResult.Error))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ var processAutoprefixer = function (cssContent, mapContent, browsers, from, to)
try {
result = autoprefixer(browsers.split(",").map(function (s) { return s.trim(); }));
} catch (e) {
// Return same css and map back so compilers can continue.
return {
Success: false,
Remarks: "Invalid browser provided! See autoprefixer docs for list of valid browsers options.",
Remarks: "Autoprefixer: Invalid browser provided! See autoprefixer docs for list of valid browsers options.",
css: cssContent,
map: mapContent
};
Expand Down Expand Up @@ -43,14 +44,14 @@ var processAutoprefixer = function (cssContent, mapContent, browsers, from, to)
//#region Handler
var handleAutoPrefixer = function (writer, params) {
if (!fs.existsSync(params.sourceFileName)) {
writer.write(JSON.stringify({ Success: false, Remarks: "Input file not found!" }));
writer.write(JSON.stringify({ Success: false, Remarks: "Autoprefix: Input file not found!" }));
writer.end();
return;
}

fs.readFile(params.sourceFileName, 'utf8', function (err, data) {
if (err) {
writer.write(JSON.stringify({ Success: false, Remarks: "Error reading input file." }));
writer.write(JSON.stringify({ Success: false, Remarks: "Autoprefixer: Error reading input file.", Details: err }));
writer.end();
return;
}
Expand All @@ -67,7 +68,7 @@ var handleAutoPrefixer = function (writer, params) {
Success: true,
Remarks: "Successful!",
Output: {
outputContent: output.css
Content: output.css
}
}));

Expand Down
58 changes: 58 additions & 0 deletions EditorExtensions/Resources/server/services/srv-coffeelint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//#region Imports
var coffeelint = require("coffeelint"),
configFinder = require("coffeelint/lib/configfinder"),
fs = require("fs");
//#endregion

//#region Reporter
var reporter = function (results, writer, path) {
var errorItems = results.map(function (error) {
return {
Line: error.lineNumber,
Message: "CoffeeLint: " + error.message,
FileName: path
};
});

writer.write(JSON.stringify({
Success: true,
Remarks: "Successful!",
Output: {
Content: errorItems
}
}));
writer.end();
}
//#endregion

//#region Handler
var handleCoffeeLint = function (writer, params) {
var tempError = console.error;
console.error = function () { /* waste log messages toDevNull */ };

var config = configFinder.getConfig(params.sourceFileName);

console.error = tempError;

if (config == null) {
writer.write(JSON.stringify({ Success: false, Remarks: "CoffeeLint: Invalid Config file" }));
writer.end();
return;
}

fs.readFile(params.sourceFileName, 'utf8', function (err, data) {
if (err) {
writer.write(JSON.stringify({ Success: false, Remarks: "CoffeeLint: Error reading input file.", Details: err }));
writer.end();
return;
}

var results = coffeelint.lint(data, config);
reporter(results, writer, params.sourceFileName);
});
};
//#endregion

//#region Exports
module.exports = handleCoffeeLint;
//#endregion
23 changes: 18 additions & 5 deletions EditorExtensions/Resources/server/services/srv-coffeescript.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//#region Imports
var coffeescript = require("coffee-script"),
path = require("path"),
fs = require("fs");
fs = require("fs"),
xRegex = require("xregexp").XRegExp;
//#endregion

//#region Handler
Expand All @@ -16,7 +17,7 @@ var handleCoffeeScript = function (writer, params) {

fs.readFile(params.sourceFileName, 'utf8', function (err, data) {
if (err) {
writer.write(JSON.stringify({ Success: false, Remarks: err }));
writer.write(JSON.stringify({ Success: false, Remarks: "CoffeeScript: Error reading input file.", Details: err }));
writer.end();
return;
}
Expand All @@ -36,13 +37,25 @@ var handleCoffeeScript = function (writer, params) {
Success: true,
Remarks: "Successful!",
Output: {
outputContent: js,
mapContent: map
Content: js,
Map: map
}
}));
writer.end();
} catch (error) {
writer.write(JSON.stringify({ Success: false, Remarks: error.stack || ("" + error) }));
var regex = xRegex.exec(error, xRegex(".*:.\\d*:.\\d*: error: (?<fullMessage>(?<message>.*)(\\n*.*)*)", 'gi'));
writer.write(JSON.stringify({
Success: false,
Remarks: "CoffeeScript: An error has occured while processing your request.",
Details: regex.message,
Errors: {
Line: error.location.first_line,
Column: error.location.first_column,
Message: regex.message,
FileName: error.filename,
FullMessage: regex.fullMessage
}
}));
writer.end();
}
});
Expand Down
23 changes: 18 additions & 5 deletions EditorExtensions/Resources/server/services/srv-icedcoffeescript.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//#region Imports
var icedcoffeescript = require("iced-coffee-script"),
path = require("path"),
fs = require("fs");
fs = require("fs"),
xRegex = require("xregexp").XRegExp;
//#endregion

//#region Handler
Expand All @@ -17,7 +18,7 @@ var handleIcedCoffeeScript = function (writer, params) {

fs.readFile(params.sourceFileName, 'utf8', function (err, data) {
if (err) {
writer.write(JSON.stringify({ Success: false, Remarks: "Error reading input file." }));
writer.write(JSON.stringify({ Success: false, Remarks: "IcedCoffeeScript: Error reading input file.", Details: err }));
writer.end();
return;
}
Expand All @@ -37,13 +38,25 @@ var handleIcedCoffeeScript = function (writer, params) {
Success: true,
Remarks: "Successful!",
Output: {
outputContent: js,
mapContent: map
Content: js,
Map: map
}
}));
writer.end();
} catch (error) {
writer.write(JSON.stringify({ Success: false, Remarks: error.stack || ("" + error) }));
var regex = xRegex.exec(error, xRegex(".*:.\\d*:.\\d*: error: (?<fullMessage>(?<message>.*)(\\n*.*)*)", 'gi'));
writer.write(JSON.stringify({
Success: false,
Remarks: "IcedCoffeeScript: An error has occured while processing your request.",
Details: error.message,
Errors: {
Line: error.location.first_line,
Column: error.location.first_column,
Message: regex.message,
FileName: error.filename,
FullMessage: regex.fullMessage
}
}));
writer.end();
}
});
Expand Down
58 changes: 55 additions & 3 deletions EditorExtensions/Resources/server/services/srv-jscs.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,63 @@
//#region Imports
var jscs = require("jscs");
var jscs = require("jscs/lib/checker"),
configFile = require("jscs/lib/cli-config"),
path = require("path"),
vow = require('vow');
//#endregion

//#region Reporter
var reporter = function (results, writer) {
var errorItems = [];
var errors = results[0];
var fileName = errors.getFilename();

if (!errors.isEmpty()) {
errorItems = errors.getErrorList().map(function (error) {
return {
Line: error.line,
Column: error.column + 1,
Message: "JSCS: " + error.message,
FileName: fileName
};
});
}

writer.write(JSON.stringify({
Success: true,
Remarks: "Successful!",
Output: {
Content: errorItems
}
}));
writer.end();
};
//#endregion

//#region Handler
var handleJSCS = function (writer, params) {
writer.write(JSON.stringify({ Success: false, Remarks: "Service Not Implemented." }));
writer.end();
var config;

try {
config = configFile.load(null, path.dirname(params.sourceFileName));
} catch (e) {
writer.write(JSON.stringify({ Success: false, Remarks: "JSCS: Invalid Config file", Details: e.message || e.stack }));
writer.end();
return;
}

var checker = new jscs();

checker.registerDefaultRules();
checker.configure(config);

// Unlike their cli, we don't need Vows'defer() and call all().
// All we need is proceed on done().
vow.done(checker.checkPath(params.sourceFileName),
function (results) { reporter(results, writer); },
function () { // They should probably need add this to their CLI code too: https://github.com/mdevils/node-jscs/issues/490
writer.write(JSON.stringify({ Success: false, Remarks: "JSCS: Cannot parse invalid JavaScript." }));
writer.end();
});
};
//#endregion

Expand Down
43 changes: 40 additions & 3 deletions EditorExtensions/Resources/server/services/srv-jshint.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,48 @@
//#region Imports
var jshint = require("jshint");
var jshint = require("jshint/src/cli");
//#endregion

//#region Reporter
var reporter = function (results, writer) {
var messageItems = results.map(function (result) {
var error = result.error;

if (error.reason === "Missing radix parameter.") {
error.reason = "When using the parseInt function, remember to specify the radix parameter. Example: parseInt('3', 10)";
}

return {
Line: parseInt(error.line, 10),
Column: parseInt(error.character, 10),
Message: "JsHint (" + error.code + "): " + error.reason,
FileName: result.file
};
});

writer.write(JSON.stringify({
Success: true,
Remarks: "Successful!",
Output: {
Content: messageItems
}
}));
writer.end();
}
//#endregion

//#region Handler
var handleJSHint = function (writer, params) {
writer.write(JSON.stringify({ Success: false, Remarks: "Service Not Implemented." }));
writer.end();
// Override jshint's export.exit(1). The only reason this would exit
// in case of Web Essentials is the invalid JSON.
jshint.exit = function () {
writer.write(JSON.stringify({ Success: false, Remarks: "JsHint: Invalid Config file" }));
writer.end();
};

jshint.run({
args: [params.sourceFileName],
reporter: function (results) { reporter(results, writer); }
});
};
//#endregion

Expand Down
24 changes: 14 additions & 10 deletions EditorExtensions/Resources/server/services/srv-less.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,27 @@ var less = require("less"),

//#region Handler
var handleLess = function (writer, params) {
if (!fs.existsSync(params.sourceFileName)) {
writer.write(JSON.stringify({ Success: false, Remarks: "Input file not found!" }));
writer.end();
return;
}

fs.readFile(params.sourceFileName, 'utf8', function (err, data) {
if (err) {
writer.write(JSON.stringify({ Success: false, Remarks: err }));
writer.write(JSON.stringify({ Success: false, Remarks: "LESS: Error reading input file.", Details: err }));
writer.end();
return;
}

try {
new (less.Parser)({ filename: params.sourceFileName }).parse(data, function (e, tree) {
if (e) {
writer.write(JSON.stringify({ Success: false, Remarks: "Error reading input file." }));
writer.write(JSON.stringify({
Success: false,
Remarks: "LESS: Error parsing input file.",
Details: e.message,
Errors: {
Line: e.line,
Column: e.column,
Message: e.message,
FileName: e.filename
}
}));
writer.end();
return;
}
Expand Down Expand Up @@ -68,8 +72,8 @@ var handleLess = function (writer, params) {
Success: true,
Remarks: "Successful!",
Output: {
outputContent: css,
mapContent: map
Content: css,
Map: map
}
}));
writer.end();
Expand Down
Loading

0 comments on commit 9314818

Please sign in to comment.