diff --git a/AzureLiquid.Preview/PreviewProcess.cs b/AzureLiquid.Preview/PreviewProcess.cs
index 8cbd8f3..432e82d 100644
--- a/AzureLiquid.Preview/PreviewProcess.cs
+++ b/AzureLiquid.Preview/PreviewProcess.cs
@@ -12,6 +12,11 @@ namespace AzureLiquid.Preview;
///
public class PreviewProcess
{
+ ///
+ /// The argument parser.
+ ///
+ private readonly PreviewProcessArguments _args;
+
///
/// Handles writing console output to private persisted log.
///
@@ -32,6 +37,7 @@ public class PreviewProcess
///
public PreviewProcess()
{
+ _args = new PreviewProcessArguments();
Template = string.Empty;
Content = string.Empty;
Output = "./preview.txt";
@@ -68,7 +74,7 @@ public PreviewProcess()
public string Output { get; set; }
///
- /// Gets a value indicating whether the process should watch for changes to template or content files.
+ /// Gets or sets a value indicating whether the process should watch for changes to template or content files.
///
///
/// true if should watch; otherwise, false.
@@ -87,16 +93,19 @@ public PreviewProcess()
///
/// Start a new instance of the class using the incoming arguments.
///
- /// The process arguments
+ /// The process arguments.
/// A new instance of the class.
[ExcludeFromCodeCoverage]
public static PreviewProcess Create(string[] args)
{
var preview = new PreviewProcess();
- // deepcode ignore XmlInjection: XML is not used by this application, it is passed back to the user, deepcode ignore XXE:
- preview.ParseArguments(args);
+ preview.Template = preview._args.ParsePath(args, "template");
+ preview.Content = preview._args.ParsePath(args, "content");
+ preview.Output = preview._args.ParsePath(args, "output");
+
HandleNoArgumentsPassed(args, preview);
+
if (preview.CanRender)
{
RenderAndWatch(preview);
@@ -109,107 +118,6 @@ public static PreviewProcess Create(string[] args)
return preview;
}
- /// Parses the arguments and sets process options.
- ///
- /// The arguments. Values are expected to be "--template", "--help", "--content", "--output" or
- /// "--watch".
- ///
- private void ParseArguments(string[] args)
- {
- for (var index = 0; index < args.Length; index++)
- {
- var arg = args[index];
- var path = Directory.GetCurrentDirectory();
- ParseTemplate(args, index, arg, path);
- ParseContent(args, index, arg, path);
- ParseOutputResults(args, index, arg, path);
-
- // Switch watch param if needed
- if (IsArgMatch(arg, "watch"))
- {
- ShouldWatch = true;
- }
-
- // Show help info
- if (IsArgMatch(arg, "help"))
- {
- WriteHelpOutput();
- }
- }
- }
-
- ///
- /// Parses the output results file path if specified.
- ///
- /// The passed command arguments.
- /// The parameter index.
- /// The current argument.
- /// The target path.
- private void ParseOutputResults(string[] args, int index, string arg, string path)
- {
- if (!IsArgMatch(arg, "output") || index - 1 >= args.Length)
- {
- return;
- }
-
- try
- {
- Output = Path.GetFullPath(args[index + 1], path);
- }
- catch
- {
- WriteErrorLine($"Invalid output path: {args[index + 1]}");
- }
- }
-
- ///
- /// Parses the incoming content file path if specified.
- ///
- /// The passed command arguments.
- /// The parameter index.
- /// The current argument.
- /// The target path.
- private void ParseContent(string[] args, int index, string arg, string path)
- {
- if (!IsArgMatch(arg, "content") || index - 1 >= args.Length)
- {
- return;
- }
-
- try
- {
- Content = Path.GetFullPath(args[index + 1], path);
- }
- catch
- {
- WriteErrorLine($"Invalid content path: {args[index + 1]}");
- }
- }
-
- ///
- /// Parses the incoming template file path if specified.
- ///
- /// The passed command arguments.
- /// The parameter index.
- /// The current argument.
- /// The target path.
- private void ParseTemplate(string[] args, int index, string arg, string path)
- {
- if (!IsArgMatch(arg, "template") || index - 1 >= args.Length)
- {
- return;
- }
-
- try
- {
- Template = Path.GetFullPath(args[index + 1], path);
- }
- catch
- {
- WriteErrorLine($"Invalid template path: {args[index + 1]}");
- }
- }
-
///
/// Renders the output and watches for changes if specified.
///
@@ -308,67 +216,102 @@ public string Render()
{
if (!CanRender)
{
- WriteErrorLine("Unable to render as inputs our outputs not found or not specified");
+ WriteErrorLine("Unable to render as inputs or outputs not found or not specified");
return string.Empty;
}
- string content;
- try
+ var content = ReadFileContent(Content);
+ if (string.IsNullOrEmpty(content))
{
- content = File.ReadAllText(Content);
+ return string.Empty;
}
- catch (IOException)
+
+ var template = ReadFileContent(Template);
+ if (string.IsNullOrEmpty(template))
{
- // Lock issue, wait and retry
- Thread.Sleep(TimeSpan.FromSeconds(1));
- return Render();
+ return string.Empty;
}
- string template;
+ var parser = new LiquidParser();
+ if (!SetParserContent(parser, content))
+ {
+ return string.Empty;
+ }
+
+ return RenderTemplate(parser, template);
+ }
+
+ ///
+ /// Reads the file content.
+ ///
+ /// The file path.
+ /// The file content.
+ private string ReadFileContent(string filePath)
+ {
try
{
- template = File.ReadAllText(Template);
+ return File.ReadAllText(filePath);
}
catch (IOException)
{
// Lock issue, wait and retry
Thread.Sleep(TimeSpan.FromSeconds(1));
- return Render();
+ return ReadFileContent(filePath);
}
+ catch (Exception e)
+ {
+ LogWarning($"Unable to read file: {filePath}", e);
+ return string.Empty;
+ }
+ }
- var parser = new LiquidParser();
-
- if (Content.ToLowerInvariant().EndsWith(".json"))
+ ///
+ /// Sets the parser content.
+ ///
+ /// The parser.
+ /// The content.
+ ///
+ /// true if the content was set; otherwise, false.
+ ///
+ private bool SetParserContent(LiquidParser parser, string content)
+ {
+ try
{
- try
+ if (Content.ToLowerInvariant().EndsWith(".json"))
{
parser.SetContentJson(content);
}
- catch (Exception e)
- {
- LogWarning(" Unable to read input JSON file", e);
- return string.Empty;
- }
- }
-
- if (Content.ToLowerInvariant().EndsWith(".xml"))
- {
- try
+ else if (Content.ToLowerInvariant().EndsWith(".xml"))
{
parser.SetContentXml(content);
}
- catch (Exception ex)
+ else
{
- LogWarning(" Unable to read input XML file", ex);
- return string.Empty;
+ WriteErrorLine("Unsupported content type");
+ return false;
}
}
+ catch (Exception e)
+ {
+ LogWarning("Unable to set parser content", e);
+ return false;
+ }
+
+ return true;
+ }
+ ///
+ /// Renders the template.
+ ///
+ /// The parser.
+ /// The template.
+ /// The output from the template.
+ private string RenderTemplate(LiquidParser parser, string template)
+ {
try
{
var output = parser.Parse(template).Render();
File.WriteAllText(Output, output);
-
return output;
}
catch (Exception e)
@@ -376,8 +319,6 @@ public string Render()
WriteErrorLine($"Error: {e.Message}");
return string.Empty;
}
-
- // TODO: Refactor this method
}
///
diff --git a/AzureLiquid.Preview/PreviewProcessArguments.cs b/AzureLiquid.Preview/PreviewProcessArguments.cs
new file mode 100644
index 0000000..91e6495
--- /dev/null
+++ b/AzureLiquid.Preview/PreviewProcessArguments.cs
@@ -0,0 +1,63 @@
+namespace AzureLiquid.Preview;
+
+///
+/// Handles the arguments passed to the preview process.
+///
+public class PreviewProcessArguments
+{
+ ///
+ /// The current path of the process.
+ ///
+ private readonly string _path;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PreviewProcessArguments() => _path = Directory.GetCurrentDirectory();
+
+ ///
+ /// Gets the index of the argument, if it exists.
+ ///
+ /// The key.
+ /// The index of the argument.
+ private static int GetArgumentIndex(string[] args, string key)
+ {
+ for (int i = 0; i < args?.Length; i++)
+ {
+ if (IsArgMatch(args[i], key))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ ///
+ /// Determines whether the argument matches the partial argument key name.
+ ///
+ /// The argument.
+ /// The key.
+ ///
+ /// true if argument found; otherwise, false.
+ ///
+ private static bool IsArgMatch(string arg, string key)
+ {
+ return string.CompareOrdinal(arg, "--" + key) == 0;
+ }
+
+ ///
+ /// Parses the argument value.
+ ///
+ /// The arguments.
+ /// The key.
+ /// The argument value.
+ public string ParsePath(string[] args, string key)
+ {
+ var index = GetArgumentIndex(args, key);
+ return
+ index == -1 || index - 1 >= args?.Length || args == null ? string.Empty : // No match, or no arguments passed
+ Path.GetFullPath(args[index + 1], _path) // Argument found, parsing path
+ ?? string.Empty; // Argument found, but path is invalid
+ }
+}
\ No newline at end of file
diff --git a/AzureLiquid.Tests/PreviewProcessTests.cs b/AzureLiquid.Tests/PreviewProcessTests.cs
index 0a3e993..9356741 100644
--- a/AzureLiquid.Tests/PreviewProcessTests.cs
+++ b/AzureLiquid.Tests/PreviewProcessTests.cs
@@ -72,7 +72,6 @@ public void EnsurePreviewParsingCSharpArguments()
///
/// Ensure the preview process can be created from a set of arguments.
///
- /// Determine if a log should be produced.
/// First argument.
/// Second argument.
/// Third argument.
@@ -82,16 +81,13 @@ public void EnsurePreviewParsingCSharpArguments()
/// Seventh argument.
/// Eighth argument.
[Theory]
- [InlineData(false, "", "", "", "", "", "", "", "")]
- [InlineData(false, "--template", "./Resources/event.liquid", "--content", "./Resources/event.json", "--output",
- "./Resources/preview.txt", "", "")]
- [InlineData(false, "--template", "./Resources/event.liquid", "", "", "", "", "", "")]
- [InlineData(false, "--watch", "", "", "", "", "", "", "")]
- [InlineData(true, "--help", "", "", "", "", "", "", "")]
- [InlineData(true, "--template", "./Resources/event_not_found.liquid", "--content", "./Resources/event.xml",
- "--output", "./Resources/preview.txt", "", "")]
- public void EnsureArgumentParsing(bool shouldLog, string arg1, string arg2, string arg3, string arg4, string arg5,
- string arg6, string arg7, string arg8)
+ [InlineData("", "", "", "", "", "", "", "")]
+ [InlineData("--template", "./Resources/event.liquid", "--content", "./Resources/event.json", "--output", "./Resources/preview.txt", "", "")]
+ [InlineData("--template", "./Resources/event.liquid", "", "", "", "", "", "")]
+ [InlineData("--watch", "", "", "", "", "", "", "")]
+ [InlineData("--help", "", "", "", "", "", "", "")]
+ [InlineData("--template", "./Resources/event_not_found.liquid", "--content", "./Resources/event.xml", "--output", "./Resources/preview.txt", "", "")]
+ public void EnsureArgumentParsing(string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8)
{
// Arrange
var args = new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
@@ -101,17 +97,11 @@ public void EnsureArgumentParsing(bool shouldLog, string arg1, string arg2, stri
// Assert
preview.Should().NotBeNull("A preview process should have been created");
-
- if (shouldLog)
- {
- preview.Log.Should().NotBeEmpty("A log should have been created");
- }
- else
- {
- preview.Log.Should().BeEmpty("No log should have been created");
- }
}
+ ///
+ /// Ensure the preview process can be created from a set of arguments.
+ ///
[Fact]
public void EnsureObjectCreation()
{
@@ -153,8 +143,6 @@ public void EnsureWatcher()
instance.Log.Should().NotBeEmpty("A log should have been created");
}
- #region Nested type: Arrangement
-
///
/// Contains arranged values used for testing, containing mock instances and expected return values.
///
@@ -222,6 +210,4 @@ public static string GetPath(string path)
return Path.GetFullPath(path, basePath);
}
}
-
- #endregion
}
\ No newline at end of file