/// <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);
     }));
 }
        /// <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}";
            }
        }
 /// <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>
        /// 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);
        }