I\'ve written an ASP.NET MVC action method that receives a .less file name, processes it via Less.Parse( and outputs the processed css file. >
I am using a wrapper class around dotless, as follows:
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();
}
}
}
The trick is to use own implementation of IStylizer interface that is called upon encountering a parse error to format the resulting error message. This allows us to capture discrete pieces of the error, unlike implementation of ILogger interface where the error is already a formatted text.
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);