Added support for trimming unnecessary newlines.
This commit is contained in:
parent
0b84ca8877
commit
49f9478c79
|
@ -71,7 +71,11 @@ namespace mustache
|
|||
}
|
||||
else
|
||||
{
|
||||
generators = new List<IGenerator>() { _subGenerator };
|
||||
generators = new List<IGenerator>();
|
||||
if (_subGenerator != null)
|
||||
{
|
||||
generators.Add(_subGenerator);
|
||||
}
|
||||
}
|
||||
foreach (KeyScope childScope in scopes)
|
||||
{
|
||||
|
|
|
@ -49,7 +49,8 @@ namespace mustache
|
|||
public Generator Compile(string format)
|
||||
{
|
||||
CompoundGenerator generator = new CompoundGenerator(_master, new ArgumentCollection());
|
||||
int formatIndex = buildCompoundGenerator(_master, _tagScope, generator, format, 0);
|
||||
Trimmer trimmer = new Trimmer();
|
||||
int formatIndex = buildCompoundGenerator(_master, _tagScope, generator, trimmer, format, 0);
|
||||
string trailing = format.Substring(formatIndex);
|
||||
StaticGenerator staticGenerator = new StaticGenerator(trailing);
|
||||
generator.AddGenerator(staticGenerator);
|
||||
|
@ -60,7 +61,7 @@ namespace mustache
|
|||
{
|
||||
foreach (TagDefinition childTag in definition.ChildTags)
|
||||
{
|
||||
scope.AddTag(childTag);
|
||||
scope.TryAddTag(childTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +122,8 @@ namespace mustache
|
|||
private static int buildCompoundGenerator(
|
||||
TagDefinition tagDefinition,
|
||||
TagScope scope,
|
||||
CompoundGenerator generator,
|
||||
CompoundGenerator generator,
|
||||
Trimmer trimmer,
|
||||
string format, int formatIndex)
|
||||
{
|
||||
while (true)
|
||||
|
@ -139,11 +141,10 @@ namespace mustache
|
|||
}
|
||||
|
||||
string leading = format.Substring(formatIndex, match.Index - formatIndex);
|
||||
StaticGenerator staticGenerator = new StaticGenerator(leading);
|
||||
generator.AddGenerator(staticGenerator);
|
||||
|
||||
if (match.Groups["key"].Success)
|
||||
{
|
||||
trimmer.AddStaticGenerator(generator, true, leading);
|
||||
formatIndex = match.Index + match.Length;
|
||||
string key = match.Groups["key"].Value;
|
||||
string alignment = match.Groups["alignment"].Value;
|
||||
|
@ -161,13 +162,14 @@ namespace mustache
|
|||
string message = String.Format(Resources.UnknownTag, tagName);
|
||||
throw new FormatException(message);
|
||||
}
|
||||
trimmer.AddStaticGeneratorBeforeTag(generator, true, leading);
|
||||
if (nextDefinition.HasBody)
|
||||
{
|
||||
ArgumentCollection arguments = getArguments(nextDefinition, match);
|
||||
CompoundGenerator compoundGenerator = new CompoundGenerator(nextDefinition, arguments);
|
||||
TagScope nextScope = new TagScope(scope);
|
||||
registerTags(nextDefinition, nextScope);
|
||||
formatIndex = buildCompoundGenerator(nextDefinition, nextScope, compoundGenerator, format, formatIndex);
|
||||
formatIndex = buildCompoundGenerator(nextDefinition, nextScope, compoundGenerator, trimmer, format, formatIndex);
|
||||
generator.AddGenerator(nextDefinition, compoundGenerator);
|
||||
}
|
||||
else
|
||||
|
@ -181,6 +183,8 @@ namespace mustache
|
|||
else if (match.Groups["close"].Success)
|
||||
{
|
||||
string tagName = match.Groups["name"].Value;
|
||||
TagDefinition nextDefinition = scope.Find(tagName);
|
||||
trimmer.AddStaticGeneratorBeforeTag(generator, false, leading);
|
||||
formatIndex = match.Index;
|
||||
if (tagName == tagDefinition.Name)
|
||||
{
|
||||
|
@ -190,6 +194,7 @@ namespace mustache
|
|||
}
|
||||
else if (match.Groups["comment"].Success)
|
||||
{
|
||||
trimmer.AddStaticGenerator(generator, false, leading);
|
||||
formatIndex = match.Index + match.Length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,18 @@ namespace mustache
|
|||
_tagLookup.Add(definition.Name, definition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trys to register the tag in the current scope.
|
||||
/// </summary>
|
||||
/// <param name="definition">The tag to add to the current scope.</param>
|
||||
public void TryAddTag(TagDefinition definition)
|
||||
{
|
||||
if (Find(definition.Name) == null)
|
||||
{
|
||||
_tagLookup.Add(definition.Name, definition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the tag definition with the given name.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
|
||||
namespace mustache
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes unnecessary whitespace from static text.
|
||||
/// </summary>
|
||||
internal sealed class Trimmer
|
||||
{
|
||||
private bool hasHeader;
|
||||
private bool hasFooter;
|
||||
private bool hasTag;
|
||||
private bool canTrim;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of a Trimmer.
|
||||
/// </summary>
|
||||
public Trimmer()
|
||||
{
|
||||
hasTag = false;
|
||||
canTrim = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the given text, creating a StaticGenerator and adding it to the current compound generator.
|
||||
/// </summary>
|
||||
/// <param name="generator">The compound generator to add the static generator to.</param>
|
||||
/// <param name="isHeader">Gets whether we're encountered the header tag.</param>
|
||||
/// <param name="value">The static text to trim.</param>
|
||||
public void AddStaticGeneratorBeforeTag(CompoundGenerator generator, bool isHeader, string value)
|
||||
{
|
||||
string trimmed = processLines(value);
|
||||
hasHeader |= isHeader;
|
||||
hasFooter |= hasHeader && !isHeader;
|
||||
addStaticGenerator(generator, trimmed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the given text, creating a StaticGenerator and adding it to the current compound generator.
|
||||
/// </summary>
|
||||
/// <param name="generator">The compound generator to add the static generator to.</param>
|
||||
/// <param name="isOutput">Specifies whether the tag results in output.</param>
|
||||
/// <param name="value">The static text to trim.</param>
|
||||
public void AddStaticGenerator(CompoundGenerator generator, bool isOutput, string value)
|
||||
{
|
||||
string trimmed = processLines(value);
|
||||
canTrim &= !isOutput;
|
||||
addStaticGenerator(generator, trimmed);
|
||||
}
|
||||
|
||||
private string processLines(string value)
|
||||
{
|
||||
string trimmed = value;
|
||||
int newline = value.IndexOf(Environment.NewLine);
|
||||
if (newline == -1)
|
||||
{
|
||||
canTrim &= String.IsNullOrWhiteSpace(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// finish processing the previous line
|
||||
if (canTrim && hasTag && (!hasHeader || !hasFooter))
|
||||
{
|
||||
string lineEnd = trimmed.Substring(0, newline);
|
||||
if (String.IsNullOrWhiteSpace(lineEnd))
|
||||
{
|
||||
trimmed = trimmed.Substring(newline + Environment.NewLine.Length);
|
||||
}
|
||||
}
|
||||
// start processing the next line
|
||||
hasTag = false;
|
||||
hasHeader = false;
|
||||
hasFooter = false;
|
||||
int lastNewline = value.LastIndexOf(Environment.NewLine);
|
||||
string lineStart = value.Substring(lastNewline + Environment.NewLine.Length);
|
||||
canTrim = String.IsNullOrWhiteSpace(lineStart);
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
private static void addStaticGenerator(CompoundGenerator generator, string trimmed)
|
||||
{
|
||||
if (trimmed.Length > 0)
|
||||
{
|
||||
StaticGenerator leading = new StaticGenerator(trimmed);
|
||||
generator.AddGenerator(leading);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@
|
|||
<Compile Include="TagParameter.cs" />
|
||||
<Compile Include="KeyScope.cs" />
|
||||
<Compile Include="TagScope.cs" />
|
||||
<Compile Include="Trimmer.cs" />
|
||||
<Compile Include="WithGenerator.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue