public override void Render(Context context, TextWriter result) { IFileSystem fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; string source = fileSystem.ReadTemplateFile(context, _templateName); Template partial = Template.Parse(source); string shortenedTemplateName = _templateName.Substring(1, _templateName.Length - 2); object variable = context[_variableName ?? shortenedTemplateName]; context.Stack(() => { foreach (var keyValue in _attributes) { context[keyValue.Key] = context[keyValue.Value]; } if (variable is IEnumerable) { ((IEnumerable)variable).Cast <object>().ToList().ForEach(v => { context[shortenedTemplateName] = v; partial.Render(result, RenderParameters.FromContext(context)); }); return; } context[shortenedTemplateName] = variable; partial.Render(result, RenderParameters.FromContext(context)); }); }
public override void Render(Context context, TextWriter result) { IFileSystem fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; string source = fileSystem.ReadTemplateFile(context, _templateName); Template template = Template.Parse(source); List <Block> parentBlocks = FindBlocks(template.Root); Blocks.ForEach(block => { Block pb = parentBlocks.Find(b => b.BlockName == block.BlockName); if (pb != null) { pb.Parent = block.Parent; pb.AddParent(pb.NodeList); pb.NodeList.Clear(); pb.NodeList.AddRange(block.NodeList); } else if (IsExtending(template)) { template.Root.NodeList.Add(block); } }); template.Render(result, RenderParameters.FromContext(context)); }
/// <summary> /// Actually use DotLiquid to render a liquid string into output. /// </summary> /// <param name="source">Liquid source to render.</param> /// <param name="sourceIdentifier">For telemetry purposes, optional string identifying what's being rendered.</param> /// <param name="output">TextWriter to render output to.</param> /// <param name="context">DotLiquid context.</param> private static void InternalRenderLiquid(string source, string sourceIdentifier, TextWriter output, Context context) { Template template; if (!string.IsNullOrEmpty(sourceIdentifier)) { sourceIdentifier = string.Format(" ({0})", sourceIdentifier); } try { using (PerformanceProfiler.Instance.StartMarker(PerformanceMarkerName.LiquidExtension, PerformanceMarkerArea.Liquid, PerformanceMarkerTagName.LiquidSourceParsed)) { template = Template.Parse(source); } } catch (SyntaxException e) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Liquid parse error{0}: {1}", sourceIdentifier, e.ToString())); output.Write(e.Message); return; } ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Rendering Liquid{0}", sourceIdentifier)); using (PerformanceProfiler.Instance.StartMarker(PerformanceMarkerName.LiquidExtension, PerformanceMarkerArea.Liquid, PerformanceMarkerTagName.RenderLiquid)) { template.Render(output, RenderParameters.FromContext(context)); } foreach (var error in template.Errors) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Liquid rendering error{0}: {1}", sourceIdentifier, error.ToString())); } }
public override void Render(Context context, TextWriter result) { Template partial = LoadCachedPartials(_templateName, context); string shortenedTemplateName = _templateName.Substring(1, _templateName.Length - 2); object variable = context[_variableName ?? shortenedTemplateName]; context.Stack(() => { foreach (var keyValue in _attributes) { context[keyValue.Key] = context[keyValue.Value]; } if (variable is IEnumerable && !(variable is string)) { ((IEnumerable)variable).Cast <object>().ToList().ForEach(v => { context[shortenedTemplateName] = v; partial.Render(result, RenderParameters.FromContext(context)); }); return; } context[shortenedTemplateName] = variable; partial.Render(result, RenderParameters.FromContext(context)); }); }
public async override Task RenderAsync(Context context, TextWriter result) { // Get the template or template content and then either copy it (since it will be modified) or parse it IFileSystem fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; Template template = null; if (fileSystem is ITemplateFileSystem templateFileSystem) { template = await templateFileSystem.GetTemplateAsync(context, this.templateName).ConfigureAwait(false); } if (template == null) { string source = await fileSystem.ReadTemplateFileAsync(context, this.templateName).ConfigureAwait(false); template = Template.Parse(source); } List<Block> parentBlocks = this.FindBlocks(template.Root, null); List<Block> orphanedBlocks = ((List<Block>)context.Scopes[0]["extends"]) ?? new List<Block>(); BlockRenderState blockState = BlockRenderState.Find(context) ?? new BlockRenderState(); await context.Stack(() => { context["blockstate"] = blockState; // Set or copy the block state down to this scope context["extends"] = new List<Block>(); // Holds Blocks that were not found in the parent foreach (Block block in this.NodeList.OfType<Block>().Concat(orphanedBlocks)) { Block pb = parentBlocks.Find(b => b.BlockName == block.BlockName); if (pb != null) { if (blockState.Parents.TryGetValue(block, out Block parent)) { blockState.Parents[pb] = parent; } pb.AddParent(blockState.Parents, pb.GetNodeList(blockState)); blockState.NodeLists[pb] = block.GetNodeList(blockState); } else if (this.IsExtending(template)) { ((List<Block>)context.Scopes[0]["extends"]).Add(block); } } return template.RenderAsync(result, RenderParameters.FromContext(context, result.FormatProvider)); }).ConfigureAwait(false); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="result"></param> public override void Render(Context context, TextWriter result) { // Get the template or template content and then either copy it (since it will be modified) or parse it var fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; var templateFileSystem = fileSystem as ITemplateFileSystem; Template template = null; if (templateFileSystem != null) { template = templateFileSystem.GetTemplate(context, _templateName); } if (template == null) { var source = fileSystem.ReadTemplateFile(context, _templateName); template = Template.Parse(source, template.FileSystem); } var parentBlocks = FindBlocks(template.Root, null); var orphanedBlocks = ((List <Block>)context.Scopes.First()["extends"]) ?? new List <Block>(); var blockState = BlockRenderState.Find(context) ?? new BlockRenderState(); context.Stack(() => { context["blockstate"] = blockState; // Set or copy the block state down to this scope context["extends"] = new List <Block>(); // Holds Blocks that were not found in the parent foreach (var block in NodeList.OfType <Block>().Concat(orphanedBlocks)) { var pb = parentBlocks.Find(b => b.BlockName == block.BlockName); if (pb != null) { if (blockState.Parents.TryGetValue(block, out var parent)) { blockState.Parents[pb] = parent; } pb.AddParent(blockState.Parents, pb.GetNodeList(blockState)); blockState.NodeLists[pb] = block.GetNodeList(blockState); } else if (IsExtending(template)) { ((List <Block>)context.Scopes.First()["extends"]).Add(block); } } template.Render(result, RenderParameters.FromContext(context, result.FormatProvider)); }); }
public void TestOperationCancelledError() { var template = Template.Parse(" {% for i in (1..1000000) %} {{ i }} {% endfor %} "); var source = new CancellationTokenSource(100); var context = new Context( environments: new List <Hash>(), outerScope: new Hash(), registers: new Hash(), errorsOutputMode: ErrorsOutputMode.Rethrow, maxIterations: 0, formatProvider: CultureInfo.InvariantCulture, cancellationToken: source.Token); Assert.Throws <System.OperationCanceledException>(() => { template.Render(RenderParameters.FromContext(context, CultureInfo.InvariantCulture)); }); }
public override void Render(Context context, TextWriter result) { IFileSystem fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; object file = fileSystem.ReadTemplateFile(context, _templateName); Template partial = file as Template; partial = partial ?? Template.Parse(file == null ? null : file.ToString()); // support style: include 'path' and include "path" string shortenedTemplateName = null; object variable = null; if (_templateName.Length > 0 && (_templateName[0] == '\'' || _templateName[0] == '"')) { shortenedTemplateName = _templateName.Substring(1, _templateName.Length - 2); variable = context[_variableName ?? shortenedTemplateName]; } context.Stack(() => { foreach (var keyValue in _attributes) { context[keyValue.Key] = context[keyValue.Value]; } if (variable is IEnumerable) { ((IEnumerable)variable).Cast <object>().ToList().ForEach(v => { context[shortenedTemplateName] = v; partial.Render(result, RenderParameters.FromContext(context)); }); return; } if (shortenedTemplateName != null) { context[shortenedTemplateName] = variable; } partial.Render(result, RenderParameters.FromContext(context)); }); }
public async override Task RenderAsync(Context context, TextWriter result) { IFileSystem fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; Template partial = null; if (fileSystem is ITemplateFileSystem templateFileSystem) { partial = await templateFileSystem.GetTemplateAsync(context, this.templateName).ConfigureAwait(false); } if (partial == null) { string source = await fileSystem.ReadTemplateFileAsync(context, this.templateName).ConfigureAwait(false); partial = Template.Parse(source); } string shortenedTemplateName = this.templateName.Substring(1, this.templateName.Length - 2); object variable = context[this.variableName ?? shortenedTemplateName, this.variableName != null]; await context.Stack(async() => { foreach (KeyValuePair <string, string> keyValue in this.attributes) { context[keyValue.Key] = context[keyValue.Value]; } if (variable is IEnumerable) { foreach (object v in ((IEnumerable)variable).Cast <object>().ToList()) { context[shortenedTemplateName] = v; await partial.RenderAsync(result, RenderParameters.FromContext(context, result.FormatProvider)).ConfigureAwait(false); } return; } context[shortenedTemplateName] = variable; await partial.RenderAsync(result, RenderParameters.FromContext(context, result.FormatProvider)).ConfigureAwait(false); }).ConfigureAwait(false); }
public override void Render(Context context, TextWriter result) { // Get the template or template content and then either copy it (since it will be modified) or parse it IFileSystem fileSystem = context.Registers["file_system"] as IFileSystem ?? Template.FileSystem; object file = fileSystem.ReadTemplateFile(context, _templateName); Template template = file as Template; template = template ?? Template.Parse(file == null ? null : file.ToString()); List <Block> parentBlocks = FindBlocks(template.Root, null); List <Block> orphanedBlocks = ((List <Block>)context.Scopes[0]["extends"]) ?? new List <Block>(); BlockRenderState blockState = BlockRenderState.Find(context) ?? new BlockRenderState(); context.Stack(() => { context["blockstate"] = blockState; // Set or copy the block state down to this scope context["extends"] = new List <Block>(); // Holds Blocks that were not found in the parent foreach (Block block in NodeList.OfType <Block>().Concat(orphanedBlocks)) { Block pb = parentBlocks.Find(b => b.BlockName == block.BlockName); if (pb != null) { Block parent; if (blockState.Parents.TryGetValue(block, out parent)) { blockState.Parents[pb] = parent; } pb.AddParent(blockState.Parents, pb.GetNodeList(blockState)); blockState.NodeLists[pb] = block.GetNodeList(blockState); } else if (IsExtending(template)) { ((List <Block>)context.Scopes[0]["extends"]).Add(block); } } template.Render(result, RenderParameters.FromContext(context)); }); }
//Renders the file public override void Render(Context context, TextWriter result) { //Current HTTPContext HttpContext ctx = HttpContext.Current; //Current MD or MDH file (needed for cache management and circular references detection) dynamic parentFile = context[MDFieldsResolver.INTERNAL_REFERENCE_TO_CURRENT_FILE]; //as MIISFile; //Process the current parameter to allow the substitution of possible values, to be able to use them as parameters for this inserFile tag _parentFileRenderParams = RenderParameters.FromContext(context, result.FormatProvider); Template paramsTemplate = Template.Parse(_fileName); _fileName = paramsTemplate.Render(_parentFileRenderParams); string subRenderedContent = ""; MarkdownFile insertedFile = null; //Circular references detector CircularReferencesDetector crd = new CircularReferencesDetector(); //Read and process the inserted file contents if possible //Don't need to check if it's a valid file, because this has already be done in the Initialize method try { string fp2File = ctx.Server.MapPath(_fileName); //Full path to the inserted file //Checks if current file has been referenced before or not object crdObj = context[CRD_CONTEXT_VAR_NAME]; //Try to get a CR Detector from context if (crdObj == null || crdObj.GetType() != typeof(CircularReferencesDetector)) { //If there's no detector (first insertfile) then add one to the context crd.CheckCircularReference(parentFile.FilePath); //Add current initial file as a reference context[CRD_CONTEXT_VAR_NAME] = crd; } else { crd = (CircularReferencesDetector)crdObj; } if (crd.CheckCircularReference(fp2File) == false) { insertedFile = new MarkdownFile(fp2File, false); //Use the raw content of the file. Later we'll further process it //Liquid fields processing must always be done in the raw format to prevent problems with //unexpected HTML inserted by HTML conversion and not present in the original file, when the liquid tags were written subRenderedContent = insertedFile.RawContent; //Add the processed file to the dependencies of the currently processed content file, so that the file is invalidated when the FPF changes (if caching is enabled) parentFile.AddFileDependency(fp2File); } else { throw new Exception(string.Format("Circular reference!!:<br>{0}", crd.GetNestedFilesPath())); } } catch (System.Security.SecurityException) { subRenderedContent = $"Can't access file \"{_fileName}\""; } catch (System.IO.FileNotFoundException) { subRenderedContent = $"File not found: \"{_fileName}\""; } catch (Exception ex) { //This should only happen while testing, never in production, so I send the exception's message subRenderedContent = $"Error loading \"{_fileName}\": {ex.Message}"; } //If the raw contents of the file were read if (insertedFile != null) { Template partial = Template.Parse(subRenderedContent); //Process the file using the appropiate context switch (_renderContextType) { case RENDER_CONTEXT_TYPE_THIS: //Render the raw subfile content *in the same context as the parent file* subRenderedContent = partial.Render(_parentFileRenderParams); break; case RENDER_CONTEXT_TYPE_OWN: //Render the file in its own context subRenderedContent = insertedFile.ProcessedContent; break; case RENDER_CONTEXT_TYPE_NONE: //Use an empty context (placeholders will be deleted) subRenderedContent = partial.Render(new Hash()); break; default: //It's a thrid party file's context //In this case we need to use the MIISFile that represents the third file, as the context MDFieldsResolver renderContext = new MarkdownFile(ctx.Server.MapPath(_renderContextType), false).FieldsResolver; subRenderedContent = partial.Render(renderContext); break; } //Further process the results into HTML if the injected file its a Markdown file if (insertedFile.FileExt == MarkdownFile.MARKDOWN_DEF_EXT) { subRenderedContent = Renderer.ConvertMarkdown2Html(subRenderedContent, insertedFile.UseEmoji, insertedFile.EnabledMDExtensions); } //Sice we're inserting HTML we need to add the delimiters preventing the processing of the HTML //when the final file is transformed into HTML from Markdown subRenderedContent = MDFieldsResolver.HTML_NO_PROCESSING_DELIMITER_BEGIN + subRenderedContent + MDFieldsResolver.HTML_NO_PROCESSING_DELIMITER_END; } result.Write(subRenderedContent); crd.Reset(); }