Lightweight, powerful, flavorful, template engine.
A Lightweight, powerful, flavorful, templating engine for C# and other .net-based languages. Its a fork of Mustachio.
Need general help? open a Discussion
Found a bug? open a Bug
Project Nuget | Github | Status | Description |
---|---|---|---|
Morestachio |
The base Morestachio lib | ||
Morestachio.Linq |
Linq formatter | ||
Morestachio.Runner |
An executable interface for invoking a Morestachio Template | ||
Morestachio.Newtonsoft.Json |
Newtonsoft Json types support | ||
Morestachio.System.Text.Json |
System.Text Json types support | ||
Morestachio.System.Xml.Linq |
XDocument types support | ||
Morestachio.Extensions.Logging |
Microsoft.Extensions.Logging.ILogger support |
Morestachio allows you to create simple text-based templates that are fast and safe to render. It is optimized for WebServers and offers a high degree of customization with its formatter syntax.
Try it out, without consequenses. The Morestachio online editor allows you to create templates within your browser: Editor
// Your template
var sourceTemplate = "Dear {{name}}, this is definitely a personalized note to you. Very truly yours, {{sender}}";
// Parse the template into the document tree.
var document = await ParserOptionsBuilder
.New() //creates a new builder that inherts all default values
.WithTemplate(sourceTemplate) //sets the template for that builder
.BuildAndParseAsync(); //Builds the template and calls ParseAsync() on the returned ParserOptions
// Create the values for the template model:
dynamic model = new ExpandoObject();
model.name = "John";
model.sender = "Sally";
// or with dictionarys
IDictionary model = new Dictionary<string, object>();
model["name"] = "John";
model["sender"] = "Sally";
//or with any other object
var model = new { name= "John", sender= "Sally" };
//create an object based renderer or a compiled renderer
//the renderer is reusable and ThreadSave
var renderer = document.CreateRenderer();
// Render the template with your model and get the result as a string
var content = renderer.RenderAndStringify(model); // Dear John, this is definitely a personalized note to you. Very truly yours, Sally
Morestachio is build upon Mustachio and extends the mustachio syntax in a a lot of points.
{{#import 'secondary_template' }}
{{ this.is.a.valid.path }}
and {{ ../this.goes.up.one.level }}
and {{ ~.this.goes.up.to.Root }}
#each
& #do
& #while
& #repeat
#each data.?
Checkout the Github Wiki for an extensive documentation: https://github.com/JPVenson/morestachio/wiki
Template partials ARE a great feature for large scale template development.
You can create a Partial with the {{#declare NAME}}Partial{{/declare}}
syntax. You can navigate up inside this partials. Partials can also be nested but are currently restricted to a maximum recursion of 255 depth. The programmer has the choice to define a behavior that ether throws an Exception or does nothing and ignores any deeper recusions.
A Partial must be declared before its usage with {{#import 'NAME'}}
but you can use a partial to create hirarical templates.
You can even inject your predefined Partials into all of your Templates by utilizing the PartialsStore
. Use your own IPartialStore
or a build in one with ParserOptionsBuilder.WithDefaultPartialStore(store => {...add partials to store...})
.
Its possible to use plain C# objects they will be called by reflection.
Also you can now set the excact size of the template to limit it (this could be come handy if you are in a hostet environment) use the ParserOptionsBuilder.WithMaxSize()
option to define a max size. It will be enforced on exact that amount of bytes in the stream.
One mayor component is the usage of Variable output strategies in morestachio.
The output handling is done by a IByteCounterStream
that wraps your specific output. This can ether be a Stream
, TextWriter
, StringBuilder
or anything else. For thoese types Morestachio has pre defined Implementations named ByteCounterStream
, ByteCounterTextWriter
and ByteCounterStringBuilder
. All thoese types are enforcing the ParserOptionsBuilder.WithMaxSize()
config if set and will write your template with the set ParserOptionsBuilder.WithEncoding()
With Morestachio you can invoke C# methods from you template, so called 'Formatters'. There are Build in formatters you can call in any template, registered via the DefaultFormatterService.Default
class. When you add a formatter in the default service, it will be availible in every template. You can also add formatters per-template via the ParserOptionsBuilder.WithFormatters
service.
To Invoke a formatter from you template use the Function syntax:
{{Just.One.Formattable.FormatterToCall().Thing}}
This links a c# function named "FormatterToCall".
You can register delegates by using ParserOptionsBuilder.WithFormatter(...)
or you can create a public static class
that has methods attributed with the MorestachioFormatterAttribute
and add them via the ParserOptionsBuilder.WithFormatters<TType>
or you can use an instance method attributed with the MorestachioFormatterAttribute
.
The formatter CAN return a new object on wich you can call new Propertys or it can return a string.
There are formatter prepaired for types implementing the IFormattable
interface. This includes all Primitve types. That means for example that you can call the ToString
formatter on any DateTime
:
{{MyObject.DateTime.ToString("D")}} <-- this will resolve a property "MyObject" and then "DateTime" and will call ToString on it with the argument "D"
Formatter References Can be used to reference another property/key in the template and then use it in a Formatter. Everything that is not a string (ether prefixed and suffixed with " or ') will be threaded as an expression that also can contain formatter calls
{{MyObject.Value.ToString(Key)}}
This will call a formatter that is resposible for the type that Value
has and will give it whats in Key
. Example:
//create the template
var template = "{{Value.ToStringX(Key)}}";
//create the model
var model = new Dictionary<string, object>();
model["Value"] = DateTime.Now;
model["Key"] = "D";
//now add a formatter for our DateTime and add it to the ParserOptions
var document = await ParserOptionsBuilder
.New()
.WithTemplate(template)
// Value | Argument | Return
.WithFormatter(new Func<DateTime, string , string>((value, argument) => {
//value will be the DateTime object and argument will be the value from Key
return value.ToString(argument);
}, "ToStringX")
.BuildAndParseAsync();
document.CreateRenderer().RenderAndStringify(model); // Friday, September 21, 2018 ish