Force newlines to be explicit
Since there weren't consistent rules for when to include newlines, I decided to make an explicit tag (similar to HTML's <br /> tag). This can have a dramatic impact on your existing code (unless it is just HTML).
This commit is contained in:
parent
65b79062d6
commit
e2fd882ef1
|
@ -60,11 +60,14 @@ namespace Mustache.Test
|
||||||
public void TestCompile_OutputNewLineBlank_PrintsBothLines()
|
public void TestCompile_OutputNewLineBlank_PrintsBothLines()
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
const string format = @"Hello
|
const string format = @"Hello{{#newline}}
|
||||||
|
";
|
||||||
|
|
||||||
|
const string expected = @"Hello
|
||||||
";
|
";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(null);
|
string result = generator.Render(null);
|
||||||
Assert.AreEqual(format, result, "The wrong text was generated.");
|
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -268,7 +271,7 @@ namespace Mustache.Test
|
||||||
public void TestCompile_OutputNewLineOutput_PrintsBothLines()
|
public void TestCompile_OutputNewLineOutput_PrintsBothLines()
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
const string format = @"{{this}}
|
const string format = @"{{this}}{{#newline}}
|
||||||
After";
|
After";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render("Content");
|
string result = generator.Render("Content");
|
||||||
|
@ -285,7 +288,7 @@ After";
|
||||||
public void TestCompile_EmptyNewLineKey_PrintsBothLines()
|
public void TestCompile_EmptyNewLineKey_PrintsBothLines()
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
const string format = @"
|
const string format = @"{{#newline}}
|
||||||
{{this}}";
|
{{this}}";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render("Content");
|
string result = generator.Render("Content");
|
||||||
|
@ -318,7 +321,7 @@ Content";
|
||||||
public void TestCompile_KeyKey_PrintsBothLines()
|
public void TestCompile_KeyKey_PrintsBothLines()
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
const string format = @"{{this}}
|
const string format = @"{{this}}{{#newline}}
|
||||||
{{this}}";
|
{{this}}";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render("Content");
|
string result = generator.Render("Content");
|
||||||
|
@ -432,7 +435,7 @@ Content";
|
||||||
const string format = "{{#! comment }} {{#! comment }}";
|
const string format = "{{#! comment }} {{#! comment }}";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(new object());
|
string result = generator.Render(new object());
|
||||||
Assert.AreEqual(String.Empty, result, "The wrong text was generated.");
|
Assert.AreEqual(" ", result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -465,12 +468,12 @@ Content";
|
||||||
/// If a comment makes up the entire format string, the nothing should be printed out.
|
/// If a comment makes up the entire format string, the nothing should be printed out.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestCompile_CommentAloneOnlyLine__PrintsEmpty()
|
public void TestCompile_CommentAloneOnlyLine_PrintsSurroundingSpace()
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
Generator generator = compiler.Compile(" {{#! comment }} ");
|
Generator generator = compiler.Compile(" {{#! comment }} ");
|
||||||
string result = generator.Render(null);
|
string result = generator.Render(null);
|
||||||
Assert.AreEqual(String.Empty, result, "The wrong text was generated.");
|
Assert.AreEqual(" ", result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -486,8 +489,7 @@ Content";
|
||||||
After";
|
After";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(new object());
|
string result = generator.Render(new object());
|
||||||
const string expected = @"Before
|
const string expected = @"Before After";
|
||||||
After";
|
|
||||||
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,8 +506,7 @@ After";
|
||||||
After";
|
After";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(new object());
|
string result = generator.Render(new object());
|
||||||
const string expected = @"Before
|
const string expected = @"Before After";
|
||||||
After";
|
|
||||||
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,14 +521,13 @@ After";
|
||||||
const string format = @"Before
|
const string format = @"Before
|
||||||
{{#! This is a comment }}
|
{{#! This is a comment }}
|
||||||
{{#! This is another comment }}
|
{{#! This is another comment }}
|
||||||
|
{{#newline}}
|
||||||
{{#! This is the final comment }}
|
{{#! This is the final comment }}
|
||||||
After";
|
After";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(new object());
|
string result = generator.Render(new object());
|
||||||
const string expected = @"Before
|
const string expected = @"Before
|
||||||
|
After";
|
||||||
After";
|
|
||||||
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,9 +543,7 @@ After";
|
||||||
After";
|
After";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(new object());
|
string result = generator.Render(new object());
|
||||||
const string expected = @"Before
|
const string expected = @"Before ExtraAfter";
|
||||||
Extra
|
|
||||||
After";
|
|
||||||
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
Assert.AreEqual(expected, result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,7 +574,7 @@ After";
|
||||||
After";
|
After";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
string result = generator.Render(null);
|
string result = generator.Render(null);
|
||||||
Assert.AreEqual("After", result, "The wrong text was generated.");
|
Assert.AreEqual(" After", result, "The wrong text was generated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -618,8 +616,8 @@ First
|
||||||
public void TestCompile_ContentNewLineCommentNewLineContentNewLineComment_PrintsContent()
|
public void TestCompile_ContentNewLineCommentNewLineContentNewLineComment_PrintsContent()
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
const string format = @"First
|
const string format = @"First{{#newline}}
|
||||||
{{#! comment }}
|
{{#! comment }}
|
||||||
Middle
|
Middle
|
||||||
{{#! comment }}";
|
{{#! comment }}";
|
||||||
Generator generator = compiler.Compile(format);
|
Generator generator = compiler.Compile(format);
|
||||||
|
@ -795,6 +793,7 @@ Content{{/if}}";
|
||||||
const string format = @"{{#if this}}
|
const string format = @"{{#if this}}
|
||||||
First
|
First
|
||||||
{{/if}}{{#if this}}
|
{{/if}}{{#if this}}
|
||||||
|
{{#newline}}
|
||||||
Last
|
Last
|
||||||
{{/if}}";
|
{{/if}}";
|
||||||
Generator generator = parser.Compile(format);
|
Generator generator = parser.Compile(format);
|
||||||
|
@ -832,6 +831,7 @@ Content
|
||||||
const string format = @"{{#if this}}
|
const string format = @"{{#if this}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
First
|
First
|
||||||
|
{{#newline}}
|
||||||
{{#if this}}
|
{{#if this}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
Last";
|
Last";
|
||||||
|
@ -1005,10 +1005,11 @@ Last";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// A bug was found where the index tag was trying to read the arguments for the next tag.
|
||||||
|
/// This was caused by the index tag chewing up more of the input than it was supposed to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestCompile_Each_LoopOverCollectionTwice()
|
public void TestCompile_Each_ContextAfterIndexTag()
|
||||||
{
|
{
|
||||||
List<TestObject> objects = new List<TestObject>();
|
List<TestObject> objects = new List<TestObject>();
|
||||||
objects.Add(new TestObject { Name = "name1", Val = "val1" });
|
objects.Add(new TestObject { Name = "name1", Val = "val1" });
|
||||||
|
@ -1016,11 +1017,10 @@ Last";
|
||||||
objects.Add(new TestObject { Name = "name3", Val = "val3" });
|
objects.Add(new TestObject { Name = "name3", Val = "val3" });
|
||||||
|
|
||||||
const string template = @"{{#each this}}
|
const string template = @"{{#each this}}
|
||||||
Item Number: {{#index}}<br />
|
Item Number: {{#index}}<br />{{#newline}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#each this}}
|
{{#each this}}
|
||||||
Item Number: foo<br />
|
Item Number: foo<br />{{#newline}}
|
||||||
|
|
||||||
{{/each}}";
|
{{/each}}";
|
||||||
|
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
|
@ -1111,15 +1111,17 @@ Item Number: foo<br />
|
||||||
{
|
{
|
||||||
FormatCompiler compiler = new FormatCompiler();
|
FormatCompiler compiler = new FormatCompiler();
|
||||||
const string format = @"Hello {{Customer.FirstName}}:
|
const string format = @"Hello {{Customer.FirstName}}:
|
||||||
|
{{#newline}}
|
||||||
|
{{#newline}}
|
||||||
{{#with Order}}
|
{{#with Order}}
|
||||||
{{#if LineItems}}
|
{{#if LineItems}}
|
||||||
Below are your order details:
|
Below are your order details:
|
||||||
|
{{#newline}}
|
||||||
|
{{#newline}}
|
||||||
{{#each LineItems}}
|
{{#each LineItems}}
|
||||||
{{Name}}: {{UnitPrice:C}} x {{Quantity}}
|
{{Name}}: {{UnitPrice:C}} x {{Quantity}}{{#newline}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
{{#newline}}
|
||||||
Your order total was: {{Total:C}}
|
Your order total was: {{Total:C}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/with}}";
|
{{/with}}";
|
||||||
|
|
|
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
[assembly: AssemblyVersion("0.1.3.0")]
|
[assembly: AssemblyVersion("0.2.0.0")]
|
||||||
[assembly: AssemblyFileVersion("0.1.3.0")]
|
[assembly: AssemblyFileVersion("0.2.0.0")]
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Mustache
|
||||||
{
|
{
|
||||||
private readonly TagDefinition _definition;
|
private readonly TagDefinition _definition;
|
||||||
private readonly ArgumentCollection _arguments;
|
private readonly ArgumentCollection _arguments;
|
||||||
private readonly LinkedList<IGenerator> _primaryGenerators;
|
private readonly List<IGenerator> _primaryGenerators;
|
||||||
private IGenerator _subGenerator;
|
private IGenerator _subGenerator;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -23,7 +23,7 @@ namespace Mustache
|
||||||
{
|
{
|
||||||
_definition = definition;
|
_definition = definition;
|
||||||
_arguments = arguments;
|
_arguments = arguments;
|
||||||
_primaryGenerators = new LinkedList<IGenerator>();
|
_primaryGenerators = new List<IGenerator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -47,19 +47,6 @@ namespace Mustache
|
||||||
addGenerator(generator, isSubGenerator);
|
addGenerator(generator, isSubGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a StaticGenerator from the given value and adds it.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="generators">The static generators to add.</param>
|
|
||||||
public void AddStaticGenerators(IEnumerable<StaticGenerator> generators)
|
|
||||||
{
|
|
||||||
foreach (StaticGenerator generator in generators)
|
|
||||||
{
|
|
||||||
LinkedListNode<IGenerator> node = _primaryGenerators.AddLast(generator);
|
|
||||||
generator.Node = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addGenerator(IGenerator generator, bool isSubGenerator)
|
private void addGenerator(IGenerator generator, bool isSubGenerator)
|
||||||
{
|
{
|
||||||
if (isSubGenerator)
|
if (isSubGenerator)
|
||||||
|
@ -68,7 +55,7 @@ namespace Mustache
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_primaryGenerators.AddLast(generator);
|
_primaryGenerators.Add(generator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,17 +63,17 @@ namespace Mustache
|
||||||
{
|
{
|
||||||
Dictionary<string, object> arguments = _arguments.GetArguments(scope);
|
Dictionary<string, object> arguments = _arguments.GetArguments(scope);
|
||||||
IEnumerable<NestedContext> contexts = _definition.GetChildContext(writer, scope, arguments);
|
IEnumerable<NestedContext> contexts = _definition.GetChildContext(writer, scope, arguments);
|
||||||
LinkedList<IGenerator> generators;
|
List<IGenerator> generators;
|
||||||
if (_definition.ShouldGeneratePrimaryGroup(arguments))
|
if (_definition.ShouldGeneratePrimaryGroup(arguments))
|
||||||
{
|
{
|
||||||
generators = _primaryGenerators;
|
generators = _primaryGenerators;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
generators = new LinkedList<IGenerator>();
|
generators = new List<IGenerator>();
|
||||||
if (_subGenerator != null)
|
if (_subGenerator != null)
|
||||||
{
|
{
|
||||||
generators.AddLast(_subGenerator);
|
generators.Add(_subGenerator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (NestedContext context in contexts)
|
foreach (NestedContext context in contexts)
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace Mustache
|
||||||
_tagLookup.Add(indexDefinition.Name, indexDefinition);
|
_tagLookup.Add(indexDefinition.Name, indexDefinition);
|
||||||
WithTagDefinition withDefinition = new WithTagDefinition();
|
WithTagDefinition withDefinition = new WithTagDefinition();
|
||||||
_tagLookup.Add(withDefinition.Name, withDefinition);
|
_tagLookup.Add(withDefinition.Name, withDefinition);
|
||||||
|
NewlineTagDefinition newlineDefinition = new NewlineTagDefinition();
|
||||||
|
_tagLookup.Add(newlineDefinition.Name, newlineDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -75,12 +77,10 @@ namespace Mustache
|
||||||
throw new ArgumentNullException("format");
|
throw new ArgumentNullException("format");
|
||||||
}
|
}
|
||||||
CompoundGenerator generator = new CompoundGenerator(_masterDefinition, new ArgumentCollection());
|
CompoundGenerator generator = new CompoundGenerator(_masterDefinition, new ArgumentCollection());
|
||||||
Trimmer trimmer = new Trimmer();
|
|
||||||
List<Context> context = new List<Context>() { new Context(_masterDefinition.Name, new ContextParameter[0]) };
|
List<Context> context = new List<Context>() { new Context(_masterDefinition.Name, new ContextParameter[0]) };
|
||||||
int formatIndex = buildCompoundGenerator(_masterDefinition, context, generator, trimmer, format, 0);
|
int formatIndex = buildCompoundGenerator(_masterDefinition, context, generator, format, 0);
|
||||||
string trailing = format.Substring(formatIndex);
|
string trailing = format.Substring(formatIndex);
|
||||||
generator.AddStaticGenerators(trimmer.RecordText(trailing, false, false));
|
generator.AddGenerator(new StaticGenerator(trailing));
|
||||||
trimmer.Trim();
|
|
||||||
return new Generator(generator);
|
return new Generator(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,6 @@ namespace Mustache
|
||||||
TagDefinition tagDefinition,
|
TagDefinition tagDefinition,
|
||||||
List<Context> context,
|
List<Context> context,
|
||||||
CompoundGenerator generator,
|
CompoundGenerator generator,
|
||||||
Trimmer trimmer,
|
|
||||||
string format, int formatIndex)
|
string format, int formatIndex)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -192,7 +191,7 @@ namespace Mustache
|
||||||
|
|
||||||
if (match.Groups["key"].Success)
|
if (match.Groups["key"].Success)
|
||||||
{
|
{
|
||||||
generator.AddStaticGenerators(trimmer.RecordText(leading, true, true));
|
generator.AddGenerator(new StaticGenerator(leading));
|
||||||
formatIndex = match.Index + match.Length;
|
formatIndex = match.Index + match.Length;
|
||||||
string key = match.Groups["key"].Value;
|
string key = match.Groups["key"].Value;
|
||||||
string alignment = match.Groups["alignment"].Value;
|
string alignment = match.Groups["alignment"].Value;
|
||||||
|
@ -217,7 +216,7 @@ namespace Mustache
|
||||||
}
|
}
|
||||||
if (nextDefinition.HasContent)
|
if (nextDefinition.HasContent)
|
||||||
{
|
{
|
||||||
generator.AddStaticGenerators(trimmer.RecordText(leading, true, false));
|
generator.AddGenerator(new StaticGenerator(leading));
|
||||||
ArgumentCollection arguments = getArguments(nextDefinition, match);
|
ArgumentCollection arguments = getArguments(nextDefinition, match);
|
||||||
CompoundGenerator compoundGenerator = new CompoundGenerator(nextDefinition, arguments);
|
CompoundGenerator compoundGenerator = new CompoundGenerator(nextDefinition, arguments);
|
||||||
IEnumerable<TagParameter> contextParameters = nextDefinition.GetChildContextParameters();
|
IEnumerable<TagParameter> contextParameters = nextDefinition.GetChildContextParameters();
|
||||||
|
@ -227,7 +226,7 @@ namespace Mustache
|
||||||
ContextParameter[] parameters = contextParameters.Select(p => new ContextParameter(p.Name, arguments.GetKey(p))).ToArray();
|
ContextParameter[] parameters = contextParameters.Select(p => new ContextParameter(p.Name, arguments.GetKey(p))).ToArray();
|
||||||
context.Add(new Context(nextDefinition.Name, parameters));
|
context.Add(new Context(nextDefinition.Name, parameters));
|
||||||
}
|
}
|
||||||
formatIndex = buildCompoundGenerator(nextDefinition, context, compoundGenerator, trimmer, format, formatIndex);
|
formatIndex = buildCompoundGenerator(nextDefinition, context, compoundGenerator, format, formatIndex);
|
||||||
generator.AddGenerator(nextDefinition, compoundGenerator);
|
generator.AddGenerator(nextDefinition, compoundGenerator);
|
||||||
if (hasContext)
|
if (hasContext)
|
||||||
{
|
{
|
||||||
|
@ -236,7 +235,7 @@ namespace Mustache
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
generator.AddStaticGenerators(trimmer.RecordText(leading, true, true));
|
generator.AddGenerator(new StaticGenerator(leading));
|
||||||
ArgumentCollection arguments = getArguments(nextDefinition, match);
|
ArgumentCollection arguments = getArguments(nextDefinition, match);
|
||||||
InlineGenerator inlineGenerator = new InlineGenerator(nextDefinition, arguments);
|
InlineGenerator inlineGenerator = new InlineGenerator(nextDefinition, arguments);
|
||||||
generator.AddGenerator(inlineGenerator);
|
generator.AddGenerator(inlineGenerator);
|
||||||
|
@ -244,7 +243,7 @@ namespace Mustache
|
||||||
}
|
}
|
||||||
else if (match.Groups["close"].Success)
|
else if (match.Groups["close"].Success)
|
||||||
{
|
{
|
||||||
generator.AddStaticGenerators(trimmer.RecordText(leading, true, false));
|
generator.AddGenerator(new StaticGenerator(leading));
|
||||||
string tagName = match.Groups["name"].Value;
|
string tagName = match.Groups["name"].Value;
|
||||||
TagDefinition nextDefinition = _tagLookup[tagName];
|
TagDefinition nextDefinition = _tagLookup[tagName];
|
||||||
formatIndex = match.Index;
|
formatIndex = match.Index;
|
||||||
|
@ -256,7 +255,7 @@ namespace Mustache
|
||||||
}
|
}
|
||||||
else if (match.Groups["comment"].Success)
|
else if (match.Groups["comment"].Success)
|
||||||
{
|
{
|
||||||
generator.AddStaticGenerators(trimmer.RecordText(leading, true, false));
|
generator.AddGenerator(new StaticGenerator(leading));
|
||||||
formatIndex = match.Index + match.Length;
|
formatIndex = match.Index + match.Length;
|
||||||
}
|
}
|
||||||
else if (match.Groups["unknown"].Success)
|
else if (match.Groups["unknown"].Success)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Mustache
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a tag that outputs a newline.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class NewlineTagDefinition : InlineTagDefinition
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of an NewlineTagDefinition.
|
||||||
|
/// </summary>
|
||||||
|
public NewlineTagDefinition()
|
||||||
|
: base("newline")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text to output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The writer to write the output to.</param>
|
||||||
|
/// <param name="arguments">The arguments passed to the tag.</param>
|
||||||
|
/// <param name="contextData">Extra data passed along with the context.</param>
|
||||||
|
public override void GetText(TextWriter writer, Dictionary<string, object> arguments, object contextData)
|
||||||
|
{
|
||||||
|
writer.Write(Environment.NewLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,6 @@ using System.Runtime.CompilerServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.1.3.0")]
|
[assembly: AssemblyVersion("0.2.0.0")]
|
||||||
[assembly: AssemblyFileVersion("0.1.3.0")]
|
[assembly: AssemblyFileVersion("0.2.0.0")]
|
||||||
[assembly: InternalsVisibleTo("mustache-sharp.test")]
|
[assembly: InternalsVisibleTo("mustache-sharp.test")]
|
|
@ -9,20 +9,14 @@ namespace Mustache
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class StaticGenerator : IGenerator
|
internal sealed class StaticGenerator : IGenerator
|
||||||
{
|
{
|
||||||
|
private readonly string value;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of a StaticGenerator.
|
/// Initializes a new instance of a StaticGenerator.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StaticGenerator()
|
public StaticGenerator(string value)
|
||||||
{
|
{
|
||||||
}
|
this.value = value.Replace(Environment.NewLine, String.Empty);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the linked list node containing the current generator.
|
|
||||||
/// </summary>
|
|
||||||
public LinkedListNode<IGenerator> Node
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -30,20 +24,7 @@ namespace Mustache
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Value
|
public string Value
|
||||||
{
|
{
|
||||||
get;
|
get { return value; }
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the static text from the final output.
|
|
||||||
/// </summary>
|
|
||||||
public void Prune()
|
|
||||||
{
|
|
||||||
if (Node != null)
|
|
||||||
{
|
|
||||||
Node.List.Remove(Node);
|
|
||||||
Node = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
|
void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Mustache
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Removes unnecessary lines from the final output.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class Trimmer
|
|
||||||
{
|
|
||||||
private readonly LinkedList<LineDetails> _lines;
|
|
||||||
private LinkedListNode<LineDetails> _currentLine;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of a Trimmer.
|
|
||||||
/// </summary>
|
|
||||||
public Trimmer()
|
|
||||||
{
|
|
||||||
_lines = new LinkedList<LineDetails>();
|
|
||||||
_currentLine = _lines.AddLast(new LineDetails());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the state of the trimmer, indicating that the given text was encountered before an inline tag.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The text at the end of the format string.</param>
|
|
||||||
/// <param name="generator">The generator created for the inline tag.</param>
|
|
||||||
/// <returns>A static generator containing the passed text.</returns>
|
|
||||||
public IEnumerable<StaticGenerator> RecordText(string value, bool isTag, bool isOutput)
|
|
||||||
{
|
|
||||||
int newLineIndex = value.IndexOf(Environment.NewLine);
|
|
||||||
if (newLineIndex == -1)
|
|
||||||
{
|
|
||||||
StaticGenerator generator = new StaticGenerator() { Value = value };
|
|
||||||
_currentLine.Value.Generators.Add(generator);
|
|
||||||
_currentLine.Value.HasTag |= isTag;
|
|
||||||
_currentLine.Value.HasOutput |= !String.IsNullOrWhiteSpace(value);
|
|
||||||
yield return generator;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string[] lines = value.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
|
||||||
|
|
||||||
// get the trailing generator
|
|
||||||
string trailing = lines[0];
|
|
||||||
StaticGenerator trailingGenerator = new StaticGenerator() { Value = trailing };
|
|
||||||
_currentLine.Value.Generators.Add(trailingGenerator);
|
|
||||||
_currentLine.Value.HasOutput |= !String.IsNullOrWhiteSpace(trailing);
|
|
||||||
yield return trailingGenerator;
|
|
||||||
|
|
||||||
// get the middle generators
|
|
||||||
for (int lineIndex = 1; lineIndex < lines.Length - 1; ++lineIndex)
|
|
||||||
{
|
|
||||||
string middle = lines[lineIndex];
|
|
||||||
StaticGenerator middleGenerator = new StaticGenerator() { Value = middle };
|
|
||||||
LineDetails middleDetails = new LineDetails() { HasTag = false };
|
|
||||||
_currentLine = _lines.AddLast(middleDetails);
|
|
||||||
_currentLine.Value.Generators.Add(middleGenerator);
|
|
||||||
_currentLine.Value.HasOutput = true;
|
|
||||||
yield return middleGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the leading generator
|
|
||||||
string leading = lines[lines.Length - 1];
|
|
||||||
StaticGenerator leadingGenerator = new StaticGenerator() { Value = leading };
|
|
||||||
LineDetails details = new LineDetails() { HasTag = isTag };
|
|
||||||
_currentLine = _lines.AddLast(details);
|
|
||||||
_currentLine.Value.Generators.Add(leadingGenerator);
|
|
||||||
_currentLine.Value.HasOutput = !String.IsNullOrWhiteSpace(leading);
|
|
||||||
yield return leadingGenerator;
|
|
||||||
}
|
|
||||||
if (isOutput)
|
|
||||||
{
|
|
||||||
_currentLine.Value.HasOutput = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Trim()
|
|
||||||
{
|
|
||||||
removeBlankLines();
|
|
||||||
separateLines();
|
|
||||||
removeEmptyGenerators();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeBlankLines()
|
|
||||||
{
|
|
||||||
LinkedListNode<LineDetails> current = _lines.First;
|
|
||||||
while (current != null)
|
|
||||||
{
|
|
||||||
LineDetails details = current.Value;
|
|
||||||
LinkedListNode<LineDetails> temp = current;
|
|
||||||
current = current.Next;
|
|
||||||
if (details.HasTag && !details.HasOutput)
|
|
||||||
{
|
|
||||||
foreach (StaticGenerator generator in temp.Value.Generators)
|
|
||||||
{
|
|
||||||
generator.Prune();
|
|
||||||
}
|
|
||||||
temp.List.Remove(temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void separateLines()
|
|
||||||
{
|
|
||||||
LinkedListNode<LineDetails> current = _lines.First;
|
|
||||||
while (current != _lines.Last)
|
|
||||||
{
|
|
||||||
List<StaticGenerator> generators = current.Value.Generators;
|
|
||||||
StaticGenerator lastGenerator = generators[generators.Count - 1];
|
|
||||||
lastGenerator.Value += Environment.NewLine;
|
|
||||||
current = current.Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeEmptyGenerators()
|
|
||||||
{
|
|
||||||
LinkedListNode<LineDetails> current = _lines.First;
|
|
||||||
while (current != null)
|
|
||||||
{
|
|
||||||
foreach (StaticGenerator generator in current.Value.Generators)
|
|
||||||
{
|
|
||||||
if (generator.Value.Length == 0)
|
|
||||||
{
|
|
||||||
generator.Prune();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current = current.Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class LineDetails
|
|
||||||
{
|
|
||||||
public LineDetails()
|
|
||||||
{
|
|
||||||
Generators = new List<StaticGenerator>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasTag { get; set; }
|
|
||||||
|
|
||||||
public List<StaticGenerator> Generators { get; set; }
|
|
||||||
|
|
||||||
public bool HasOutput { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -40,6 +40,7 @@
|
||||||
<Compile Include="ContentTagDefinition.cs" />
|
<Compile Include="ContentTagDefinition.cs" />
|
||||||
<Compile Include="Context.cs" />
|
<Compile Include="Context.cs" />
|
||||||
<Compile Include="ContextParameter.cs" />
|
<Compile Include="ContextParameter.cs" />
|
||||||
|
<Compile Include="NewlineTagDefinition.cs" />
|
||||||
<Compile Include="IndexTagDefinition.cs" />
|
<Compile Include="IndexTagDefinition.cs" />
|
||||||
<Compile Include="KeyFoundEventArgs.cs" />
|
<Compile Include="KeyFoundEventArgs.cs" />
|
||||||
<Compile Include="InlineTagDefinition.cs" />
|
<Compile Include="InlineTagDefinition.cs" />
|
||||||
|
@ -68,7 +69,6 @@
|
||||||
<Compile Include="TagDefinition.cs" />
|
<Compile Include="TagDefinition.cs" />
|
||||||
<Compile Include="TagParameter.cs" />
|
<Compile Include="TagParameter.cs" />
|
||||||
<Compile Include="KeyScope.cs" />
|
<Compile Include="KeyScope.cs" />
|
||||||
<Compile Include="Trimmer.cs" />
|
|
||||||
<Compile Include="WithGenerator.cs" />
|
<Compile Include="WithGenerator.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue