Skip to content

Commit

Permalink
Feature: Nodejs as a Web Service - pt. 7. (madskristensen#381)
Browse files Browse the repository at this point in the history
* Client: Wiring-up with new base.
* Server: Fixed error handling.
* Test: Updated to FluentAssertions 3.0.
  • Loading branch information
am11 authored and nycdotnet committed Jul 16, 2014
1 parent 9314818 commit e5123c3
Show file tree
Hide file tree
Showing 37 changed files with 569 additions and 756 deletions.
68 changes: 14 additions & 54 deletions EditorExtensions/CoffeeScript/Compilers/CoffeeScriptCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System.ComponentModel.Composition;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using MadsKristensen.EditorExtensions.Settings;
using Microsoft.VisualStudio.Utilities;

Expand All @@ -13,62 +8,27 @@ namespace MadsKristensen.EditorExtensions.CoffeeScript
[ContentType("CoffeeScript")]
public class CoffeeScriptCompiler : JsCompilerBase
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\coffee-script\bin\coffee");
private static readonly Regex _errorParsingPattern = new Regex(@"\A(?<fileName>.*):(?<line>.\d*):(?<column>.\d*): error: (?<fullMessage>(?<message>.*)(\n*.*)*)", RegexOptions.Multiline | RegexOptions.Compiled);
private static readonly Regex _sourceMapInJs = new Regex(@"\/\/\\*#.*(?i:sourceMappingURL)([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*", RegexOptions.Multiline);

public override bool GenerateSourceMap { get { return WESettings.Instance.CoffeeScript.GenerateSourceMaps && !WESettings.Instance.CoffeeScript.MinifyInPlace; } }
public override string ServiceName { get { return "CoffeeScript"; } }
protected override string CompilerPath { get { return _compilerPath; } }
public override bool RequireMatchingFileName { get { return true; } }
protected override Regex ErrorParsingPattern { get { return _errorParsingPattern; } }
public override bool MinifyInPlace { get { return WESettings.Instance.CoffeeScript.MinifyInPlace; } }
public override bool GenerateSourceMap { get { return WESettings.Instance.CoffeeScript.GenerateSourceMaps && !MinifyInPlace; } }

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
protected override string GetPath(string sourceFileName, string targetFileName)
{
var args = new StringBuilder();
string mapFileName = targetFileName + ".map";
var parameters = new NodeServerUtilities.Parameters();

if (!WESettings.Instance.CoffeeScript.WrapClosure)
args.Append("--bare ");
parameters.Add("service", ServiceName);
parameters.Add("sourceFileName", sourceFileName);
parameters.Add("targetFileName", targetFileName);
parameters.Add("mapFileName", mapFileName);

if (GenerateSourceMap)
args.Append("--map ");

args.AppendFormat(CultureInfo.CurrentCulture, "--output \"{0}\" --compile \"{1}\"", Path.GetDirectoryName(targetFileName), sourceFileName);

return Task.FromResult(args.ToString());
}

protected async override Task<string> PostProcessResult(string resultSource, string sourceFileName, string targetFileName, string mapFileName)
{
Logger.Log(ServiceName + ": " + Path.GetFileName(sourceFileName) + " compiled.");

string realTargetFileName = Path.Combine(Path.GetDirectoryName(targetFileName), FileHelpers.GetFileNameWithoutExtension(targetFileName) + ".js");

if (WESettings.Instance.CoffeeScript.MinifyInPlace)
{
File.Delete(realTargetFileName); // Because CoffeeScript compiler doesn't take custom file name as parameter.
}
parameters.Add("sourceMapURL");

if (GenerateSourceMap)
{
string targetMap = Path.ChangeExtension(realTargetFileName, ".map");

if (File.Exists(targetMap))
File.Delete(targetMap);

File.Move(mapFileName, targetMap);

resultSource = UpdateSourceLinkInJsComment(resultSource, FileHelpers.RelativePath(targetFileName, targetMap));
}

return await Task.FromResult(resultSource);
}
if (!WESettings.Instance.CoffeeScript.WrapClosure)
parameters.Add("bare");

private static string UpdateSourceLinkInJsComment(string content, string sourceMapRelativePath)
{
return _sourceMapInJs.Replace(content,
string.Format(CultureInfo.InvariantCulture,
"//# sourceMappingURL={0}", sourceMapRelativePath));
return parameters.FlattenParameters();
}
}
}
}
17 changes: 1 addition & 16 deletions EditorExtensions/CoffeeScript/Linters/CoffeeLintCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,13 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using MadsKristensen.EditorExtensions.JavaScript;

namespace MadsKristensen.EditorExtensions.CoffeeScript
{
public class CoffeeLintCompiler : JsHintCompiler
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\coffeelint\bin\coffeelint");
private static readonly string _reporter = Path.Combine(WebEssentialsResourceDirectory, @"Scripts\coffeeReporter.js");
public new readonly static string ConfigFileName = "coffeelint.json";

public override IEnumerable<string> SourceExtensions { get { return new[] { ".coffee", ".iced" }; } }
public override string ServiceName { get { return "CoffeeLint"; } }
protected override string CompilerPath { get { return _compilerPath; } }

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
{
GetOrCreateGlobalSettings(ConfigFileName); // Ensure that default settings exist

return Task.FromResult(string.Format(CultureInfo.CurrentCulture, "--reporter \"{0}\" \"{1}\"",
_reporter,
sourceFileName));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.ComponentModel.Composition;
using System.IO;
using System.Threading.Tasks;
using MadsKristensen.EditorExtensions.CoffeeScript;
using Microsoft.VisualStudio.Utilities;

Expand All @@ -10,14 +8,11 @@ namespace MadsKristensen.EditorExtensions.IcedCoffeeScript
[ContentType(IcedCoffeeScriptContentTypeDefinition.IcedCoffeeScriptContentType)]
public class IcedCoffeeScriptCompiler : CoffeeScriptCompiler
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\iced-coffee-script\bin\coffee");

public override string ServiceName { get { return "IcedCoffeeScript"; } }
protected override string CompilerPath { get { return _compilerPath; } }

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
protected override string GetPath(string sourceFileName, string targetFileName)
{
return Task.FromResult("--runtime inline " + base.GetArguments(sourceFileName, targetFileName, mapFileName).Result);
return base.GetPath(sourceFileName, targetFileName) + "runtime=inline";
}
}
}
}
37 changes: 2 additions & 35 deletions EditorExtensions/JavaScript/Linters/JsCodeStyleCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,10 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;


namespace MadsKristensen.EditorExtensions.JavaScript
{
public class JsCodeStyleCompiler : JsHintCompiler
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\jscs\bin\jscs");
private static readonly string _reporter = Path.Combine(WebEssentialsResourceDirectory, @"Scripts\jscsReporter.js");
public new static readonly string ConfigFileName = ".jscsrc";

public override IEnumerable<string> SourceExtensions { get { return new[] { ".js" }; } }
public override string ServiceName { get { return "JSCS"; } }
protected override string CompilerPath { get { return _compilerPath; } }

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
{
GetOrCreateGlobalSettings(ConfigFileName); // Ensure that default settings exist

return Task.FromResult(string.Format(CultureInfo.CurrentCulture, "--reporter \"{0}\" --config \"{1}\" \"{2}\"",
_reporter,
FindLocalSettings(sourceFileName, ConfigFileName) ?? GetOrCreateGlobalSettings(ConfigFileName),
sourceFileName));
}

protected static string FindLocalSettings(string sourcePath, string settingsName)
{
string dir = Path.GetDirectoryName(sourcePath);

while (!File.Exists(Path.Combine(dir, settingsName)))
{
dir = Path.GetDirectoryName(dir);
if (String.IsNullOrEmpty(dir))
return null;
}

return Path.Combine(dir, settingsName);
}
}
}
}
31 changes: 13 additions & 18 deletions EditorExtensions/JavaScript/Linters/JsHintCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;

namespace MadsKristensen.EditorExtensions.JavaScript
{
public interface ILintCompiler
{
Task<CompilerResult> CheckAsync(string sourcePath);
string ServiceName { get; }
IEnumerable<string> SourceExtensions { get; }
Task<CompilerResult> CheckAsync(string sourcePath);
}

public class JsHintCompiler : NodeExecutorBase, ILintCompiler
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\jshint\bin\jshint");
// JsHint Reported is located in Resources\Scripts\ directory. Read more at http://www.jshint.com/docs/reporters/
private static readonly string _reporter = Path.Combine(WebEssentialsResourceDirectory, @"Scripts\jshintReporter.js");
public static readonly string ConfigFileName = ".jshintrc";

public override string TargetExtension { get { return null; } }
public virtual IEnumerable<string> SourceExtensions { get { return new[] { ".js" }; } }

public override string ServiceName { get { return "JsHint"; } }
public override string TargetExtension { get { return null; } }
public override bool MinifyInPlace { get { return false; } }
public override bool GenerateSourceMap { get { return false; } }
protected override string CompilerPath { get { return _compilerPath; } }
protected override Func<string, IEnumerable<CompilerError>> ParseErrors
{
get { return ParseErrorsWithJson; }
}

public Task<CompilerResult> CheckAsync(string sourcePath)
{
Expand All @@ -49,18 +41,21 @@ public static string GetOrCreateGlobalSettings(string fileName)
return globalFile;
}

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
protected override string GetPath(string sourceFileName, string targetFileName)
{
GetOrCreateGlobalSettings(ConfigFileName); // Ensure that default settings exist

return Task.FromResult(string.Format(CultureInfo.CurrentCulture, "--reporter \"{0}\" \"{1}\"",
_reporter,
sourceFileName));
var parameters = new NodeServerUtilities.Parameters();

parameters.Add("service", ServiceName);
parameters.Add("sourceFileName", sourceFileName);

return parameters.FlattenParameters();
}

protected async override Task<string> PostProcessResult(string resultSource, string sourceFileName, string targetFileName, string mapFileName)
protected override string PostProcessResult(CompilerResult result)
{
return await Task.FromResult(resultSource);
return result.Result;
}
}
}
51 changes: 27 additions & 24 deletions EditorExtensions/LESS/Compilers/LessCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System.ComponentModel.Composition;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using MadsKristensen.EditorExtensions.Settings;
using Microsoft.VisualStudio.Utilities;

Expand All @@ -12,29 +8,36 @@ namespace MadsKristensen.EditorExtensions.Less
[ContentType("LESS")]
public class LessCompiler : CssCompilerBase
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\less\bin\lessc");
private static readonly Regex _errorParsingPattern = new Regex(@"\A(?<message>.+) in (?<fileName>.+) on line (?<line>\d+), column (?<column>\d+):$", RegexOptions.Multiline | RegexOptions.Compiled);

public override string TargetExtension { get { return ".css"; } }
public override string ServiceName { get { return "LESS"; } }
protected override string CompilerPath { get { return _compilerPath; } }
protected override Regex ErrorParsingPattern { get { return _errorParsingPattern; } }
public override bool GenerateSourceMap { get { return WESettings.Instance.Less.GenerateSourceMaps && !WESettings.Instance.Less.MinifyInPlace; } }
public override bool MinifyInPlace { get { return WESettings.Instance.Less.MinifyInPlace; } }
public override bool GenerateSourceMap { get { return WESettings.Instance.Less.GenerateSourceMaps && !MinifyInPlace; } }

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
protected override string GetPath(string sourceFileName, string targetFileName)
{
string mapDirectory = Path.GetDirectoryName(mapFileName);

// Source maps would be generated in "ALL" cases (regardless of the settings).
// If the option in settings is disabled, we will delete the map file once the
// B64VLQ values are extracted.
return Task.FromResult(string.Format(CultureInfo.CurrentCulture,
"--no-color --relative-urls --strict-math={0} --source-map-basepath=\"{1}\" --source-map=\"{2}\" \"{3}\" \"{4}\"",
WESettings.Instance.Less.StrictMath ? "on" : "off",
mapDirectory,
mapFileName,
sourceFileName,
targetFileName));
string mapFileName = targetFileName + ".map";
var parameters = new NodeServerUtilities.Parameters();

parameters.Add("service", ServiceName);
parameters.Add("sourceFileName", sourceFileName);
parameters.Add("targetFileName", targetFileName);
parameters.Add("mapFileName", mapFileName);

if (GenerateSourceMap)
parameters.Add("sourceMapURL");

if (!WESettings.Instance.Less.StrictMath)
parameters.Add("strictMath");

if (WESettings.Instance.Css.Autoprefix)
{
parameters.Add("autoprefixer");

if (!string.IsNullOrWhiteSpace(WESettings.Instance.Css.AutoprefixerBrowsers))
parameters.Add("autoprefixerBrowsers", WESettings.Instance.Css.AutoprefixerBrowsers);
}

return parameters.FlattenParameters();
}
}
}
}
42 changes: 16 additions & 26 deletions EditorExtensions/LiveScript/Compilers/LiveScriptCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System.ComponentModel.Composition;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using MadsKristensen.EditorExtensions.Settings;
using Microsoft.VisualStudio.Utilities;

Expand All @@ -13,32 +8,27 @@ namespace MadsKristensen.EditorExtensions.LiveScript
[ContentType(LiveScriptContentTypeDefinition.LiveScriptContentType)]
public class LiveScriptCompiler : JsCompilerBase
{
private static readonly string _compilerPath = Path.Combine(WebEssentialsResourceDirectory, @"nodejs\tools\node_modules\LiveScript\bin\livescript");
private static readonly Regex _errorParsingPattern = new Regex(@"Failed at: (?<filename>.*?)Error: (?<message>.*)", RegexOptions.Multiline);

public override bool GenerateSourceMap { get { return WESettings.Instance.LiveScript.GenerateSourceMaps; } }
public override string ServiceName { get { return "LiveScript"; } }
protected override string CompilerPath { get { return _compilerPath; } }
public override bool RequireMatchingFileName { get { return true; } }
protected override Regex ErrorParsingPattern { get { return _errorParsingPattern; } }

protected override Task<string> GetArguments(string sourceFileName, string targetFileName, string mapFileName)
public override bool MinifyInPlace { get { return WESettings.Instance.SweetJs.MinifyInPlace; } }
public override bool GenerateSourceMap { get { return false; /*WESettings.Instance.LiveScript.GenerateSourceMaps && !WESettings.Instance.LiveScript.MinifyInPlace;*/ } }
// Maps aren't yet supported by LiveScript
protected override string GetPath(string sourceFileName, string targetFileName)
{
var args = new StringBuilder();
string mapFileName = targetFileName + ".map";
var parameters = new NodeServerUtilities.Parameters();

if (!WESettings.Instance.LiveScript.WrapClosure)
args.Append("-b ");
parameters.Add("service", ServiceName);
parameters.Add("sourceFileName", sourceFileName);
parameters.Add("targetFileName", targetFileName);
parameters.Add("mapFileName", mapFileName);

args.AppendFormat(CultureInfo.CurrentCulture, "-o \"{0}\" -c \"{1}\"", Path.GetDirectoryName(targetFileName), sourceFileName);
if (GenerateSourceMap)
parameters.Add("sourceMapURL");

return Task.FromResult(args.ToString());
}

protected async override Task<string> PostProcessResult(string resultSource, string sourceFileName, string targetFileName, string mapFileName)
{
Logger.Log(ServiceName + ": " + Path.GetFileName(sourceFileName) + " compiled.");
if (!WESettings.Instance.LiveScript.WrapClosure)
parameters.Add("bare");

return await Task.FromResult(resultSource);
return parameters.FlattenParameters();
}
}
}
}
Loading

0 comments on commit e5123c3

Please sign in to comment.