/// <summary> /// Set a Tag value. A null value removes the Tag. /// </summary> /// <param name="key">Tag Name</param> /// <param name="subkey">Nested SimpleTag to find (if non null) Tag name</param> /// <param name="value">value to be set. A list can be passed for a subtag by separating the values by ';'</param> public void Set(string key, string subkey, string value) { if (value == null) { Remove(key, subkey); return; } List<SimpleTag> list = null; SimpleTags.TryGetValue(key, out list); if (list == null) SimpleTags[key] = list = new List<SimpleTag>(1); if (list.Count == 0) list.Add(new SimpleTag()); if (subkey == null) { list[0].Value = value; } else { if (list[0].SimpleTags == null) list[0].SimpleTags = new Dictionary<string, List<SimpleTag>>(StringComparer.OrdinalIgnoreCase); List<SimpleTag> slist = null; list[0].SimpleTags.TryGetValue(subkey, out slist); if (slist == null) slist = new List<SimpleTag>(1); list[0].SimpleTags[subkey] = slist; if (slist.Count == 0) slist.Add(new SimpleTag()); // Sub-values var svalues = value.Split(';'); int j; for (j = 0; j < svalues.Length; j++) { SimpleTag subtag; if (j >= slist.Count) slist.Add(subtag = new SimpleTag()); else subtag = slist[j]; subtag.Value = svalues[j]; } if (j < slist.Count) slist.RemoveRange(j, slist.Count - j); } }
private static void ExtractStepInfo(Guide aGuide, Step aStep, string aFileContents, string aStepDirectory) { aStep.IsValid = true; bool validTitleFound = false; bool validStepNumberFound = false; bool wasNewLine = true; for (int index = 0; index < aFileContents.Length; index++) { var character = aFileContents[index]; if (wasNewLine && character == '#') { continue; } wasNewLine = character == '\r' || character == '\n'; if (TagParser.ParseTag(aFileContents, ref index, out var tag, out var tagContent, out var attributes, isIncrementIndex: true)) { if (SimpleTags.IsTag(SimpleTags.Tag.Title, tag)) { aStep.Title = SimpleTags.GetContent <string>(tagContent); validTitleFound = !string.IsNullOrEmpty(aStep.Title); } else if (SimpleTags.IsTag(SimpleTags.Tag.Image, tag)) { ClassEnum classEnum = ClassEnum.All; if (attributes.ContainsKey("class")) //TODO make hard reference { classEnum = SimpleTags.GetContent <ClassEnum>(attributes["class"]); } aStep.ImageSources[classEnum] = Path.Combine(aStepDirectory, SimpleTags.GetContent <string>(tagContent)); } else if (SimpleTags.IsTag(SimpleTags.Tag.StepNumber, tag)) { aStep.StepNumber = SimpleTags.GetContent <int>(tagContent); validStepNumberFound = true; } else if (SimpleTags.IsTag(SimpleTags.Tag.SubStep, tag)) { SubStep subStep = SubStep.Parse(aGuide, aStep, attributes, tagContent); if (subStep.IsValid) { aStep.SubSteps.Add(subStep); } } } } aStep.ValidateImageSources(); if (!validTitleFound || !validStepNumberFound) { aStep.IsValid = false; } }
public static SubStep Parse(Guide aGuide, Step aStep, Dictionary <string, string> aDictionaryOfAttributes, string aFileContent) { SubStep result = new SubStep(aGuide, aStep); result.StepDirectory = aStep.StepDirectory; if (!aDictionaryOfAttributes.TryGetValue("order", out string orderAttribute) || !int.TryParse(orderAttribute, out int order)) { result.IsValid = false; return(result); } result.StepOrder = order; result.IsValid = true; if (aDictionaryOfAttributes.TryGetValue("class", out string classAttribute)) { result.ClassFlags = SimpleTags.GetContent <ClassEnum>(classAttribute); } else { result.ClassFlags = ClassEnum.All; } if (aDictionaryOfAttributes.TryGetValue("legend", out string legendAttribute)) { result.Legend = SimpleTags.GetContent <Color>(legendAttribute); } StringBuilder contentBuilder = new StringBuilder(); bool? hasFirstLineTab = null; foreach (var line in aFileContent.Split(Environment.NewLine.ToCharArray())) { if (string.IsNullOrEmpty(line.Trim()) || line.Trim().StartsWith("#")) { continue; } if (!hasFirstLineTab.HasValue) { hasFirstLineTab = line.StartsWith("\t"); } if (hasFirstLineTab.Value && line.StartsWith("\t")) { contentBuilder.AppendLine(line.Substring(1, line.Length - 1)); } else { contentBuilder.AppendLine(line); } } result.StepText = contentBuilder.ToString(); return(result); }
/// <summary> /// Retrieve a Tag list. If there are multiple tag inside a SimpleTag (when /// accessing a sub-key), these sub-list are represented as semicolon-separated /// values. /// </summary> /// <param name="key">Tag name</param> /// <param name="subkey">Nested SimpleTag to find (if non null) Tag name</param> /// <param name="recu">Also search in parent Tag if true (default: true)</param> /// <returns>Array of values. Nested sub-list are represented by a semicolon- /// separated string /// </returns> public string[] Get(string key, string subkey = null, bool recu = true) { string[] ret = null; List<SimpleTag> mtags; if ((!SimpleTags.TryGetValue(key, out mtags) || mtags == null) && recu) { Tag tag = this; while ((tag = tag.Parent) != null && !tag.SimpleTags.TryGetValue(key, out mtags)) ; } if (subkey != null && mtags != null) { ret = new string[mtags.Count]; // Handle Nested SimpleTags for (int i = 0; i < mtags.Count; i++) { string str = null; var stag = mtags[i]; if (stag.SimpleTags != null) { List<SimpleTag> list = null; stag.SimpleTags.TryGetValue(subkey, out list); if (list == null || list.Count==0) { str = null; } if (mtags.Count == 1) { str = list[0]; } else { str = string.Join("; ", list); } } ret[i] = str; } } else if (mtags != null) { ret = new string[mtags.Count]; for (int i = 0; i < mtags.Count; i++) { ret[i] = mtags[i]; } } return ret; }
public List <string> GetRenderedTags() { var renderedTags = new List <string>(); SimpleTags.ForEach(st => renderedTags.Add(st.Value)); ComplexTags.ForEach(ct => renderedTags.Add(ct.FormattedValue)); CoerceLegalTags(renderedTags); return(renderedTags); }
/// <summary> /// Remove a Tag /// </summary> /// <param name="key">Tag Name</param> /// <param name="subkey">Nested SimpleTag to find (if non null) Tag name</param> public void Remove(string key, string subkey = null) { List <SimpleTag> list = null; if (SimpleTags.TryGetValue(key, out list)) { if (list != null) { if (subkey != null) { foreach (var stag in list) { if (stag.SimpleTags != null) { List <SimpleTag> slist = null; stag.SimpleTags.TryGetValue(subkey, out slist); if (slist != null) { if (list.Count > 1) { if (slist.Count > 0) { slist.RemoveAt(0); } } else { slist.Clear(); } } } } } else { list.Clear(); } } if (subkey == null) { SimpleTags.Remove(key); } } }
/// <summary> /// Retrieve a list of SimpleTag sharing the same TagName (key). /// </summary> /// <param name="key">Tag name</param> /// <param name="subkey">Nested SimpleTag to find (if non null) Tag name</param> /// <param name="recu">Also search in parent Tag if true (default: true)</param> /// <returns>Array of values</returns> public List <SimpleTag> GetSimpleTags(string key, string subkey = null, bool recu = true) { List <SimpleTag> mtags; if ((!SimpleTags.TryGetValue(key, out mtags) || mtags == null) && recu) { Tag tag = this; while ((tag = tag.Parent) != null && !tag.SimpleTags.TryGetValue(key, out mtags)) { ; } } // Handle Nested SimpleTags if (subkey != null && mtags != null) { var subtags = new List <SimpleTag>(mtags.Count); foreach (var stag in mtags) { if (stag.SimpleTags != null) { List <SimpleTag> list = null; stag.SimpleTags.TryGetValue(subkey, out list); if (mtags.Count > 1) { subtags.Add(list != null && list.Count > 0 ? list[0] : null); } else { subtags = list; } } } return(subtags); } return(mtags); }
public static Guide Parse(string aDirectory) { Guide result = new Guide(); bool titleFound = false; bool classFound = false; if (!File.Exists(Path.Combine(aDirectory, GuideInfoFile))) { return(result); } string guideFileContent = File.ReadAllText(Path.Combine(aDirectory, GuideInfoFile)); foreach (var line in guideFileContent.Split(Environment.NewLine.ToCharArray()).Select(l => l.Trim()).Where(l => !string.IsNullOrEmpty(l))) { int index = 0; if (TagParser.ParseTag(line, ref index, out string tag, out string tagContent, out var attributes, isIncrementIndex: false)) { if (SimpleTags.IsTag(SimpleTags.Tag.Title, tag)) { result.Title = SimpleTags.GetContent <string>(tagContent); titleFound = true; } else if (SimpleTags.IsTag(SimpleTags.Tag.Class, tag)) { result.Classes = SimpleTags.GetContent <ClassEnum>(tagContent); classFound = true; } } } result.IsValid = titleFound && classFound; if (result.IsValid) { ParseSteps(result, aDirectory); } return(result); }
/// <summary> /// Create or overwrite the actual tags of a given name/sub-name by new values. /// </summary> /// <param name="key">Tag Name</param> /// <param name="subkey">Nested SimpleTag to find (if non null) Tag name</param> /// <param name="values">Array of values. for each subtag value, a list can be passed by separating the values by ';'</param> public void Set(string key, string subkey, string[] values) { if (values == null) { Remove(key, subkey); return; } List <SimpleTag> list = null; SimpleTags.TryGetValue(key, out list); if (list == null) { SimpleTags[key] = list = new List <SimpleTag>(1); } int i; for (i = 0; i < values.Length; i++) { SimpleTag stag; if (i >= list.Count) { list.Add(stag = new SimpleTag()); } else { stag = list[i]; } if (subkey == null) { stag.Value = values[i]; } else { if (stag.SimpleTags == null) { stag.SimpleTags = new Dictionary <string, List <SimpleTag> >(StringComparer.OrdinalIgnoreCase); } List <SimpleTag> slist = null; stag.SimpleTags.TryGetValue(subkey, out slist); if (slist == null) { slist = new List <SimpleTag>(1); } stag.SimpleTags[subkey] = slist; // Sub-values var svalues = values[i].Split(';'); int j; for (j = 0; j < svalues.Length; j++) { SimpleTag subtag; if (j >= slist.Count) { slist.Add(subtag = new SimpleTag()); } else { subtag = slist[j]; } subtag.Value = svalues[j]; } if (j < slist.Count) { slist.RemoveRange(j, slist.Count - j); } } } if (subkey == null && i < list.Count) { list.RemoveRange(i, list.Count - i); } }
private void AddText(string aText, ref bool isQuestChanges, Span aCurrentSpan = null, string aCurrentText = null, bool isUnderline = false) { var textLines = aText.Split(Environment.NewLine.ToCharArray()); if (aCurrentSpan == null) { aCurrentSpan = new Span(); _paragraph.Inlines.Add(aCurrentSpan); } if (aCurrentText == null) { aCurrentText = string.Empty; } string[] realLines = textLines.Where(t => !t.Trim().StartsWith("#") && !string.IsNullOrEmpty(t.Trim())).ToArray(); for (int i = 0; i < realLines.Length; i++) { string line = realLines[i]; for (int charInde = 0; charInde < line.Length; charInde++) { if (line[charInde] == '\t') { aCurrentText += " "; continue; } if (TagParser.ParseTag(line, ref charInde, out var tag, out var tagContent, out var attributes)) { //Regular text if (!string.IsNullOrEmpty(aCurrentText)) { aCurrentSpan.Inlines.Add(GetText(aCurrentText, isUnderline)); aCurrentText = string.Empty; } if (SimpleTags.IsTag(SimpleTags.Tag.Legend, tag)) { var legendColor = SimpleTags.GetContent <Color>(tagContent); aCurrentSpan.Inlines.Add(CreateLegendRectangle(legendColor)); } else if (SimpleTags.IsTag(SimpleTags.Tag.TLoc, tag)) { var tloc = SimpleTags.GetContent <Point>(tagContent); if (double.IsNaN(tloc.X) || double.IsNaN(tloc.Y)) { aCurrentSpan.Inlines.Add(GetText("(error)", isUnderline)); } else { var tlocRun = new TLocInline(this, tloc, tagContent); aCurrentSpan.Inlines.Add(tlocRun); } } else if (SimpleTags.IsTag(SimpleTags.Tag.Bold, tag)) { var boldSpan = new Span(); boldSpan.FontWeight = FontWeights.Bold; aCurrentSpan.Inlines.Add(boldSpan); AddText(tagContent, ref isQuestChanges, aCurrentSpan: boldSpan, aCurrentText: aCurrentText, isUnderline: isUnderline); } else if (SimpleTags.IsTag(SimpleTags.Tag.Place, tag)) //Maybe do something else for this, same as bold atm { var boldSpan = new Span(); boldSpan.FontWeight = FontWeights.Bold; aCurrentSpan.Inlines.Add(boldSpan); AddText(tagContent, ref isQuestChanges, aCurrentSpan: boldSpan, aCurrentText: aCurrentText, isUnderline: isUnderline); } else if (SimpleTags.IsTag(SimpleTags.Tag.Italic, tag)) { var italicSpan = new Span(); italicSpan.FontStyle = FontStyles.Italic; aCurrentSpan.Inlines.Add(italicSpan); AddText(tagContent, ref isQuestChanges, aCurrentSpan: italicSpan, aCurrentText: aCurrentText, isUnderline: isUnderline); } else if (SimpleTags.IsTag(SimpleTags.Tag.Underline, tag)) { AddText(tagContent, ref isQuestChanges, aCurrentSpan: aCurrentSpan, aCurrentText: aCurrentText, isUnderline: true); } else if (SimpleTags.IsTag(SimpleTags.Tag.DONTFORGET, tag)) { var empesizedSpan = new Span(); empesizedSpan.FontStyle = FontStyles.Italic; empesizedSpan.FontWeight = FontWeights.ExtraBold; empesizedSpan.FontSize = aCurrentSpan.FontSize + 5; aCurrentSpan.Inlines.Add(empesizedSpan); AddText(tagContent, ref isQuestChanges, aCurrentSpan: empesizedSpan, aCurrentText: aCurrentText, isUnderline: isUnderline); } else if (SimpleTags.IsTag(SimpleTags.Tag.Picture, tag)) { string url = string.Empty; attributes.TryGetValue("url", out url); { //TODO make hard reference url = System.IO.Path.Combine(_stepDirectory, url); aCurrentSpan.Inlines.Add(new PictureLinkInline(this, url, tagContent)); } } else if (SimpleTags.IsTag(SimpleTags.Tag.LineBreak, tag)) { //aCurrentSpan.Inlines.Add(new LineBreak()); } else { var tagType = SimpleTags.GetTagFromString(tag); var colorSpan = new Span(); colorSpan.Foreground = new SolidColorBrush(TextColors.GetColorFromTag(tagType)); if (IsQuestTag(tagType)) { isQuestChanges = true; tagContent = HandleQuestTags(tagType, tagContent, attributes); } aCurrentSpan.Inlines.Add(colorSpan); if (attributes.Any(a => a.Key == "isTargetLink".ToLower() && bool.TryParse(a.Value, out bool isTargetLink) && isTargetLink)) { colorSpan.Inlines.Add(new CopyToClipboardInline(this, tagContent, $"/targetexact {tagContent}")); }