/// <summary> /// Add text as lg file content to template engine. A fullpath id is needed when importResolver is empty, or simply pass in customized importResolver. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">id is the content identifier. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>Template engine with the parsed content.</returns> public TemplateEngine AddText(string content, string id = "", ImportResolverDelegate importResolver = null) { CheckImportResolver(id, importResolver); var rootResource = LGParser.Parse(content, id); var lgresources = rootResource.DiscoverDependencies(importResolver); Templates.AddRange(lgresources.SelectMany(x => x.Templates)); RunStaticCheck(Templates); return(this); }
/// <summary> /// Add a new template and return LG resource. /// </summary> /// <param name="templateName">new template name.</param> /// <param name="parameters">new params.</param> /// <param name="templateBody">new template body.</param> /// <returns>new lg resource.</returns> public LGResource AddTemplate(string templateName, List <string> parameters, string templateBody) { var template = Templates.FirstOrDefault(u => u.Name == templateName); if (template != null) { throw new Exception($"template {templateName} already exists."); } var templateNameLine = BuildTemplateNameLine(templateName, parameters); var newTemplateBody = ConvertTemplateBody(templateBody); var newContent = $"{Content}\r\n{templateNameLine}\r\n{newTemplateBody}"; return(LGParser.Parse(newContent, Id)); }
/// <summary> /// Delete an exist template. /// </summary> /// <param name="templateName">which template should delete.</param> /// <returns>updated LG file.</returns> public LGFile DeleteTemplate(string templateName) { var template = Templates.FirstOrDefault(u => u.Name == templateName); if (template != null) { var startLine = template.ParseTree.Start.Line - 1; var stopLine = template.ParseTree.Stop.Line - 1; var newContent = ReplaceRangeContent(Content, startLine, stopLine, null); Initialize(LGParser.ParseText(newContent, Id, ImportResolver)); } return(this); }
/// <summary> /// Delete an exist template. /// </summary> /// <param name="templateName">which template should delete.</param> /// <returns>return the new lg resource.</returns> public LGResource DeleteTemplate(string templateName) { var template = Templates.FirstOrDefault(u => u.Name == templateName); if (template == null) { return(this); } var startLine = template.ParseTree.Start.Line - 1; var stopLine = template.ParseTree.Stop.Line - 1; var newContent = ReplaceRangeContent(Content, startLine, stopLine, null); return(LGParser.Parse(newContent, Id)); }
/// <summary> /// Add a new template and return LG File. /// </summary> /// <param name="templateName">new template name.</param> /// <param name="parameters">new params.</param> /// <param name="templateBody">new template body.</param> /// <returns>updated LG file.</returns> public LGFile AddTemplate(string templateName, List <string> parameters, string templateBody) { var template = Templates.FirstOrDefault(u => u.Name == templateName); if (template != null) { throw new Exception(LGErrors.TemplateExist(templateName)); } var templateNameLine = BuildTemplateNameLine(templateName, parameters); var newTemplateBody = ConvertTemplateBody(templateBody); var newContent = $"{Content.TrimEnd()}\r\n\r\n{templateNameLine}\r\n{newTemplateBody}\r\n"; Initialize(LGParser.ParseText(newContent, Id, ImportResolver)); return(this); }
/// <summary> /// Use to evaluate an inline template str. /// </summary> /// <param name="inlineStr">inline string which will be evaluated.</param> /// <param name="scope">scope object or JToken.</param> /// <returns>Evaluate result.</returns> public object Evaluate(string inlineStr, object scope = null) { // wrap inline string with "# name and -" to align the evaluation process var fakeTemplateId = "__temp__"; inlineStr = !inlineStr.Trim().StartsWith("```") && inlineStr.IndexOf('\n') >= 0 ? "```" + inlineStr + "```" : inlineStr; var wrappedStr = $"# {fakeTemplateId} \r\n - {inlineStr}"; var lgsource = LGParser.Parse(wrappedStr, "inline"); var templates = Templates.Concat(lgsource.Templates).ToList(); RunStaticCheck(templates); var evaluator = new Evaluator(templates, this.expressionEngine); return(evaluator.EvaluateTemplate(fakeTemplateId, scope)); }
/// <summary> /// update an exist template. /// </summary> /// <param name="templateName">origin template name. the only id of a template.</param> /// <param name="newTemplateName">new template Name.</param> /// <param name="parameters">new params.</param> /// <param name="templateBody">new template body.</param> /// <returns>updated LG file.</returns> public LGFile UpdateTemplate(string templateName, string newTemplateName, List <string> parameters, string templateBody) { var template = Templates.FirstOrDefault(u => u.Name == templateName); if (template != null) { var templateNameLine = BuildTemplateNameLine(newTemplateName, parameters); var newTemplateBody = ConvertTemplateBody(templateBody); var content = $"{templateNameLine}\r\n{newTemplateBody}\r\n"; var startLine = template.ParseTree.Start.Line - 1; var stopLine = template.ParseTree.Stop.Line - 1; var newContent = ReplaceRangeContent(Content, startLine, stopLine, content); Initialize(LGParser.ParseText(newContent, Id, ImportResolver)); } return(this); }
/// <summary> /// update an exist template. /// </summary> /// <param name="templateName">origin template name. the only id of a template.</param> /// <param name="parameters">new params.</param> /// <param name="templateBody">new template body.</param> /// <returns>new LG resource.</returns> public LGResource UpdateTemplate(string templateName, List <string> parameters, string templateBody) { var template = Templates.FirstOrDefault(u => u.Name == templateName); if (template == null) { return(this); } var templateNameLine = BuildTemplateNameLine(templateName, parameters); var newTemplateBody = ConvertTemplateBody(templateBody); var content = $"{templateNameLine}\r\n{newTemplateBody}"; var startLine = template.ParseTree.Start.Line - 1; var stopLine = template.ParseTree.Stop.Line - 1; var newContent = ReplaceRangeContent(Content, startLine, stopLine, content); return(LGParser.Parse(newContent, Id)); }
/// <summary> /// Load .lg files into template engine /// You can add one file, or mutlple file as once /// If you have multiple files referencing each other, make sure you add them all at once, /// otherwise static checking won't allow you to add it one by one. /// </summary> /// <param name="filePaths">Paths to .lg files.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>Teamplate engine with parsed files.</returns> public TemplateEngine AddFiles(IEnumerable <string> filePaths, ImportResolverDelegate importResolver = null) { var totalLGResources = new List <LGResource>(); foreach (var filePath in filePaths) { var fullPath = Path.GetFullPath(ImportResolver.NormalizePath(filePath)); var rootResource = LGParser.Parse(File.ReadAllText(fullPath), fullPath); var lgresources = rootResource.DiscoverDependencies(importResolver); totalLGResources.AddRange(lgresources); } // Remove duplicated lg files by id var deduplicatedLGResources = totalLGResources.GroupBy(x => x.Id).Select(x => x.First()).ToList(); Templates.AddRange(deduplicatedLGResources.SelectMany(x => x.Templates)); RunStaticCheck(Templates); return(this); }
public List <Diagnostic> CheckFiles(IEnumerable <string> filePaths, ImportResolverDelegate importResolver = null) { var result = new List <Diagnostic>(); var templates = new List <LGTemplate>(); var isParseSuccess = true; try { var totalLGResources = new List <LGResource>(); foreach (var filePath in filePaths) { // do not use ??=, it will cause issue in the C# < 8.0 importResolver = importResolver ?? ImportResolver.FileResolver; var fullPath = Path.GetFullPath(ImportResolver.NormalizePath(filePath)); var rootResource = LGParser.Parse(File.ReadAllText(fullPath), fullPath); var resources = rootResource.DiscoverDependencies(importResolver); totalLGResources.AddRange(resources); } var deduplicatedLGResources = totalLGResources.GroupBy(x => x.Id).Select(x => x.First()).ToList(); templates = deduplicatedLGResources.SelectMany(x => x.Templates).ToList(); } catch (LGException ex) { result.AddRange(ex.Diagnostics); isParseSuccess = false; } catch (Exception err) { result.Add(new Diagnostic(new Range(new Position(0, 0), new Position(0, 0)), err.Message)); isParseSuccess = false; } if (isParseSuccess) { result.AddRange(CheckTemplates(templates)); } return(result); }
public List <Diagnostic> CheckText(string content, string id = "", ImportResolverDelegate importResolver = null) { if (importResolver == null) { var importPath = ImportResolver.NormalizePath(id); if (!Path.IsPathRooted(importPath)) { throw new Exception("[Error] id must be full path when importResolver is null"); } } var result = new List <Diagnostic>(); var templates = new List <LGTemplate>(); var isParseSuccess = true; try { var rootResource = LGParser.Parse(content, id); var resources = rootResource.DiscoverDependencies(importResolver); templates = resources.SelectMany(x => x.Templates).ToList(); } catch (LGException ex) { result.AddRange(ex.Diagnostics); isParseSuccess = false; } catch (Exception err) { result.Add(new Diagnostic(new Range(new Position(0, 0), new Position(0, 0)), err.Message)); isParseSuccess = false; } if (isParseSuccess) { result.AddRange(CheckTemplates(templates)); } return(result); }
/// <summary> /// Use to evaluate an inline template str. /// </summary> /// <param name="inlineStr">inline string which will be evaluated.</param> /// <param name="scope">scope object or JToken.</param> /// <returns>Evaluate result.</returns> public object Evaluate(string inlineStr, object scope = null) { if (inlineStr == null) { throw new ArgumentException("inline string is null."); } CheckErrors(); // wrap inline string with "# name and -" to align the evaluation process var fakeTemplateId = Guid.NewGuid().ToString(); var multiLineMark = "```"; inlineStr = !inlineStr.Trim().StartsWith(multiLineMark) && inlineStr.Contains('\n') ? $"{multiLineMark}{inlineStr}{multiLineMark}" : inlineStr; var newContent = $"# {fakeTemplateId} \r\n - {inlineStr}"; var newLgFile = LGParser.ParseTextWithRef(newContent, this); return(newLgFile.EvaluateTemplate(fakeTemplateId, scope)); }
/// <summary> /// Resolve imported LG resources from a start resource. /// All the imports will be visited and resolved to LGResouce list. /// </summary> /// <param name="start">The lg resource from which to start resolving imported resources.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <param name="resourcesFound">Resources that have been found.</param> private void ResolveImportResources(LGResource start, ImportResolverDelegate importResolver, HashSet <LGResource> resourcesFound) { var resourceIds = start.Imports.Select(lg => lg.Id).ToList(); resourcesFound.Add(start); foreach (var id in resourceIds) { try { var(content, path) = importResolver(start.Id, id); var childResource = LGParser.Parse(content, path); if (!resourcesFound.Contains(childResource)) { ResolveImportResources(childResource, importResolver, resourcesFound); } } catch (Exception err) { throw new Exception($"[Error]{id}:{err.Message}", err); } } }