This is the Accord Project template engine. Rich-text templates are defined in TemplateMark (either as markdown files, or JSON documents) and are then merged with JSON data to produce output documents. Templates may contain TypeScript expressions.
The core template engine is a JSON to JSON transformation that converts TemplateMark JSON + agreement data (JSON) to AgreementMark JSON.
Note: Use the
@accordproject/markdown-transform
project to convert markdown templates to TemplateMark JSON and to convert AgreementMark JSON to output formats (HTML, PDF, DOCX etc.). For command-line usage please use@accordproject/template-cli
.
TemplateMark is a document object model that describes a rich-text template, with embedded variables, conditional sections, formulae etc. TemplateMark uses embedded TypeScript expressions for conditionals and calculations.
The format of both TemplateMark and AgreementMark is specified using the Concerto data modeling language.
At a high-level the template engine converts a TemplateMark DOM to an AgreementMark DOM, evaluating TypeScript expressions for conditional sections and formulae, and replaces variable references with variable values from the supplied agreement data.
Let's create the simplest template imaginable, the infamous "hello world"!
The code for this test is available at: https://github.com/accordproject/template-engine/blob/main/test/HelloWorld.test.ts
First create a template data model in Concerto syntax. The data model defines the structure of the data to be merged with the template. In this case the template model contains a single property message
of type String
. The property is required (it is not optional
).
namespace helloworld@1.0.0
@template
concept TemplateData {
o String message
}
Next define the TemplateMark for the template. In this case it is the plain-text world "Hello"
followed by a space, then the variable message
followed by "."
.
Hello {{message}}.
Note that in this case the template is defined using an extended markdown syntax (rich-text with embedded variables etc.). The
@accordproject/markdown-transform
packages are used to convert the markdown to TemplateMark JSON, for use by the template engine.
Define an instance of the helloworld@1.0.0.TemplateData
data model. In this case setting the value of the message
property to the string "World".
const data = {
$class: 'helloworld@1.0.0.TemplateData',
message: 'World',
};
When the TemplateMark and the data JSON is passed to the Template Engine it merges the two, in this case by simply replacing the reference to the message
variable with its value from the data JSON and to produce an AgreementMark JSON document.
This AgreementMark JSON document can then be passed to the @accordproject/markdown-transform
modules for conversion to markdown, PDF, HTML.
{
"$class": "org.accordproject.commonmark@0.5.0.Document",
"xmlns": "http://commonmark.org/xml/1.0",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Hello "
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"value": "World",
"name": "message",
"elementType": "String"
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "."
}
]
}
]
}
]
}
The Hello World example just scratches the surface of what can be accomplished! TemplateMark can define optional sections, conditional sections, TypeScript formulae/calculations and even reference external data.
Refer to the full example for details.
More detailed syntax documentation is to come! Read the existing documentation at: https://docs.accordproject.org/docs/markup-templatemark.html
There are many great Open Source template engines available, such as Mustache, Handlebars or EJS, so why create yet another?
Most template engines are fundamentally text based — i.e. they treat templates as text strings and are glorified "find and replace" machines. This approach creates a coupling between the input format of the template, say, a DOCX file, and the output of the template engine, which in the case of a DOCX template, has to be a DOCX file. This makes supporting multiple input and output formats difficult.
The Accord Project template engine breaks the coupling between the template input format and the engine output format, and moves data format conversion outside of the core template engine. Templates at the engine level are TemplateMark JSON documents and the output from the template engine is an AgreementMark JSON document. Separate libraries are used to convert source templates into TemplateMark JSON, or to render AgreementMark JSON to an output format.
This flexibility allows a markdown template to be created that is used to create HTML, PDF or DOCX. One can even imagine using DOCX templates to create HTML or PDF files, or other scenarios.
TemplateMark JSON is a well-defined file format, meaning that powerful template editors can be created to define it: including widgets and user-experience for defining conditional sections, and formulae, and offering template preview and integrated testing. Template editing is closer to programming in our opinion than word-processing.
We encourage community and commercial innovation in this area!
Unlike some templating systems which prohibit, or minmize, logic in templates, Accord Project templates fully embrace templates that may contain sophisticated logic: conditional logic to determine what text to include, or even calculations, for example to calculate the monthly payments for a mortgage based on the term of the mortgage, the amount and the interest rate.
Given the ability for templates to contain logic there's an imperative to ensure that the templates are safe - i.e. when a template is merged with well-structured data it is guaranteed to produce well-structured output.
Too many templating engines fail in unpredictable ways at runtime, or silently generate invalid output, when presented with data — unacceptable for enterprise usage.
Accord Project templates are therefore strongly-typed. The logic in templates is expressed in TypeScript. TypeScript is a strongly-typed, general purpose programming language, supported by a vibrant Open Source and enterprise community. TypeScript compiles to JavaScript for easy execution on most platforms.
The rich-text with variables of a template is associated with a Concerto data model. The Concerto data model defines the structure of the data required for the template, and is used to statically compile the template and verify type-safety, and is also used at runtime to ensure that incoming data is well structured.
Templates may be statically compiled to TypeScript programs, enforcing type-safety, ensuring that no unsafe code evaluation ("eval") is required at runtime, and easing integration into applications.
The template compiler is a separate project, hosted here: https://github.com/accordproject/template-compiler
Note that this module is primarily intended for tool authors, or developers embedding template engines within applications. For command-line usage please refer to the @accordproject/template-cli
package which implements a full pipeline to convert markdown templates plus JSON data to supported output formats, such as HTML, DOCX or PDF.
npm install @accordproject/template-engine --save
Accord Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the LICENSE file. Accord Project documentation files are made available under the Creative Commons Attribution 4.0 International License (CC-BY-4.0), available at http://creativecommons.org/licenses/by/4.0/.