The OpenD Programming Language

WebTemplateRenderer

A class to render web template files into HTML documents.

More...

Constructors

this
this(TemplateLoader loader, EmbeddedTagResult function(string content, string[string] attributes)[string] embeddedTagTranslators)

Members

Functions

addDefaultFunctions
void addDefaultFunctions(var context)

Adds the default functions to the context. You can override this to add additional default functions (or static data) to the context objects.

postProcess
void postProcess(Document document)

The default is currently to do nothing. This function only exists for you to override it.

renderTemplate
Document renderTemplate(string templateName, var context, var skeletonContext, string skeletonName)

Structs

EmbeddedTagResult
struct EmbeddedTagResult

Detailed Description

You can customize various parts of this with subclassing and dependency injection. Customization hook points include:

  1. You pass a TemplateLoader instance to the constructor. This object is responsible for loading a particular named template and returning a string of its html text. If you don't pass one, the default behavior is to load a particular file out of the templates directory.
  2. The next step is transforming the string the TemplateLoader returned into a document object model. This is done by a private function at this time. If you want to use a different format than HTML, you should either embed the other language in your template (you can pass a translator to the constructor, details to follow later in this document)
  3. Next, the contexts must be prepared. It will call addDefaultFunctions on each one to prepare them. You can override that to provide more or fewer functions.
  4. Now, it is time to expand the template. This is done by a private function, so you cannot replace this step, but you can customize it in some ways by passing functions to the constructor's embeddedTagTranslators argument.
  5. At this point, it combines the expanded template with the skeleton to form the complete, expanded document.
  6. Finally, it will call your custom post-processing function right before returning the document. You can override the postProcess method to add custom behavior to this step.

Custom Special Tags

You can define translator for special tags, such as to embed a block of custom markup inside your template.

Let's suppose we want to add a <plaintext>...</plaintext> tag that does not need HTML entity encoding.

<main>
	I can use <b>HTML</b> &amp; need to respect entity encoding here.

	<plaintext>
		But here, I can write & as plain text and <b>html</b> will not work.
	</plaintext>
</main>

We can make that possible by defining a custom special tag when constructing the WebTemplateRenderer, like this:

auto renderer = new WebTemplateRenderer(null /* no special loader needed */, [
	// this argument is the special tag name and a function to work with it
	// listed as associative arrays.
	"plaintext": function(string content, string[string] attributes) {
		import arsd.dom;
		return WebTemplateRenderer.EmbeddedTagResult(new TextNode(content));
	}
]);

The associative array keys are the special tag name. For each one, this instructs the HTML parser to treat them similarly to <script> - it will read until the closing tag, making no attempt to parse anything else inside it. It just scoops of the content, then calls your function to decide what to do with it.

Your function is given an associative array of attributes on the special tag and its inner content, as raw source, from the file. You must construct an appropriate DOM element from the content (including possibly a DocumentFragment object if you need multiple tags inside) and return it, along with, optionally, an enumerated value telling the renderer if it should try to expand template text inside this new element. If you don't provide a value, it will try to automatically guess what it should do based on the returned element type. (That is, if you return a text node, it will try to do a string-based replacement, and if you return another node, it will descend into it the same as any other node written in the document looking for AspCode elements.)

The example given here returns a TextNode, so we let it do the default string-based template content processing. But if we returned WebTemplateRenderer.EmbeddedTagResult(new TextNode(content), false);, it would not support embedded templates and any <% .. %> stuff would be left as-is.

You can trim some of that namespace spam if you make a subclass and pass it to super inside your constructor.

Meta

History

Added February 5, 2024 (dub v11.5)