2011-01-25 19 views
12

Tôi đã viết một phương thức hành động ASP.NET MVC nhận tên tệp .less, xử lý nó qua Less.Parse(<filename>) và xuất ra tệp css đã xử lý.Làm thế nào tôi có thể xuất ra lỗi khi sử dụng .less programmatically?

Điều này làm việc tốt miễn là mã .less là hợp lệ, nhưng nếu có lỗi, dotLess chỉ trả về một chuỗi rỗng. Vì vậy, nếu có lỗi khi xử lý tệp, phương thức hành động của tôi sẽ trả về tệp css trống.

Làm cách nào để xuất thông báo lỗi có mô tả gần đúng hơn về lỗi cú pháp?

+0

Bạn đã xem SquishIt chưa? http://www.codethinked.com/post/2010/05/26/SquishIt-The-Friendly-ASPNET-JavaScript-and-CSS-Squisher.aspx –

+0

@qstarin: Cảm ơn, nhưng tôi đã sử dụng combres (http: //combres.codeplex.com/) cho mục đích sản xuất và combres có thể làm mọi thứ squishit (cộng thêm một chút nữa). Nhưng tôi vẫn cần câu trả lời cho câu hỏi của tôi ở trên cho mục đích phát triển. Lý do là tôi không thích làm việc với một tải xuống kết hợp bao gồm tất cả các tệp CSS của tôi, thay vào đó tôi thích các tệp riêng biệt. Và tất cả mọi thứ hoạt động tốt, ngoại trừ các thông báo lỗi ... –

+0

Tôi tò mò, những tính năng hữu ích nào mà Combres cung cấp cho SquishIt không? Nhìn qua tài liệu của Combres, có vẻ như họ làm nhiều việc giống nhau. SquishIt, tuy nhiên, bao gồm dotLess vào chế biến của nó. Đó là lý do tại sao tôi đề cập đến nó, bởi vì bạn sẽ không cần một hành động riêng biệt để thực hiện việc biên dịch dotLess. –

Trả lời

14

Trình phân tích cú pháp dotLess bẫy Ngoại lệ và xuất chúng vào Trình ghi nhật ký. Đoạn từ nguồn dotLess rằng thực hiện này là 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 có quá tải mà phải mất một đối tượng DotlessConfiguration, mà cung cấp một số tính năng mà bạn có thể sử dụng:

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; } 
} 

Bạn sẽ nhận thấy rằng các Logger tài sản thuộc loại Type. Dù loại mà bạn cung cấp phải thực hiện 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); 
} 

Như chúng ta đã thấy trong đoạn đầu tiên, phương pháp Error trên logger sẽ được gọi khi một lỗi gặp phải trong quá trình phân tích cú pháp.

Bây giờ, một điểm dính của tất cả điều này là cách chính xác một thể hiện của loại thực hiện ILogger được khởi tạo. Bên trong, dotLess sử dụng một thùng chứa IoC được đưa vào DLL. Theo sau các cuộc gọi phương thức, dường như nó sẽ gọi số Activator.CreateInstance để khởi tạo ILogger của bạn.

Tôi hy vọng điều này có phần ít hữu ích.

+0

Tuyệt vời. Cảm ơn rất nhiều! :-) –

+1

Tôi thực sự nên làm lại API logger một chút .. Tại thời điểm viết nó có ý nghĩa với chỉ sử dụng nội bộ trong tâm trí .. nhưng đối với người gọi bên ngoài này là khá xấu .. – Tigraine

+0

@Tigraine: Tôi hy vọng ít nhất Tôi đã giải thích một cách chính xác cách bắt các sự kiện ghi nhật ký, tôi đã không chắc chắn nếu tôi đã xóa tất cả, đặc biệt là những gì các nhánh đã chỉ định một đối tượng DotlessConfiguration chỉ với lớp ghi nhật ký. , Tôi muốn trỏ đến SimpleLoggingFramework hoặc Common.Logging như hai mặt tiền tiềm năng cho các hệ thống ghi nhật ký, mặc dù thành thật nó có thể trở nên lộn xộn với tất cả các phụ thuộc .... chúc may mắn. heh –

5

Tôi vừa đối mặt với điều này hôm nay trong dự án RequestReduce của tôi. Tôi đã nhận được ít trống -> css biến đổi vì có lỗi phân tích xuất hiện để được đi vào ether. Nhờ câu trả lời của qes tôi đã có thể làm việc ra một giải pháp mà tôi có thể viết các lỗi cho dòng phản ứng. Dưới đây là dotless.Core.Loggers.ILogger tôi:

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; } 
} 

tôi chuyển thông tin này vào Configuration gửi đến EngineFactory:

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

Đối với mục đích kiểm tra đơn vị tôi muốn vượt qua trong HttpResponseBase tôi rằng sẽ viết lỗi. Đây là nơi tôi cảm thấy mọi thứ nhận xấu xí với một số đúc khó chịu để có được một tài liệu tham khảo để logger của tôi:

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

Tôi hy vọng điều này sẽ giúp ra ngoài và nếu ai đó biết một cách thanh lịch hơn để có được một tham chiếu đến logger, xin vui lòng cho tôi biết.

+0

Bạn đặt lớp 'LessLogger' ở đâu? – guanome

5

Bạn có thể thực hiện việc này rất dễ dàng với web.config. Trong phần cấu hình không có dấu chấm, hãy thêm thông tin sau: logger="dotless.Core.Loggers.AspResponseLogger". Điều này sẽ làm cho đầu ra dotless các lỗi thay vì css trống.

Tôi đã bao gồm những điều sau đây làm ví dụ. ("..." đại diện cho các công cụ hiện có trong web.config của bạn). Trong ví dụ dưới đây, bộ nhớ cache của tôi được đặt thành false. Điều này rất hữu ích cho mục đích gỡ lỗi.Nó có lẽ nên được đặt thành true trong những hoàn cảnh bình thường.

<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

Tôi đã thêm dòng có dạng như sau Không có gì cho tôi? – Jacques

+0

Bạn không chắc tại sao điều này được đánh dấu là câu trả lời? –

+1

+1 Công trình này - nếu sử dụng một cái gì đó giống như SquishIt, hãy đảm bảo bạn chỉ tham chiếu trực tiếp các tệp ít hơn trong trình duyệt của mình (hoặc bất kỳ thứ gì) để xem các lỗi – davidsleeps

0

Vì lợi ích của người khác, giải pháp @ tony722 hoạt động nếu bạn chỉ cần tham chiếu các tệp .less từ trang của bạn.

Nhưng nếu bạn gọi Less.Parse trực tiếp, phương pháp này sẽ viết bất kỳ lỗi vào Response:

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

này đăng nhập để cửa sổ đầu ra trong 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

là giải pháp này. Nó đòi hỏi một logger phải được thực hiện như những cái trước? – petersmm

1

Tôi đang sử dụng một lớp bao bọc xung quanh dotless , như sau:

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(); 
     } 
    } 
} 

Bí quyết là sử dụng riêng impleme ntation của giao diện IStylizer được gọi khi gặp lỗi phân tích cú pháp để định dạng thông báo lỗi kết quả. Điều này cho phép chúng tôi nắm bắt các phần rời rạc của lỗi, không giống như việc triển khai giao diện ILogger trong đó lỗi đã là văn bản được định dạng.

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); 
Các vấn đề liên quan