public static string Parse(string markdown, Func <string, string> variableEvaluator = null, bool requireCodeBlocks = true) { var lines = markdown.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); // parse and merge code blocks into single syntax tree var mergedYaml = new YamlMappingNode(); bool foundCodeBlock = false; for (int i = 0; i < lines.Length; i++) { CodeFence fenceOpen = TryParseCodeFence(lines[i]); CodeFence fenceClose; // get code block if (fenceOpen != null) { foundCodeBlock = true; var codeBlock = new StringBuilder(); // parse code block i++; while (i < lines.Length && ((fenceClose = TryParseCodeFence(lines[i])) == null || !IsCodeFencePair(fenceOpen, fenceClose))) { codeBlock.AppendLine(lines[i]); i++; } // deserialize and merge var guard = Regex.Match(fenceOpen.InfoString.ResolveVariables(variableEvaluator), @"enabled=(?<guard>\S+)").Groups["guard"]; // TODO: logical ops? var active = !guard.Success || guard.Value == "true"; // TODO: that all? TRUE? 1? wat? if (active) { // deserialize and merge var codeBlockYaml = codeBlock.ToString().ResolveVariables(variableEvaluator).ParseYaml() as YamlMappingNode; if (codeBlockYaml == null) { throw new FormatException("A given code block was not a valid YAML object."); } mergedYaml = mergedYaml.MergeWith(codeBlockYaml); } } } if (requireCodeBlocks && !foundCodeBlock) { throw new FormatException("Require at least one code block in provided markdown."); } // return resulting YAML return(mergedYaml.Serialize()); }
private static bool IsCodeFencePair(CodeFence open, CodeFence close) => open.Fence.Length <= close.Fence.Length && open.Fence[0] == close.Fence[0];