2011-01-25 5 views
12

私は、.lessファイル名を受け取り、Less.Parse(<filename>)で処理し、処理されたCSSファイルを出力するASP.NET MVCアクションメソッドを作成しました。プログラムレスで.lessを使用するとエラーを出力する方法はありますか?

これは、.lessコードが有効である限り正常に動作しますが、エラーがある場合、dotLessは空の文字列を返します。したがって、ファイルの処理中にエラーが発生した場合、私のアクションメソッドは空のCSSファイルを返します。

代わりに構文エラーの詳細な説明を含むエラーメッセージを出力するにはどうすればよいですか?

+0

あなたはSquishItを見ましたか? http://www.codethinked.com/post/2010/05/26/SquishIt-The-Friendly-ASPNET-JavaScript-and-CSS-Squisher.aspx –

+0

@qstarin:ありがとうございます。しかし、私はすでにcombres(http: //combres.codeplex.com/)を生産目的で使用することができ、combresはすべてのことを行うことができます(プラスかなりプラス)。しかし、私はまだ開発目的のために上記の私の質問に対する答えが必要です。その理由は、すべてのCSSファイルをまとめてダウンロードして作業するのが好きではなく、別のファイルを好むからです。エラーメッセージを除いて、すべてうまくいきます... –

+0

私は興味がありますが、SquishItが提供している便利な機能は何ですか? Combresのドキュメンテーションを見ると、彼らは多くの同じ仕事をしているようです。しかし、SquishItは処理にdotLessを含める。それで、私はそれを言いました。なぜならあなたはdotLessコンパイルを実行するために別個のアクションを必要としないからです。 –

答えて

14

dotLessパーサは、例外をトラップしてロガーに出力します。これはLessEngine.TransformToCssで行いドットなしのソースからの抜粋:

public string TransformToCss(string source, string fileName) 
{ 
    try 
    { 
     Ruleset ruleset = this.Parser.Parse(source, fileName); 
     Env env = new Env(); 
     env.Compress = this.Compress; 
     Env env2 = env; 
     return ruleset.ToCSS(env2); 
    } 
    catch (ParserException exception) 
    { 
     this.Logger.Error(exception.Message); 
    } 
    return ""; 
} 

Less.Parseは、あなたが使用できるいくつかのプロパティを提供DotlessConfigurationオブジェクトを受け取るオーバーロードがあります。

public class DotlessConfiguration 
{ 
    // Properties 
    public bool CacheEnabled { get; set; } 
    public Type LessSource { get; set; } 
    public Type Logger { get; set; } 
    public LogLevel LogLevel { get; set; } 
    public bool MinifyOutput { get; set; } 
    public int Optimization { get; set; } 
    public bool Web { get; set; } 
} 

あなたはそのLoggerわかりますプロパティのタイプはTypeです。どのようなあなたがdotless.Core.Loggers.ILoggerを実装する必要があります電源の種類:エラーが解析中に遭遇したとき

public interface ILogger 
{ 
    // Methods 
    void Debug(string message); 
    void Error(string message); 
    void Info(string message); 
    void Log(LogLevel level, string message); 
    void Warn(string message); 
} 

我々は最初のスニペットで見たように、ロガーでErrorメソッドが呼び出されます。

ここでの1つの固執点は、​​を実装するタイプのインスタンスがどのようにインスタンス化されるかです。内部的には、dotLessはDLLに焼き付けられたIoCコンテナを使用します。メソッド呼び出しの後、最終的にActivator.CreateInstanceを呼び出してILoggerをインスタンス化するように見えます。

私はこれが少なくとも多少役に立ちますと願っています。

+0

優れています。どうもありがとう! :-) –

+1

私は本当にロガーAPIを少し書き直すべきです。書く時には、それは念頭に置いて内部的な使い方だけで意味がありました。しかし、外部の呼び出し元にとっては、これはかなり悪いです。 – Tigraine

+0

@Tigraine:私は少なくとも望みます私はロギングイベントをキャッチする方法を正しく説明しましたが、私はそれをすべて落としてしまったのかどうか少しはっきりしていました。特に、ロギングクラスだけが入ったDotlessConfigurationオブジェクトを指定したのは何ですか?私はSimpleLoggingFrameworkまたはCommon.Loggingを2つの潜在的ファサードとしてロギングシステムに指していると思いますが、正直なところ、すべての依存関係を混乱させる可能性があります。幸いです。 heh –

5

今日私のRequestReduceプロジェクトでこれに直面しました。私は、空白を少なくしていました - > CSSの変換は、エーテルに入っているように見える解析エラーがあったためです。 qesの答えのおかげで、私はエラーを応答ストリームに書き込むことができる解決策を見つけ出すことができました。私が書くだろうと私のHttpResponseBaseに渡したいユニットテストの目的のために

  var engine = new EngineFactory(new DotlessConfiguration 
               { 
                CacheEnabled = false, 
                Logger = typeof (LessLogger) 
               } 
       ).GetEngine(); 

:私はEngineFactoryに送られたコンフィギュレーションにこれを渡し

public class LessLogger : ILogger 
{ 
    public void Log(LogLevel level, string message) 
    { 
    } 

    public void Info(string message) 
    { 
    } 

    public void Debug(string message) 
    { 
    } 

    public void Warn(string message) 
    { 
    } 

    public void Error(string message) 
    { 
     Response.Write(message); 
    } 

    public HttpResponseBase Response { get; set; } 
} 

:ここに私のdotless.Core.Loggers.ILoggerですエラー。誰かがロガーへの参照を取得するために、よりエレガントな方法を知っているならば、私はこれが出て助けと願ってい

  ((LessLogger)((LessEngine)((ParameterDecorator)engine).Underlying).Logger).Response = response; 

してください:私は物事が私のロガーへの参照を取得するためにいくつかの厄介なキャスティングと醜いなって感じたところですお知らせ下さい。

+0

'LessLogger'クラスはどこに置いていますか? – guanome

5

これはweb.configで非常に簡単に行うことができます。ドットなし設定セクションに、次のように追加します。logger="dotless.Core.Loggers.AspResponseLogger"。これにより、空白のCSSの代わりにドットなしの出力がエラーになります。

私は例として以下を含めました。 ( "..."はweb.configの既存のものを表します)。以下の私の例では、cacheはfalseに設定されています。これはデバッグのために便利です。通常は、実際にはtrueに設定する必要があります。

<configuration>  
    <configSections> 
      ... 
      <section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler,dotless.Core" /> 
     </configSections> 

     <dotless minifyCss="false" cache="false" 
      logger="dotless.Core.Loggers.AspResponseLogger" /> 
     ...  
</configuration>  
+3

私は次のような行を追加しました 私のために何もしませんか? – Jacques

+0

これがなぜ答えとしてマークされているのか分かりませんか? –

+1

+1これは動作します - SquishItのようなものを使用している場合は、エラーを表示するためにブラウザの中に直接少ないファイルを参照することを確かめてください。 – davidsleeps

0

@ tony722のソリューションは、他の人のために、あなたのページから無関係のファイルを参照するだけで動作します。

しかし、あなたは直接Less.Parseを呼び出す場合、このメソッドはResponseにエラーが書き込まれます:

var lessConfig = new DotlessConfiguration { Logger = typeof(AspResponseLogger) }; 
string css = Less.Parse(someInput, lessConfig); 
0

これはVSでの出力ウィンドウにログ:

var config = dotless.Core.configuration.DotlessConfiguration.GetDefault(); 
config.Logger = new dotless.Core.Loggers.DiagnosticsLogger(dotless.Core.Loggers.LogLevel.Debug).GetType(); 
config.MinifyOutput = minified; 
css= Less.Parse(css, config); 
+0

はこの解決策です。ロガーは以前のように実装する必要がありますか? – petersmm

1

私はドットなしの周りにラッパークラスを使用しています

public class LessParser : IStylizer 
{ 
    public string ErrorFileName { get; private set; } 
    public int ErrorLineNumber { get; private set; } 
    public int ErrorPosition { get; private set; } 
    public string ErrorMessage { get; private set; } 

    string IStylizer.Stylize(Zone zone) 
    { 
     ErrorFileName = zone.FileName; 
     ErrorLineNumber = zone.LineNumber; 
     ErrorPosition = zone.Position; 
     ErrorMessage = zone.Message; 

     return String.Empty; 
    } 

    public string Compile(string lessContent, string lessPath) 
    { 
     var lessEngine = new EngineFactory(new DotlessConfiguration 
     { 
      CacheEnabled = false, 
      DisableParameters = true, 
      LogLevel = LogLevel.Error, 
      MinifyOutput = true 
     }).GetEngine(); 

     lessEngine.CurrentDirectory = lessPath; 

     /* uncomment if DisableParameters is false 
     if (lessEngine is ParameterDecorator) 
      lessEngine = ((ParameterDecorator)lessEngine).Underlying; 
     */ 

     /* uncomment if CacheEnabled is true 
     if (lessEngine is CacheDecorator) 
      lessEngine = ((CacheDecorator)lessEngine).Underlying; 
     */ 

     ((LessEngine)lessEngine).Parser.Stylizer = this; 

     return lessEngine.TransformToCss(lessContent, null); 
    } 

    public FileInfo SyncCss(FileInfo lessFile) 
    { 
     var cssFile = new FileInfo(
      lessFile.FullName.Substring(0, lessFile.FullName.Length - lessFile.Extension.Length) + ".css"); 

     if (!cssFile.Exists || cssFile.LastWriteTimeUtc < lessFile.LastWriteTimeUtc) 
     { 
      string cssContent = Compile(ReadFileContent(lessFile), lessFile.DirectoryName); 

      if (String.IsNullOrEmpty(cssContent)) 
       return null; 

      using (var stream = cssFile.Open(FileMode.Create)) 
      using (var writer = new StreamWriter(stream, Encoding.UTF8)) 
      { 
       writer.Write(cssContent); 
      } 
     } 

     return cssFile; 
    } 

    public string ReadFileContent(FileInfo file) 
    { 
     using (var reader = file.OpenText()) 
     { 
      return reader.ReadToEnd(); 
     } 
    } 
} 

トリックは独自の実装を使用していますIStylizerのインタフェースを使用して、解析エラーが発生したときに呼び出され、結果のエラーメッセージをフォーマットします。これにより、エラーが既にフォーマットされたテキストである​​インターフェイスの実装とは異なり、個別のエラーをキャプチャできます。

var parser = new LessParser(); 
var lessFile = new FileInfo("C:\\temp\\sample.less")); 
var cssFile = parser.SyncCss(lessFile); 

if (cssFile != null) 
    Console.WriteLine(parser.ReadFileContent(cssFile)); 
else 
    Console.WriteLine("Error '{3}' in {0}, line {1}, position {2}", 
     parser.ErrorFileName, parser.ErrorLineNumber, parser.ErrorPosition, parser.ErrorMessage); 
関連する問題