Подтвердить что ты не робот

Как я могу выводить ошибки при использовании .less программно?

Я написал метод действия ASP.NET MVC, который получает имя файла без .less, обрабатывает его через Less.Parse(<filename>) и выводит обработанный файл css.

Это работает отлично до тех пор, пока код .less действителен, но если есть ошибка, dotLess просто возвращает пустую строку. Поэтому, если есть ошибка обработки файла, мой метод действия возвращает пустой файл css.

Как я могу вывести сообщение об ошибке с более подробным описанием синтаксической ошибки?

4b9b3361

Ответ 1

Ловушки парсера dotLess Исключает и выводит их в Logger. Этот фрагмент из источника 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 в журнале регистрируется, когда во время разбора встречается ошибка.

Теперь одна липкая точка всего этого заключается в том, как создается экземпляр экземпляра типа, реализующего ILogger. Внутри, dotLess использует контейнер IoC, который запекается в DLL. Следуя вызовам метода, кажется, что он в конечном итоге вызовет Activator.CreateInstance, чтобы создать экземпляр вашего ILogger.

Я надеюсь, что это, по крайней мере, несколько полезно.

Ответ 2

Я просто столкнулся с этим сегодня в проекте RequestReduce. Я становился пустым меньше → css трансформируется, потому что были ошибки анализа, которые, казалось, попадали в эфир. Благодаря ответу qes я смог разработать решение, в котором я мог бы записывать ошибки в поток ответов. Вот мой dotless.Core.Loggers.ILogger:

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

Я передаю это в конфигурацию, отправленную в EngineFactory:

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

В целях тестирования модулей я хотел передать в HttpResponseBase, который будет писать ошибку. Именно здесь я почувствовал, что уродливые с некоторыми неприятными кастингами получают ссылку на мой регистратор:

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

Надеюсь, это поможет, и если кто-то знает более элегантный способ получить ссылку на регистратор, сообщите мне.

Ответ 3

Вы можете сделать это очень легко с помощью web.config. В разделе "Бесконечная конфигурация" добавьте следующее: logger="dotless.Core.Loggers.AspResponseLogger". Это сделает бессмысленным вывод ошибок вместо пустой css.

В качестве примера я включил следующее. ( "..." представляет существующий материал в вашем web.config). В моем примере ниже кеш установлен в значение 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>    

Ответ 4

Я использую класс-обертку без точек, следующим образом:

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, которая вызвана встречей ошибки синтаксического анализа для форматирования полученного сообщения об ошибке. Это позволяет нам записывать отдельные фрагменты ошибки, в отличие от реализации интерфейса ILogger, где ошибка уже является форматированным текстом.

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

Ответ 5

В интересах других, решение @tony722 работает, если вы просто ссылаетесь на бездействующие файлы со своих страниц.

Но если вы вызываете Less.Parse напрямую, этот метод будет записывать любую ошибку в Response:

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

Ответ 6

Этот журнал выводит окно в 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);