jehugaleahsa / mustache-sharp Goto Github PK
View Code? Open in Web Editor NEWAn extension of the mustache text template engine for .NET.
License: The Unlicense
An extension of the mustache text template engine for .NET.
License: The Unlicense
Has anyone done a quick tag for fallbacks? Instead of writing
{{#if Name}} {{Name}} {{else}}Fallback{{/if}}
I'd want to write:
{{Name, ifnull=Fallback}}
If anyone has done anything like it I would really appreciate some code for it!
In return here's a URLEncode placeholder: https://gist.github.com/oscaruribe/b82aa3e1e78a62a707d5
Usage {{#urlencode Name}} good for putting in URL when passing data!
I appear to have an odd performance issue on the compile step. I am running a web application on Amazon EC2. The "compile" step is taking huge amounts of time to compute, and is causing the CPU to fire on 100% for several seconds (30sec + in some cases). This is with the simplest of templates.
This is the code that is running:
const string template = "Hello {{name}}, how are you today? Welcome to this App {{name}}";
dynamic obj = new {Name = "Mr Smith",OtherField="Other value with a bit more text"};
using (MiniProfiler.Current.Step("Prepping Template")) {
var compiler = new FormatCompiler();
var keys = new HashSet<string>();
compiler.PlaceholderFound += (o, e) => keys.Add(e.Key);
using (MiniProfiler.Current.Step("Compiling Template")) {
var generator = compiler.Compile(template);
using (MiniProfiler.Current.Step("Template key not found handler")) {
generator.KeyNotFound += (objR, args) => {
args.Substitute = String.Format("[Field \"{0}\" of path \"{1}\" not found!]", args.MissingMember, args.Key);
args.Handled = true;
};
using (MiniProfiler.Current.Step("Fetching Expando Object")) {
using (MiniProfiler.Current.Step("Rendering Template")) {
var result = generator.Render(new CustomFormatProvider(), obj);
}
}
}
}
And below you can see the times for each step output by MiniProfiler:
Is there a way to lowercase a token? I'm looking for something like {{Entity:lowercase}}. If Entity value is 'Ticket', then I want 'ticket'
Would it be possible to implement handler for {{#unless ...}}, which is an inverse of {{#if ...}}?
In certain situations this can save many nested ifs.
Also, I note that the handler bar docs use {{else}} without a hash tag, where as your version uses the hash. Don't have a huge issue with this, just wanted to check it was "By Design"
It would be great if mustache has support of include tag:
{{#include 'path-to-other-mustache-template-file.html'}}
Hi,
When data is DynamicJsonObject it cannot find a way to get values for it.
In my case I have the following structure (simplified):
var data = new {
Issue = this, // this is just a normal class
DataSources = new Dictionary<string, dynamic[]> { }
}
then:
foreach (var dataSource in dataSources) {
var dataSourceData = dataSource.Fetch(); // This returns a dynamic
data.DataSources.Add(dataSource.Name, dataSourceData);
}
This data can be rendered into the template:
{{Title}}
/each
This works if the data in each DataSourche is dynamic or Dictionary. But when dataSource.Fetch() returns an array of DynamicJsonObject it can't find a way to get values. I made this to fake data:
var i1 = new Dictionary<string, object>();
i1.Add("Title", "t1");
var i2 = new Dictionary<string, object>();
i2.Add("Title", "t2");
return new dynamic[] {new DynamicJsonObject(i1), new DynamicJsonObject(i2)};
It seems to me that DynamicJsonObject is not identified as a valid property getter whereas dynamic is but both behave the same way,
We've experienced failures when running the package in a windows service. Works great in console mode but fails in parallel.for.
I ran into an issue where my application had hung due to high CPU usage, and it turns out that the runaway threads were all trying to access the PropertyDictionary.getCacheType.
The lock occurred in the TryGetValue (_cache.TryGetValue in PropertyDictionary.cs - Line 41).
Of course, easiest solution would be to use ConcurrentDictionary, but that is only available in .net 4.0. We could possibly use a lock to make sure only one thread can access this static dictionary at a time.
I'm transforming data:
FormatCompiler compiler = new FormatCompiler();
Generator generator = compiler.Compile(template.TransformationTemplate);
transformedData = generator.Render(gbRequest.Data);
Then I want to parse it using JObject.Parse
JObject Data = JObject.Parse(transformedData);
If a string value in gbRequest.Data contains a double quote, then JObject.Parse raises an exception. I don't think you are escaping double quote correctly.
Is it possible to have the PlaceholderFound event fire for {{#if...}}, {{#with...}} and {{#each...}} as well as normal placeholders? The current PlaceholderFound logic works great, but I can't seem to pick up whether a particular field is in the template if the field is ONLY in the {{#if tag.
Hi,
From Visual Studio 2013, I could not find a signed version of Mustache-sharp using the NugetPackage management.
Does it exist or should I create it myself from the sources? (which I'd rather not do in order to be able to keep the package management aspect of the thing :-))
Thanks in advance for your help
Cheers
Pierre
I've created some initial support for DynamicObject objects. It works for DynamicObject objects that have members, but not indexes (like Array, IList, etc.). For the moment, it depends on Dynamitey.
It's over here in commit 05a7da4 and 90ef52c. I'm probably going to work on it some more before I'll be completely happy with it, but it does work.
This is a feature that is going to be required for a project I'm working on. I would be interested in what sort of inputs you might have regarding this feature as the project maintainer. I would be happy to send you a Pull Request when I wrap up the work on it. And, I'll be sure to include some test cases for DynamicObject objects as well.
Hello,
I've been maintaining a fork providing a portable and .net core support (formerly kre, vnext, dnx, etc...). Now .net core as reached some stability, it might be interesting to reintegrate this into your repo.
Diff
https://github.com/jehugaleahsa/mustache-sharp/compare/master...sandorfr:rc2?diff=unified&name=rc2
If you are interested I'll squash the commits and make a PR.
Thanks for this lib btw.
How about an each with a limit? Anyone done that?
I created a "for" helper in order to be able to generate content using {{#for min max}} ... {{/for}} and use 'this' for index reference. I want to use nested for blocks, but can't reference parent block index neither with {{../this}}, nor {{this.this}}.
Any thoughts on how this might be implemented? There is a handlebars extension library which does this:
https://github.com/danharper/Handlebars-Helpers
It would be great to enable multiple level lists, for example:
{{#each Category}}
<h1>{{Name}} - {{MainCategoryId}}</h1>
{{#each Product}}
{{#is CategoryId MainCategoryId}}
<h4>{{ProductName}}</h4>
{{/is}}
Or for conditional formatting:
{{#each Budget}}
<h3
{{#is amount ">=" 200}}class="overbudget"{{/is}}
>{{Name}}</h3>
It would be great to have a compile option to be able to omit the {{#newline}}
.
I was using this to simply grab the content of a file and render it against a class, and seeing the new line place holder everywhere gets a bit daunting.
http://handlebarsjs.com/ documents the #unless helper (inverse of #if) but mustache-csharp does not appear to support it.
One of the things we used frequently in front-end handlebars.js implementations was the item index over array loops to help with various jquery/css sliders, etc. I don't see direct support for the {{@Index}} var in the current mustache# build. is there a mechanism to reference the loop index in an "each" construct, or are there plans for future support?
I have a JSON element with some recursivity in it :
[
{
"Nom": "Accueil",
"CleMenu": 97038,
"Menus": []
},
{
"Nom": "Conseil",
"CleMenu": 96442,
"Menus": [
{
"Nom": "Gérer au quotidien",
"CleMenu": 96443,
"Menus": []
}
]
}
]
And according to Mustache documentation, using partials like this :
{{<menu}}
<li class="">
<a href="">{{Nom}}</a>
{{if Menu.Menus}}
<ul>
{{>menu}}
</ul>
}}
</li>
{{/menu}}
<ul>
{{#each Menu}}
{{>menu}}
{{/each}}
</ul>
I should be able to iterate over my elements recursively ... but it seems that the element is simply ignored by your library.
Is it supported or not ? (I've not been able to find the partials in your documentation :s).
A feature request we have is to be able to rename a particular field. The business objects that get passed into this library are often renamed, so it would be fantastic if there was a way to rename them on the fly and have Mustache# rename all the occurrences in a template, without removing the "{{" or any of the format strings etc.
var newTemplate = generator.RenameField("Customer.Name","Customer.FirstName");
Another related option would be to check whether a particular template contains a key/field name/path:
if (generator.ContainsKey("Customer.Name")) {
...
}
Hello, thanks for putting this together!
I'm testing this and trying to use it in a project, but I noticed that the variables don't seem to be HTML escaped by default.
Am I missing something or is this not supported?
Please let me know! This is pretty important for us since we need to HTML escape most of our variables to avoid XSS attacks.
http://mustache.github.io/mustache.5.html
Thanks,
Chris
In handlebars.js, else is implemented as "{{else}}" while in mustache-sharp is implemented as "{{#else}}", any workaround of this issue?
Moreover, in the meanwhile, I'm trying to fix this problem by using "#unless" and found that it is not supported, any possible workaround?
Hi Travis!
I need to define a target framework of .NET 3.5, (possibly even lower) for use in a current project. I was able to find and correct (maybe wrongly) two of the three errors I encountered:
The ones I fixed:
The one I can't:
What is the desired effect of the use of Enumerable.Zip in this context, and would it be easy enough to work around it?
Thanks,
-Tony
I would like an option to prevent an exception being thrown when a field is not found, simply replacing it with something like [Field "MyTag" not found!]. This would enable the template engine to carry on, and most of it would be rendered correctly.
Great library by the way, keep it up!
Hi,
I need to pass a set of values to my custom tag , all works fine when those value are aplhanumeric (as passed by '\w' by regex) , but when I pass data other than alphanumeric it throws exception , "Encountered an unknown tag. It was either not registered or exists in a different context."
I am new to this so if you could point me in the right direction it would be greatly appreciated.
I have a json string that I want to parse through mustache-sharp.
I keep getting this error:
Test method Mustache.Test.FormatCompilerTester.TestCompile_Json threw exception:
System.Collections.Generic.KeyNotFoundException: The key Name could not be found.
[TestMethod]
public void TestCompile_Json()
{
FormatCompiler compiler = new FormatCompiler();
const string format = @"Hello, {{Name}}!!!";
Generator generator = compiler.Compile(format);
object json = @"{""Name"": ""Bob""}";
string result = generator.Render(json);
Assert.AreEqual("Hello, Bob!!!", result, "The wrong text was generated.");
}
Thanks
Awesome work. I have a small request:
I've come across multiple scenarios where I need to check the logical NOT condition of a value such as:
if(!condition) {
// do stuff
}
Currently, I use the {{#else}}
block to handle this (with an empty {{#if}}
section), but it would be nice to not have unnecessary empty "if" sections which can clutter the templates.
I couldn't find a way to get a list of tags used in the template.
In my application I would like to check which tags are required and then call appropriate services, gather all the required data and then compile the template.
I think that functionality would be useful. I found that this is possible (although not directly) in Ruby implementation of Mustache: http://stackoverflow.com/questions/10920826/extract-key-names-using-mustache-ruby-api
From experience writing a lot of code-generation sorts of templates (e.g. generating C++ or C# code, not HTML "code"), a useful variation of this feature is to allow a block to have whitespace compressed similar to HTML's rules, allowing markup like:
var {{name}} = {{compress-whitespace}}
{{if is_string}}
"{{value}}"
{{else}}
{{value}}
{{end}}
;{{/compress-whitespace}}
which would produce (for name=foo and is_string=true and value=bar)
var foo = "bar";
The ability to strip out the line of any control tag (if/else/end) that is nothing but whitespace is also useful to avoid a bunch of empty lines showing up in the output.
It's also handy to have a way to output the current input line number and filename so you can insert #line
tags and the like.
Example:
public class BaseClass {
public OtherBaseClass Other { get; set; }
}
public class DerivedClass : BaseClass {
new public OtherDerivedClass Other {
get { return (OtherDerivedClass)base.Other; }
}
}
If you then try to render a template for DerivedClass, PropertyDictionary will throw in line 48 at:
typeCache.Add(propertyInfo.Name, propertyInfo);
because there are 2 properties with the same name.
I suggest the property in the most derived class should take precedence (but just picking one at random, rather than throwing, would be better than nothing).
Occasionally when rendering a relatively simple template I get the following error:
[ArgumentException: An item with the same key has already been added.]
System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +14648955
Mustache.PropertyDictionary.getCacheType(Object instance) +960
Mustache.PropertyDictionary..ctor(Object instance) +41
Mustache.Scope.tryFindFirst(SearchResults results) +74
Mustache.Scope.tryFind(String name) +175
Mustache.KeyGenerator.Mustache.IGenerator.GetText(Scope scope, TextWriter writer, Scope context) +80
Mustache.CompoundGenerator.Mustache.IGenerator.GetText(Scope keyScope, TextWriter writer, Scope contextScope) +477
Mustache.CompoundGenerator.Mustache.IGenerator.GetText(Scope keyScope, TextWriter writer, Scope contextScope) +477
Mustache.Generator.render(IFormatProvider provider, Object source) +769
When you refresh the page it's fine, and Mustache should be given the same data every time.
There could potentially be something weird in the data that it's given since I haven't investigated fully, but just thought I'd see if there's any obvious reason why this might happen?
I've tried looking through the getCacheType()
method myself but I'm not super familiar with the internals of how MustacheSharp works so nothing really stood out at me.
I am getting some null reference exceptions while debugging... they are always happening on startup of a web application. Below is the stack trace... any ideas?
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at Mustache.PropertyDictionary.getCacheType(Object instance)
at Mustache.PropertyDictionary..ctor(Object instance)
at Mustache.Scope.toLookup(Object value)
at Mustache.Scope.tryFindFirst(SearchResults results)
at Mustache.Scope.tryFind(String name)
at Mustache.Scope.Find(String name)
at Mustache.KeyGenerator.Mustache.IGenerator.GetText(Scope scope, TextWriter writer, Scope context)
at Mustache.CompoundGenerator.Mustache.IGenerator.GetText(Scope keyScope, TextWriter writer, Scope contextScope)
at Mustache.Generator.render(IFormatProvider provider, Object source)
at Mustache.Generator.Render(Object source)
Is there a particular reason why mustache-sharp does not allow you to access public member variables as well as properties?
If the value is DBNull a #if treats it as though it has a value, is it me or should DBNull be a falsey value ?
Similar to #8, support looping through an object via the {{@key}}
and {{this}}
placeholders.
Like the SO answer http://stackoverflow.com/questions/9058774/handlebars-mustache-is-there-a-built-in-way-to-loop-through-the-properties-of
Or, a helper that dumps the object (JSON serialized, whatever).
Thanks!
I am trying to render HTML from JSON string by parsing it first using JSON.Net. But following test case is failing with message:
Test method Mustache.Test.FormatCompilerTester.TestCompile_Json threw exception:
System.Collections.Generic.KeyNotFoundException: The key Name could not be found
Test case:
[TestMethod]
public void TestCompile_Json()
{
FormatCompiler compiler = new FormatCompiler();
const string format = @"Hello, {{Name}}!!!";
Generator generator = compiler.Compile(format);
string json = @"{""Name"" : ""Bob""}";
JObject o = JObject.Parse(json);
string result = generator.Render(o);
Assert.AreEqual("Hello, Bob!!!", result, "The wrong text was generated.");
}
Any help would be appreciated.
For me a simple approach would be to remove new lines for lines thats contain only tags when not using {{#NewLine}}
tag
For example, here is a template :
{{#each Items}}
{{#if IsOk}}
That's okay !
{{#else}}
Nope ...
{{/if}}
{{/each}}
Currently, the ouput would be for example
That's okay !
That's okay !
Nope...
It could be great if we could have the lines with only tag ignored
That's okay !
That's okay !
Nope...
I have 18 of the tests that fail and they all have a simular characteristic having to do with whitespaces.
Some tests are adding blank lines when compared to the expected value.
Some tests are removing whitespaces, Expected < > Actual<>
Am I missing something?
I have added a few of test results that are failing.
Test Name: TestCompile_CommentNewLineBlank_PrintsBlank
Result Message: Assert.AreEqual failed. Expected:< >. Actual:<>. The wrong text was generated.
Test Name: TestCompile_CommentNewLineContent_PrintsContent
Result Message: Assert.AreEqual failed. Expected:. Actual:<
After>. The wrong text was generated.
Test Name: TestCompile_CommentNewLineContentNewLineComment_PrintsContent
Result Message: Assert.AreEqual failed. Expected:. Actual:<
First
. The wrong text was generated.
Test Name: TestCompile_MultipleTags
Result Message: Assert.AreEqual failed. Expected:<Hello Bob:
Below are your order details:
Banana: $2.50 x 1
Orange: $0.50 x 5
Apple: $0.25 x 10
Your order total was: $7.50>. Actual:<Hello Bob:
Below are your order details:
Banana: $2.50 x 1
Orange: $0.50 x 5
Apple: $0.25 x 10
Your order total was: $7.50
. The wrong text was generated.
I have the following template:
{{#each Records}} {{/each}}Bug ID: {{ID}} | {{Title}} | {{Component}} | {{OS}} | {{Project}} |
Root Cause/Resolution: {{Resolution}} |
I have this data structure:
{"Records": [{ "Title": "some title", "Component": "some component", "OS": "Some os", "Project": "Some project", "ID": "some id"}, ... more records follow
}]
}
But it's not rendering the Title, Component, OS, Project or Resolution. Essentially all those fields are the bug ID. Somehow the substitutions are all being done inserting the ID in all of the placeholders. Is my syntax wrong or what is going on?
First of all, great work. =) Love what' you've done.
I have a quick question, I've done a proof of concept using your code to generate HTML invoices. I created a Tag to calculate the total amount of the invoice which has to multiply item price x quantity for each row and sum all values. The issue that I'm facing is that I had to hard code the name of the fields that contain the price and quantity in my code, in the current code base would be possible to have something like this: ${{#total Products:[ItemPrice, Quantity]}}? Right now I have: ${{#total Products}} and have on my code the fields that should be used on the calculation. That's only a problem for me because the data comes from a json that is generated based a form builder system and people can name their fields however they want.
Cheers
Luis
Is it possible to get the root object in a custom tag definition?
Here what I'm trying to accomplish
public class JsonPathTagDefinition : InlineTagDefinition
{
public JsonPathTagDefinition() : base("json")
{
}
protected override IEnumerable<TagParameter> GetParameters()
{
return new TagParameter[] { new TagParameter("path") { IsRequired = true }}
}
public override void GetText(System.IO.TextWriter writer, Dictionary<string, object> arguments, Scope context)
{
string path = (string)arguments["path"];
object source = null;
bool found = context.TryFind("this", out source);
var json = JObject.FromObject(source)
String val = json.SelectToken(path).Value<String>();
writer.Write(val);
}
}
Then I want to do this in my template
{{#jsonpath '$..book[2]'}}
Alternatively, I can define another parameter with the source object
{{#jsonpath this '$..book[2]'}}
But I'm trying to avoid it.
Any idea
When I have emojis in parameter string they are escaped. How can I avoid this?
I am reading a template like so:
private string getFileContent( DataDto saveData )
{
string fileContent = string.Empty;
string templateFilePath = string.Format( "{0}\\Template.txt", CONFIGURATION_FOLDER );
using ( StreamReader sr = new StreamReader( templateFilePath ) )
{
string template = sr.ReadToEnd();
FormatCompiler compiler = new FormatCompiler();
Generator generator = compiler.Compile( template );
fileContent = generator.Render( saveData );
}
return fileContent;
}
If the file Template.txt has windows linefeed, then fileContent has none. Changing the linefeeds to unix solves the problem.
What gives?
If you're trying to render a text and the data doesn't include a key it fails, I'd rather it just replaced with blank. Is there any way to do that with a flag?
Has any thought been given to getting in sync with the Handlebars syntax or are you already? Do you have a sample app that executes a big template. I am the author of http://www.my2ndgeneration.com/ which is a cloud based code generator based on HandlebBars. The thing is I want to create a desktop app that will execute the templates as well. I've added some nice syntactical sugar to handlebars too as you can see here http://www.my2ndgeneration.com/TemplateLanguageDoc.aspx
I guess I'm asking if there is any chance mustach-sharp will work for me? I'm willing to help if need be.
In handlebars.js, you can access array elements using the syntax:
{{ item.[12] }}
or
{{ item.[propname] }}
It would be nice if mustache-sharp allowed the same (using the this[] indexer if the item was not an array).
I haven't looked into the source much yet, but it would great if this exception could tell you which tag was unregistered/not supported. Let me know your thoughts, thanks!
I didn't realize that I made the namespace lowercase. This will need to be fixed before release 1.0.0.0. It is purely an aesthetics thing.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.