/// <summary> /// Save the files contents to the destination location /// </summary> /// <param name="processingData"></param> /// <param name="outputPath"></param> /// <returns></returns> public override Task SaveFileContents(FileProcessingData processingData, FileOutputData outputPath) { return(SafeTask.Run(() => { // Do normal file copy when saving static file FileManager.CopyFile(processingData.FullPath, outputPath.FullPath); })); }
protected override Task PreProcessFile(FileProcessingData data) { return(SafeTask.Run(() => { // Set this file to partial if it starts with _ data.IsPartial = Path.GetFileName(data.FullPath).StartsWith("_"); })); }
/// <summary> /// Specifies Sass output paths based on Dna configuration settings, if specified /// </summary> /// <param name="data"></param> /// <returns></returns> protected override Task PostProcessOutputPaths(FileProcessingData data) { return(SafeTask.Run(() => { // For now just output in the same directory as Sass file data.OutputPaths.Add(new FileOutputData { FullPath = GetDefaultOutputPath(data), FileContents = data.UnprocessedFileContents }); })); }
/// <summary> /// Specifies output paths based on Dna configuration settings, if specified /// </summary> /// <param name="data"></param> /// <returns></returns> protected override Task PostProcessOutputPaths(FileProcessingData data) { return(SafeTask.Run(() => { // Output path is the destination folder var relativePath = data.FullPath.Substring(StaticFolderDetails.SourceFolder.Length + 1); var outputPath = Path.GetFullPath(Path.Combine(StaticFolderDetails.DestinationFolder, relativePath)); data.OutputPaths.Add(new FileOutputData { FullPath = outputPath, FileContents = data.UnprocessedFileContents }); })); }
protected override Task PreProcessFile(FileProcessingData data) { return(SafeTask.Run(() => { // We don't need any processing for static files // It is all done via the Static engine WillProcessDataTags = false; WillProcessMainTags = false; WillProcessOutputTags = false; WillProcessVariables = false; WillProcessLiveVariables = false; // Don't read the file into memory WillReadFileIntoMemory = false; })); }
/// <summary> /// Generates the css contents from the Sass input, storing it in CompiledContents ready for saving /// </summary> /// <param name="data"></param> /// <param name="output"></param> protected override void GenerateOutput(FileProcessingData data, FileOutputData output) { try { // Convert file to css var result = Scss.ConvertToCss(output.FileContents, new ScssOptions() { // Note: It will not generate the file, // only used for exception reporting // includes and source maps InputFile = data.FullPath, OutputFile = output.FullPath, // Set file output style OutputStyle = data.LocalConfiguration.ScssOutputStyle ?? ScssOutputStyle.Compact, // If we should include source map output in result GenerateSourceMap = data.LocalConfiguration.ScssGenerateSourceMaps ?? false, }); output.CompiledContents = result.Css; // If we should generate source map, we have to write that file ourselves if (data.LocalConfiguration.ScssGenerateSourceMaps == true) { // Get map path var mapPath = $"{output.FullPath}.map"; try { // Try and save file FileManager.SaveFile(result.SourceMap, mapPath); } catch (Exception ex) { // Log if we failed data.Error = $"Failed to write Css Source Map file {mapPath}. {ex.Message}"; } } } catch (Exception ex) { data.Error = $"Unexpected error generating Scss output. {ex.Message}"; } }
protected override Task PreProcessFile(FileProcessingData data) { return(SafeTask.Run(() => { // We don't need any processing for Sass files // It is all done via the Sass engine WillProcessDataTags = false; WillProcessMainTags = false; WillProcessOutputTags = false; WillProcessVariables = false; WillProcessLiveVariables = false; // Set this file to partial if it starts with _ // As per the Sass rule data.IsPartial = Path.GetFileName(data.FullPath).StartsWith("_"); // Ignore .sass-cache folder if (data.FullPath.Replace("\\", "/").Contains("/.sass-cache/")) { data.SkipMessage = "Ignoring .sass-cache folder"; } })); }
/// <summary> /// Generate no output as we will do a plain file copy action on save instead /// </summary> /// <param name="data"></param> /// <param name="output"></param> protected override void GenerateOutput(FileProcessingData data, FileOutputData output) { // NOTE: Do nothing on generate output as we will override the save function }
/// <summary> /// Replace C# specific tags /// </summary> /// <param name="data">The file data</param> /// <returns></returns> protected override Task PostProcessFile(FileProcessingData data) { return(SafeTask.Run(() => { // For each output data.OutputPaths.ForEach(output => { // Find all C# data sets Match match = null; // No error to start with data.Error = string.Empty; // Loop through all matches while (match == null || match.Success) { // Find the next data region match = Regex.Match(output.FileContents, mCSharp2GroupRegex, RegexOptions.Singleline); if (!match.Success) { return; } // NOTE: The first group is the full match // The second group is the type // Third group is data // Make sure we have enough groups if (match.Groups.Count < 3) { data.Error = $"Malformed match {match.Value}"; return; } // Take the first match as the header for the type of tag var type = match.Groups[1].Value.Trim(); var datasString = match.Groups[2].Value.Trim(); // Split the data via ; and trim it // Example data would be: group=DomIds; value=Something with space; List <CSharpTagDataItem> propertyData = null; try { propertyData = datasString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(f => { // Get data string var dataString = f?.Trim(); // Make sure we have at least one = after a character if (dataString.IndexOf('=') <= 0) { throw new ArgumentException("Invalid CSharp data item: " + dataString); } // Get name and value var name = dataString.Substring(0, dataString.IndexOf('=')); var value = dataString.Substring(dataString.IndexOf('=') + 1); return new CSharpTagDataItem { Name = name, Value = value }; }).ToList(); } catch (Exception ex) { data.Error = ex.Message; return; } switch (type) { case "properties": // Process the property data ProcessPropertiesTab(data, output, match, propertyData); // Check for success if (!data.Successful) { // Return if it fails return; } break; default: // Report error of unknown match data.Error = $"Unknown match {match.Value}"; return; } } }); })); }
/// <summary> /// Processes a properties tag, replacing it with the variabes found in the given data group /// </summary> /// <param name="data">The file processing data</param> /// <param name="output">The file output data</param> /// <param name="match">The original match that found this information</param> /// <param name="propertyData">The properties data</param> protected void ProcessPropertiesTab(FileProcessingData data, FileOutputData output, Match match, List <CSharpTagDataItem> propertyData) { // No error to start with data.Error = string.Empty; // Get group var group = propertyData.FirstOrDefault(f => f.Name.EqualsIgnoreCase("group"))?.Value; // Find all variables within the specific group // or all variables not in a group if none is specified var variables = output.Variables.Where(f => f.Group.EqualsIgnoreCase(group)).ToList(); // Find the indentation level // Based on the number of whitespace's before the match var indentation = 0; var i = match.Index - 1; while (i > 0 && output.FileContents[i--] == ' ') { indentation++; } // Create indentation string var indentString = "".PadLeft(indentation, ' '); // Remove the original tag ReplaceTag(output, match, string.Empty, removeNewline: false); // If there are no variables, just end if (variables.Count == 0) { return; } // Start region (doesn't need indentation as the original is there) var result = $"#region {group}\r\n\r\n"; // For each variable, convert it to a property variables.ForEach(variable => { // Don't continue if we have an error if (!data.Successful) { return; } // Add the comment var property = (string.IsNullOrEmpty(variable.Comment) ? indentString : GenerateXmlComment(variable.Comment, indentString)); // Get the type var type = variable.XmlElement.Attribute("Type")?.Value ?? variable.XmlElement.Element("Type")?.Value; // Make sure we got a type if (string.IsNullOrEmpty(type)) { data.Error = $"Variable has not specified a type. {variable.XmlElement.ToString()}"; return; } // Add property, leaving a newline for the next property property += $"{indentString}public {type} {variable.Name} {{ get; set; }}{ GenerateValueSetter(type, variable.Value) }\r\n\r\n"; // Add this to the result result += property; }); // Mare sure we had no issues if (!data.Successful) { return; } // End region result += $"{indentString}#endregion\r\n"; // Inject this at the match location output.FileContents = output.FileContents.Insert(match.Index, result); }