public bool WriteToStream(BaseCompositeFileProcessingProvider provider, StreamWriter sw, FileInfo fi, ClientDependencyType type, string origUrl, HttpContextBase http) { try { //if it is a file based dependency then read it var fileContents = File.ReadAllText(fi.FullName, Encoding.UTF8); //read as utf 8 //for our custom file reader to work we just need to put the origUrl into the httpcontext items so //we can retreive it in the reader to then figure out the 'real' requested path. http.Items["Cdf_LessWriter_origUrl"] = origUrl; //get the default less config var config = DotlessConfiguration.GetDefaultWeb(); //set the file reader to our custom file reader config.LessSource = typeof(CdfFileReader); //disable cache for this engine since we are already caching our own, plus enabling this will cause errors because // the import paths aren't resolved properly. config.CacheEnabled = false; //get the engine based on the custom config with our custom file reader var lessEngine = LessWeb.GetEngine(config); var output = lessEngine.TransformToCss(fileContents, origUrl); DefaultFileWriter.WriteContentToStream(provider, sw, output, type, http, origUrl); return(true); } catch (Exception ex) { ClientDependencySettings.Instance.Logger.Error(string.Format("Could not write file {0} contents to stream. EXCEPTION: {1}", fi.FullName, ex.Message), ex); return(false); } }
/// <summary> /// Compiles this instance. /// </summary> public bool Compile(out string messages) { messages = string.Empty; bool compiledSuccessfully = true; try { DirectoryInfo themeDirectory = new DirectoryInfo(this.AbsolutePath + @"\Styles"); if (themeDirectory.Exists) { FileInfo[] files = themeDirectory.GetFiles(); // Good documentation on options // https://www.codeproject.com/Articles/710676/LESS-Web-config-DotlessConfiguration-Options DotlessConfiguration dotLessConfiguration = new DotlessConfiguration(); dotLessConfiguration.MinifyOutput = true; dotLessConfiguration.DisableVariableRedefines = true; //dotLessConfiguration.RootPath = themeDirectory.FullName; var origDirectory = Directory.GetCurrentDirectory(); try { Directory.SetCurrentDirectory(themeDirectory.FullName); if (files != null) { if (this.AllowsCompile) { // don't compile files that start with an underscore foreach (var file in files.Where(f => f.Name.EndsWith(".less") && !f.Name.StartsWith("_"))) { string cssSource = LessWeb.Parse(File.ReadAllText(file.FullName), dotLessConfiguration); File.WriteAllText(file.DirectoryName + @"\" + file.Name.Replace(".less", ".css"), cssSource); // check for compile errors (an empty css source returned) if (cssSource == string.Empty) { messages += "A compile error occurred on " + file.Name; compiledSuccessfully = false; } } } } } finally { Directory.SetCurrentDirectory(origDirectory); } } } catch (Exception ex) { compiledSuccessfully = false; messages = ex.Message; } return(compiledSuccessfully); }
public string Process(string includedVirtualPath, string input) { if (VirtualPathUtility.GetExtension(includedVirtualPath) == ".less") { var cfg = DotlessConfiguration.GetDefaultWeb(); cfg.Web = true; cfg.MinifyOutput = BundleTable.EnableOptimizations; cfg.MapPathsToWeb = true; cfg.CacheEnabled = false; var importRegex = new Regex(@"@import (.*?);", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled); input = importRegex.Replace(input, m => ResolveImportLessPath(includedVirtualPath, m)); input = LessWeb.Parse(input, cfg); } var urlRegex = new Regex(@"url\((.*?)\)", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled); input = urlRegex.Replace(input, m => ResolveUrlPath(includedVirtualPath, m)); return(input); }
public bool WriteToStream(BaseCompositeFileProcessingProvider provider, StreamWriter sw, FileInfo fi, ClientDependencyType type, string origUrl, HttpContextBase http) { try { //if it is a file based dependency then read it var fileContents = File.ReadAllText(fi.FullName, Encoding.UTF8); //read as utf 8 //NOTE: passing in null will automatically for the web configuration section to be loaded in! var output = LessWeb.Parse(fileContents, null); DefaultFileWriter.WriteContentToStream(provider, sw, output, type, http, origUrl); return(true); } catch (Exception ex) { ClientDependencySettings.Instance.Logger.Error(string.Format("Could not write file {0} contents to stream. EXCEPTION: {1}", fi.FullName, ex.Message), ex); return(false); } }
private string ProcessLess(string finalCss) { DotlessConfiguration config = DotlessConfiguration.GetDefaultWeb(); config.CacheEnabled = false; config.DisableUrlRewriting = true; config.DisableParameters = true; config.MapPathsToWeb = false; config.MinifyOutput = false; config.HandleWebCompression = false; config.Debug = WebConfigSettings.DebugDotLess; string css = LessWeb.Parse(finalCss, config); if (string.IsNullOrEmpty(css)) { return("/* less parsing failed - probably a syntax error */\n" + finalCss); } return(css); }
/// <summary> /// Compiles this instance. /// </summary> public bool Compile(out string messages) { messages = string.Empty; bool result = true; try { DirectoryInfo themeDirectory = new DirectoryInfo(this.AbsolutePath + @"\Styles"); if (themeDirectory.Exists) { FileInfo[] files = themeDirectory.GetFiles(); DotlessConfiguration dotLessConfiguration = new DotlessConfiguration(); dotLessConfiguration.MinifyOutput = true; //dotLessConfiguration.RootPath = themeDirectory.FullName; Directory.SetCurrentDirectory(themeDirectory.FullName); if (files != null) { if (this.AllowsCompile) { // don't compile files that start with an underscore foreach (var file in files.Where(f => f.Name.EndsWith(".less") && !f.Name.StartsWith("_"))) { string cssSource = LessWeb.Parse(File.ReadAllText(file.FullName), dotLessConfiguration); File.WriteAllText(file.DirectoryName + @"\" + file.Name.Replace(".less", ".css"), cssSource); } } } } } catch (Exception ex) { result = false; messages = ex.Message; } return(result); }
/// <summary> /// Renders the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="result">The result.</param> public override void Render(Context context, TextWriter result) { RockPage page = HttpContext.Current.Handler as RockPage; var parms = ParseMarkup(_markup, context); using (TextWriter twStylesheet = new StringWriter()) { base.Render(context, twStylesheet); var stylesheet = twStylesheet.ToString(); if (parms.ContainsKey("compile")) { if (parms["compile"] == "less") { DotlessConfiguration dotLessConfiguration = new DotlessConfiguration(); dotLessConfiguration.MinifyOutput = true; if (parms.ContainsKey("import")) { // import statements should go at the end to allow for default variable assignment in the beginning // to help reduce the number of Less errors we automatically add the bootstrap and core rock variables files var importStatements = string.Empty; var importSource = "~/Styles/Bootstrap/variables.less,~/Styles/_rock-variables.less," + parms["import"]; var importFiles = importSource.Split(','); foreach (var importFile in importFiles) { var filePath = string.Empty; if (!importFile.StartsWith("~")) { filePath = $"~~/Styles/{importFile}"; } else { filePath = importFile; } filePath = page.ResolveRockUrl(filePath); var fullPath = page.MapPath("~/") + filePath; if (File.Exists(fullPath)) { importStatements = $"{importStatements}{Environment.NewLine}@import \"{fullPath}\";"; } } stylesheet = $"{stylesheet}{Environment.NewLine}{importStatements}"; } // ok we have our less stylesheet let's see if it's been cached (less can take ~100ms to compile so let's try not to do that if necessary) if (parms.ContainsKey("cacheduration")) { var cacheKey = stylesheet.GetHashCode().ToString(); var cachedStylesheet = RockCache.Get(cacheKey) as string; if (cachedStylesheet.IsNotNullOrWhiteSpace()) { stylesheet = cachedStylesheet; } else { stylesheet = LessWeb.Parse(stylesheet, dotLessConfiguration); // check if we should cache this if (parms.ContainsKey("cacheduration") && stylesheet.IsNotNullOrWhiteSpace()) { int cacheDuration = 0; Int32.TryParse(parms["cacheduration"], out cacheDuration); if (cacheDuration > 0) { RockCache.AddOrUpdate(cacheKey, null, stylesheet, RockDateTime.Now.AddSeconds(cacheDuration)); } } } } else { stylesheet = LessWeb.Parse(stylesheet, dotLessConfiguration); } } if (stylesheet == string.Empty) { if (parms.ContainsKey("id")) { result.Write($"An error occurred compiling the Less for this stylesheet (id: {parms["id"]})."); } else { result.Write("An error occurred compiling the Less for this stylesheet."); } return; } } if (parms.ContainsKey("id")) { var identifier = parms["id"]; if (identifier.IsNotNullOrWhiteSpace()) { var controlId = "css-" + identifier; var cssControl = page.Header.FindControl(controlId); if (cssControl == null) { cssControl = new System.Web.UI.LiteralControl($"{Environment.NewLine}<style>{stylesheet}</style>{Environment.NewLine}"); cssControl.ID = controlId; page.Header.Controls.Add(cssControl); } } } else { page.Header.Controls.Add(new System.Web.UI.LiteralControl($"{Environment.NewLine}<style>{stylesheet}</style>{Environment.NewLine}")); } } }
internal static string Process(ref IEnumerable <BundleFile> files) { DotlessConfiguration lessConfig = new WebConfigConfigurationLoader().GetConfiguration(); if (!lessConfig.LessSource.GetInterfaces().Contains(typeof(IFileReaderWithResolver))) { lessConfig.LessSource = typeof(LessVirtualFileReader); } // system.Web.Optimization cache is used instead lessConfig.CacheEnabled = false; var content = new StringBuilder(); var targetFiles = new List <BundleFile>(); foreach (BundleFile bundleFile in files) { // initialize the less engine once for each file. // this is to prevent leaking state between files ILessEngine lessEngine = LessWeb.GetEngine(lessConfig); LessEngine underlyingLessEngine = lessEngine.ResolveLessEngine(); Parser lessParser = underlyingLessEngine.Parser; targetFiles.Add(bundleFile); string filePath = bundleFile.IncludedVirtualPath; filePath = filePath.Replace('\\', '/'); filePath = VirtualPathUtility.ToAppRelative(filePath); lessParser.SetCurrentFilePath(filePath); string source = bundleFile.ApplyTransforms(); string extension = VirtualPathUtility.GetExtension(filePath); // if plain CSS file, do not transform LESS if (lessConfig.ImportAllFilesAsLess || ".less".Equals(extension, StringComparison.InvariantCultureIgnoreCase) || ".less.css".Equals(extension, StringComparison.InvariantCultureIgnoreCase)) { string lessOutput = lessEngine.TransformToCss(source, filePath); // pass the transformation result if successful if (lessEngine.LastTransformationSuccessful) { source = lessOutput; } else { // otherwise write out error message. // the transformation error is logged in LessEngine.TransformToCss if (lessConfig.Debug) { content.AppendLine(string.Format( "/* Error occurred in LESS transformation of the file: {0}. Please see details in the dotless log */", bundleFile.IncludedVirtualPath)); } continue; } } source = ConvertUrlsToAbsolute(bundleFile.IncludedVirtualPath, source); content.AppendLine(source); BundleFile[] fileDependencies = GetFileDependencies(underlyingLessEngine).ToArray(); targetFiles.AddRange(fileDependencies); DependencyCache.SaveFileDependencies(filePath, fileDependencies.Select(file => file.IncludedVirtualPath).ToArray()); } // include imports in bundle files to register cache dependencies files = BundleTable.EnableOptimizations ? targetFiles.Distinct() : targetFiles; return(content.ToString()); }
private string TransformContent(BundleResource bundleResource, HttpContext context) { var bundleType = bundleResource.Type; var content = bundleResource.Content; var serverpath = bundleResource.ServerPath; try { if (bundleType == BundleResourceType.EmbeddedScript || bundleType == BundleResourceType.ScriptFile) { var compressor = new JavaScriptCompressor { CompressionType = CompressionType.Standard, Encoding = Encoding.UTF8, ObfuscateJavascript = bundleResource.ObfuscateJs }; //Minimize var contentOut = compressor.Compress(content.Trim()) + ";"; //Return deffered execution if (ClientSettings.IsJavascriptDefferingEnabled) { return(string.Format(ClientSettings.JavascriptDefferingScript, JsonConvert.SerializeObject(contentOut))); } return(contentOut); } if (!string.IsNullOrEmpty(serverpath)) { string directoryName = Path.GetDirectoryName(serverpath); if (directoryName != null) { serverpath = directoryName.Replace('\\', '/'); } } if (bundleType == BundleResourceType.EmbeddedStyle || bundleType == BundleResourceType.StyleFile) { var compressor = new CssCompressor { CompressionType = CompressionType.Standard, RemoveComments = true }; return(ReplaceUrls(compressor.Compress(content), serverpath, context)); } if (bundleType == BundleResourceType.LessFile) { DotlessConfiguration cfg = DotlessConfiguration.GetDefaultWeb(); cfg.Web = true; cfg.MinifyOutput = true; cfg.MapPathsToWeb = true; cfg.CacheEnabled = false; //Prefilter content = ReplaceImportRegex.Replace(content, match => ReplaceImports(match, serverpath)); string processed = ReplaceUrls(LessWeb.Parse(content, cfg), serverpath, context); return(processed); } } catch (EcmaScript.NET.EcmaScriptException e) { _log.ErrorFormat("EcmaScriptException: {0} in {1} at {2} ({3}, {4}) at ", e.Message, serverpath, e.LineSource, e.LineNumber, e.ColumnNumber, e.ScriptStackTrace); } catch (Exception e) { _log.Error(e); } return(content); }