Permalink
Browse files

Merge branch 'razor-feature' into unstable. Fixes #1

  • Loading branch information...
2 parents 588a46a + 4c79dfd commit 5fd7bf31dc7404e07d8593600488cdfa9b5749db @dragan committed Sep 22, 2012
View
2 src/Mulder.Acceptance.Tests/Resources/DefaultSite/Rules
@@ -30,7 +30,7 @@ Route("/stylesheet/", (context) => {
Route("*", (context) => {
if (context.Item.IsBinary) {
// Write item with identifier /foo/ to /foo.ext
- return context.Item.Identifier.Chop() + context.Item.Meta["extension"];
+ return context.Item.Identifier.Chop() + context.Item.Meta.Extension;
} else {
// Write item with identifier /foo/ to /foo/index.html
return context.Item.Identifier + "index.html";
View
27 src/Mulder.Base/Compilation/Compiler.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.Linq;
using Mulder.Base.Domain;
@@ -91,12 +92,13 @@ void ExecuteFilters(StaticFile staticFile, Site site)
IFilter filter = filterFactory.CreateFilter(filterName);
string source = staticFile.GetLastSnapShot();
- var arguments = new Dictionary<string, object> {
- { "configuration", site.Configuration as IDictionary<string, object> },
- { "item", staticFile.Item.Meta }
+
+ var filterContext = new FilterContext {
+ Configuration = site.Configuration,
+ Item = staticFile.Item.Meta
};
- string result = filter.Execute(source, arguments);
+ string result = filter.Execute(source, filterContext);
staticFile.CreateSnapShot(result);
}
@@ -108,15 +110,16 @@ void ExecuteLayoutFilter(StaticFile staticFile, Site site)
var layoutRule = site.GetLayoutRuleFor(staticFile.Layout);
IFilter filter = filterFactory.CreateFilter(layoutRule.FilterName);
- var arguments = new Dictionary<string, object> {
- { "configuration", site.Configuration as IDictionary<string, object> },
- { "layout", staticFile.Layout.Meta },
- { "item", staticFile.Item.Meta },
- { "content", staticFile.GetLastSnapShot() }
+
+ var filterContext = new FilterContext {
+ Configuration = site.Configuration,
+ Layout = staticFile.Layout.Meta,
+ Item = staticFile.Item.Meta,
+ Content = staticFile.GetLastSnapShot()
};
-
- string result = filter.Execute(staticFile.Layout.Content, arguments);
-
+
+ string result = filter.Execute(staticFile.Layout.Content, filterContext);
+
staticFile.CreateSnapShot(result);
}
}
View
14 src/Mulder.Base/Compilation/FilterContext.cs
@@ -0,0 +1,14 @@
+using System;
+
+using Mulder.Base.Domain;
+
+namespace Mulder.Base.Compilation
+{
+ public class FilterContext
+ {
+ public IConfiguration Configuration { get; set; }
+ public dynamic Layout { get; set; }
+ public dynamic Item { get; set; }
+ public string Content { get; set; }
+ }
+}
View
2 src/Mulder.Base/Compilation/FilterFactory.cs
@@ -25,6 +25,8 @@ public IFilter CreateFilter(string filterName)
return new MarkdownFilter();
case Filters.LESS:
return new LessFilter(fileSystem);
+ case Filters.RAZOR:
+ return new RazorFilter();
default:
return null;
}
View
3 src/Mulder.Base/Compilation/Filters.cs
@@ -6,6 +6,7 @@ public enum Filters
{
LIQUID,
MARKDOWN,
- LESS
+ LESS,
+ RAZOR
}
}
View
23 src/Mulder.Base/DataSources/FileSystemUnified.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
@@ -153,13 +154,12 @@ List<FileObject> GetFileObjects(string path)
bool isBinary = IsBinary(contentFileName);
ParsedFileData parsedFileData = !isBinary
- ? ParseFiles(contentFileName, metaFileName) : new ParsedFileData { Content = "", Meta = new Dictionary<string, object>() };
+ ? ParseFiles(contentFileName, metaFileName) : new ParsedFileData { Content = "", Meta = new ExpandoObject() };
- IDictionary<string, object> meta = new Dictionary<string, object>(parsedFileData.Meta) {
- { "filename", contentFileName },
- { "meta_filename", metaFileName},
- { "extension", contentFileExtension }
- };
+ dynamic meta = parsedFileData.Meta;
+ meta.Filename = contentFileName;
+ meta.MetaFilename = metaFileName;
+ meta.Extension = contentFileExtension;
string contentFileNameWithoutPath = contentFileName.RemovePathFromFileName(path);
string identifier = GetIdentifierForFileName(contentFileNameWithoutPath);
@@ -234,17 +234,18 @@ bool IsBinary(string fileName)
ParsedFileData ParseFiles(string rawContentFileName, string metaFileName)
{
- IDictionary<string, object> meta = null;
+ dynamic meta = null;
string fileContent = string.Empty;
// If we have a stand alone meta file
if (!string.IsNullOrEmpty(metaFileName)) {
fileContent = !string.IsNullOrEmpty(rawContentFileName) ? fileSystem.ReadStringFromFile(rawContentFileName) : string.Empty;
- meta = fileSystem.ReadStringFromFile(metaFileName).DeserializeYaml()[0] as IDictionary<string, object>;
+ var yaml = fileSystem.ReadStringFromFile(metaFileName).DeserializeYaml()[0] as IDictionary<string, object>;
+ meta = yaml.ToExpando();
}
else {
string rawFileContent = !string.IsNullOrEmpty(rawContentFileName) ? fileSystem.ReadStringFromFile(rawContentFileName) : string.Empty;
- meta = rawFileContent.DeserializeYamlHeader();
+ meta = rawFileContent.DeserializeYamlHeader().ToExpando();
fileContent = rawFileContent.ExcludeYamlHeader();
}
@@ -301,14 +302,14 @@ class FileObject
public string Identifier { get; set; }
public bool IsBinary { get; set; }
public string Content { get; set; }
- public IDictionary<string, object> Meta { get; set; }
+ public dynamic Meta { get; set; }
public DateTime ModificationTime { get; set; }
}
class ParsedFileData
{
public string Content { get; set; }
- public IDictionary<string, object> Meta { get; set; }
+ public dynamic Meta { get; set; }
}
}
}
View
2 src/Mulder.Base/Domain/ISourceFile.cs
@@ -7,7 +7,7 @@ public interface ISourceFile
{
string Identifier { get; }
string Content { get; }
- IDictionary<string, object> Meta { get; }
+ dynamic Meta { get; }
DateTime ModificationTime { get; }
}
}
View
16 src/Mulder.Base/Domain/Item.cs
@@ -8,21 +8,21 @@ public class Item : ISourceFile, IEquatable<Item>
readonly string identifier;
readonly bool isBinary;
readonly string content;
- readonly IDictionary<string, object> meta;
+ readonly dynamic meta;
readonly DateTime modificationTime;
readonly List<Item> children;
readonly List<StaticFile> staticFiles;
public string Identifier { get { return identifier; } }
public bool IsBinary { get { return isBinary; } }
public string Content { get { return content; } }
- public IDictionary<string, object> Meta { get { return meta; } }
+ public dynamic Meta { get { return meta; } }
public DateTime ModificationTime { get { return modificationTime; } }
public Item Parent { get; set; }
public IEnumerable<Item> Children { get { return children; } }
public IEnumerable<StaticFile> StaticFiles { get { return staticFiles; } }
- public Item(string identifier, bool isBinary, string content, IDictionary<string, object> meta, DateTime modificationTime)
+ public Item(string identifier, bool isBinary, string content, dynamic meta, DateTime modificationTime)
{
this.identifier = identifier;
this.isBinary = isBinary;
@@ -53,7 +53,7 @@ public override string ToString()
stringBuilder.AppendLine("IsBinary: \"" + isBinary + "\"");
stringBuilder.AppendLine("Content: \"" + content + "\"");
stringBuilder.AppendLine("Meta:");
- foreach (var kvp in meta) {
+ foreach (var kvp in meta as IDictionary<string, object>) {
stringBuilder.AppendLine(" " + kvp.Key + ": \"" + kvp.Value.ToString() + "\"");
}
@@ -88,9 +88,11 @@ public bool Equals(Item other)
return false;
bool metasAreEqual = true;
- if (meta.Count == other.meta.Count) {
- foreach (var kvp in meta) {
- if (other.meta[kvp.Key].ToString() == kvp.Value.ToString())
+ var metaDictionary = meta as IDictionary<string, object>;
+ var otherMetaDictionary = other.meta as IDictionary<string, object>;
+ if (metaDictionary.Count == otherMetaDictionary.Count) {
+ foreach (var kvp in metaDictionary) {
+ if (otherMetaDictionary[kvp.Key].ToString() == kvp.Value.ToString())
continue;
metasAreEqual = false;
View
16 src/Mulder.Base/Domain/Layout.cs
@@ -7,15 +7,15 @@ public class Layout : ISourceFile, IEquatable<Layout>
{
readonly string identifier;
readonly string content;
- readonly IDictionary<string, object> meta;
+ readonly dynamic meta;
readonly DateTime modificationTime;
public string Identifier { get { return identifier; } }
public string Content { get { return content; } }
- public IDictionary<string, object> Meta { get { return meta; } }
+ public dynamic Meta { get { return meta; } }
public DateTime ModificationTime { get { return modificationTime; } }
- public Layout(string identifier, string content, IDictionary<string, object> meta, DateTime modificationTime)
+ public Layout(string identifier, string content, dynamic meta, DateTime modificationTime)
{
this.identifier = identifier;
this.content = content;
@@ -31,7 +31,7 @@ public override string ToString()
stringBuilder.AppendLine("Identifier: \"" + identifier + "\"");
stringBuilder.AppendLine("Content: \"" + content + "\"");
stringBuilder.AppendLine("Meta:");
- foreach (var kvp in meta) {
+ foreach (var kvp in meta as IDictionary<string, object>) {
stringBuilder.AppendLine(" " + kvp.Key + ": \"" + kvp.Value.ToString() + "\"");
}
@@ -64,9 +64,11 @@ public bool Equals(Layout other)
return false;
bool metasAreEqual = true;
- if (meta.Count == other.meta.Count) {
- foreach (var kvp in meta) {
- if (other.meta[kvp.Key].ToString() == kvp.Value.ToString())
+ var metaDictionary = meta as IDictionary<string, object>;
+ var otherMetaDictionary = other.meta as IDictionary<string, object>;
+ if (metaDictionary.Count == otherMetaDictionary.Count) {
+ foreach (var kvp in metaDictionary) {
+ if (otherMetaDictionary[kvp.Key].ToString() == kvp.Value.ToString())
continue;
metasAreEqual = false;
View
42 src/Mulder.Base/Extensions/DictionaryExtensions.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Dynamic;
+
+namespace Mulder.Base.Extensions
+{
+ public static class DictionaryExtensions
+ {
+ public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary)
+ {
+ var expando = new ExpandoObject();
+ var expandoDictionary = (IDictionary<string, object>)expando;
+
+ foreach (var kvp in dictionary) {
+ if (kvp.Value is IDictionary<string, object>) {
+ var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
+ expandoDictionary.Add(kvp.Key, expandoValue);
+ }
+ else if (kvp.Value is ICollection) {
+ var itemList = new List<object>();
+ foreach (var item in (ICollection)kvp.Value) {
+ if (item is IDictionary<string, object>) {
+ var expandoItem = ((IDictionary<string, object>) item).ToExpando();
+ itemList.Add(expandoItem);
+ }
+ else {
+ itemList.Add(item);
+ }
+ }
+
+ expandoDictionary.Add(kvp.Key, itemList);
+ }
+ else {
+ expandoDictionary.Add(kvp);
+ }
+ }
+
+ return expando;
+ }
+ }
+}
View
5 src/Mulder.Base/Filters/IFilter.cs
@@ -1,10 +1,11 @@
using System;
-using System.Collections.Generic;
+
+using Mulder.Base.Compilation;
namespace Mulder.Base.Filters
{
public interface IFilter
{
- string Execute(string source, IDictionary<string, object> arguments);
+ string Execute(string source, FilterContext filterContext);
}
}
View
5 src/Mulder.Base/Filters/LessFilter.cs
@@ -8,6 +8,7 @@
using dotless.Core.Parser;
using dotless.Core.Stylizers;
+using Mulder.Base.Compilation;
using Mulder.Base.IO;
namespace Mulder.Base.Filters
@@ -21,9 +22,9 @@ public LessFilter(IFileSystem fileSystem)
this.fileSystem = fileSystem;
}
- public string Execute(string source, IDictionary<string, object> arguments)
+ public string Execute(string source, FilterContext filterContext)
{
- var item = arguments["item"] as IDictionary<string, object>;
+ var item = filterContext.Item as IDictionary<string, object>;
string path = Path.GetDirectoryName(item["filename"].ToString());
string result = Transform(source, path);
View
84 src/Mulder.Base/Filters/LiquidFilter.cs
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.IO;
using DotLiquid;
using DotLiquid.FileSystems;
+using Mulder.Base.Compilation;
+
namespace Mulder.Base.Filters
{
public class LiquidFilter : IFilter
@@ -13,26 +16,32 @@ public LiquidFilter()
{
}
- public string Execute(string source, IDictionary<string, object> arguments)
+ public string Execute(string source, FilterContext filterContext)
{
- string includesPath = GetIncludesPath(arguments);
- Hash data = Hash.FromDictionary(arguments);
+ string includesPath = GetIncludesPath(filterContext.Layout);
+
+ var model = new {
+ Configuration = filterContext.Configuration,
+ Layout = new DynamicDrop(filterContext.Layout),
+ Item = new DynamicDrop(filterContext.Item),
+ Content = filterContext.Content
+ };
+
+ Hash hash = Hash.FromAnonymousObject(model);
Template template = Template.Parse(source);
Template.FileSystem = new Includes(includesPath);
- string output = template.Render(data);
+ string output = template.Render(hash);
return output;
}
- string GetIncludesPath(IDictionary<string, object> arguments)
+ string GetIncludesPath(IDictionary<string, object> layout)
{
string includesPath = string.Empty;
-
- if (arguments.ContainsKey("layout")) {
- var layoutMeta = arguments["layout"] as IDictionary<string, object>;
-
- if (layoutMeta.ContainsKey("includes_path"))
- includesPath = layoutMeta["includes_path"].ToString();
+
+ if (layout != null) {
+ if (layout.ContainsKey("includes_path"))
+ includesPath = layout["includes_path"].ToString();
}
return includesPath;
@@ -58,4 +67,57 @@ public string ReadTemplateFile(Context context, string templateName)
return string.Empty;
}
}
+
+ class DynamicDrop : Drop
+ {
+ readonly dynamic model;
+
+ public DynamicDrop(dynamic model)
+ {
+ this.model = GetValidModelType(model);
+ }
+
+ public override object BeforeMethod(string propertyName)
+ {
+ if (model == null)
+ return null;
+
+ if (String.IsNullOrEmpty(propertyName))
+ return null;
+
+ Type modelType = this.model.GetType();
+
+ object value = null;
+ if (modelType.Equals(typeof(Dictionary<string, object>))) {
+ value = GetExpandoObjectValue(propertyName);
+ }
+ else {
+ value = GetPropertyValue(propertyName);
+ }
+
+ return value;
+ }
+
+ object GetExpandoObjectValue(string propertyName)
+ {
+ return (!model.ContainsKey(propertyName)) ? null : model[propertyName];
+ }
+
+ object GetPropertyValue(string propertyName)
+ {
+ var property = model.GetType().GetProperty(propertyName);
+
+ return (property == null) ? null : property.GetValue(model, null);
+ }
+
+ static dynamic GetValidModelType(dynamic model)
+ {
+ if (model == null)
+ return null;
+
+ return model.GetType().Equals(typeof(ExpandoObject))
+ ? new Dictionary<string, object>(model, StringComparer.InvariantCultureIgnoreCase)
+ : model;
+ }
+ }
}
View
5 src/Mulder.Base/Filters/MarkdownFilter.cs
@@ -1,8 +1,9 @@
using System;
-using System.Collections.Generic;
using MarkdownSharp;
+using Mulder.Base.Compilation;
+
namespace Mulder.Base.Filters
{
public class MarkdownFilter : IFilter
@@ -11,7 +12,7 @@ public MarkdownFilter()
{
}
- public string Execute(string source, IDictionary<string, object> arguments)
+ public string Execute(string source, FilterContext filterContext)
{
var markdown = new Markdown();
string output = markdown.Transform(source);
View
75 src/Mulder.Base/Filters/RazorFilter.cs
@@ -0,0 +1,75 @@
+using Microsoft.CSharp.RuntimeBinder;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+using RazorEngine;
+using RazorEngine.Configuration;
+using RazorEngine.Templating;
+
+using Mulder.Base.Compilation;
+
+namespace Mulder.Base.Filters
+{
+ public class RazorFilter : IFilter
+ {
+ public RazorFilter()
+ {
+ }
+
+ public string Execute(string source, FilterContext filterContext)
+ {
+ string includesPath = GetIncludesPath(filterContext.Layout);
+
+ var serviceConfig = new TemplateServiceConfiguration {
+ Resolver = new IncludesResolver(includesPath)
+ };
+
+ Razor.SetTemplateService(new TemplateService(serviceConfig));
+
+ dynamic model = filterContext;
+
+ return Razor.Parse(source, model);
+ }
+
+ string GetIncludesPath(IDictionary<string, object> layout)
+ {
+ string includesPath = string.Empty;
+
+ if (layout != null) {
+ if (layout.ContainsKey("includes_path")) {
+ includesPath = layout["includes_path"].ToString();
+ }
+ }
+
+ return includesPath;
+ }
+ }
+
+ class IncludesResolver : ITemplateResolver
+ {
+ string root;
+
+ public IncludesResolver(string root)
+ {
+ this.root = root;
+ }
+
+ public string Resolve(string name)
+ {
+ string includesPath = Path.Combine(root, name);
+ bool exists = false;
+
+ foreach (var ext in new[] { ".cshtml", ".html", ".htm" }) {
+ var testPath = String.Concat(includesPath, ext);
+ exists = File.Exists(testPath);
+ if (exists) {
+ includesPath = testPath;
+ break;
+ }
+ }
+
+ return exists ? File.ReadAllText(includesPath) : String.Empty;
+ }
+ }
+}
View
6 src/Mulder.Base/Mulder.Base.csproj
@@ -48,6 +48,9 @@
<Reference Include="dotless.Core">
<HintPath>..\..\packages\dotless.1.3.0.3\lib\dotless.Core.dll</HintPath>
</Reference>
+ <Reference Include="RazorEngine">
+ <HintPath>..\..\packages\RazorEngine.3.0.8\lib\net40\RazorEngine.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -91,6 +94,9 @@
<Compile Include="Domain\Configuration.cs" />
<Compile Include="Options.cs" />
<Compile Include="Exceptions\LoadingSiteException.cs" />
+ <Compile Include="Filters\RazorFilter.cs" />
+ <Compile Include="Extensions\DictionaryExtensions.cs" />
+ <Compile Include="Compilation\FilterContext.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
View
2 src/Mulder.Base/Resources/DefaultSite/Rules
@@ -30,7 +30,7 @@ Route("/stylesheet/", (context) => {
Route("*", (context) => {
if (context.Item.IsBinary) {
// Write item with identifier /foo/ to /foo.ext
- return context.Item.Identifier.Chop() + context.Item.Meta["extension"];
+ return context.Item.Identifier.Chop() + context.Item.Meta.Extension;
} else {
// Write item with identifier /foo/ to /foo/index.html
return context.Item.Identifier + "index.html";
View
1 src/Mulder.Base/packages.config
@@ -5,4 +5,5 @@
<package id="DotLiquid" version="1.6.1.0" />
<package id="MarkdownSharp" version="1.13.0.0" />
<package id="dotless" version="1.3.0.3" />
+ <package id="RazorEngine" version="3.0.8" />
</packages>
View
4 src/Mulder.Tests/Base/Compilation/CompilerTests.cs
@@ -114,7 +114,7 @@ public void should_execute_filter_for_static_file_filters()
var staticFiles = site.Items.SelectMany(item => item.StaticFiles);
foreach (StaticFile staticFile in staticFiles) {
- filter.Received().Execute("item-content", Arg.Any<IDictionary<string, object>>());
+ filter.Received().Execute("item-content", Arg.Any<FilterContext>());
}
}
@@ -133,7 +133,7 @@ public void should_execute_filter_for_static_file_layout_filter()
var staticFiles = site.Items.SelectMany(item => item.StaticFiles);
foreach (StaticFile staticFile in staticFiles) {
- filter.Received().Execute("layout-content", Arg.Any<IDictionary<string, object>>());
+ filter.Received().Execute("layout-content", Arg.Any<FilterContext>());
}
}
View
42 src/Mulder.Tests/Base/DataSources/FileSystemUnifiedTests.cs
@@ -286,49 +286,49 @@ IEnumerable<Item> CreateExpectedItems()
false,
"test 1",
new Dictionary<string, object> {
- { "filename", Path.Combine("content", "index.html") },
- { "meta_filename", "" },
- { "extension", ".html" },
+ { "Filename", Path.Combine("content", "index.html") },
+ { "MetaFilename", "" },
+ { "Extension", ".html" },
{ "num", "1" }
},
expectedModificationTime),
new Item("/a/",
false,
"test 2",
new Dictionary<string, object> {
- { "filename", Path.Combine("content", "a.html") },
- { "meta_filename", "" },
- { "extension", ".html" },
+ { "Filename", Path.Combine("content", "a.html") },
+ { "MetaFilename", "" },
+ { "Extension", ".html" },
{ "num", "2" }
},
expectedModificationTime),
new Item("/a/b/",
false,
"test 3",
new Dictionary<string, object> {
- { "filename", Path.Combine("content", "a", "b.html") },
- { "meta_filename", "" },
- { "extension", ".html" },
+ { "Filename", Path.Combine("content", "a", "b.html") },
+ { "MetaFilename", "" },
+ { "Extension", ".html" },
{ "num", "3" }
},
expectedModificationTime),
new Item("/a/b/c/",
false,
"test 4",
new Dictionary<string, object> {
- { "filename", Path.Combine("content", "a", "b", "c.html") },
- { "meta_filename", Path.Combine("content", "a", "b", "c.yaml") },
- { "extension", ".html" },
+ { "Filename", Path.Combine("content", "a", "b", "c.html") },
+ { "MetaFilename", Path.Combine("content", "a", "b", "c.yaml") },
+ { "Extension", ".html" },
{ "num", "4" }
},
expectedModificationTime),
new Item("/binary/",
true,
"",
new Dictionary<string, object> {
- { "filename", Path.Combine("content", "binary.dat") },
- { "meta_filename", "" },
- { "extension", ".dat" }
+ { "Filename", Path.Combine("content", "binary.dat") },
+ { "MetaFilename", "" },
+ { "Extension", ".dat" }
},
expectedModificationTime)
};
@@ -390,18 +390,18 @@ IEnumerable<Layout> CreateExpectedLayouts()
new Layout("/a/",
"test 1",
new Dictionary<string, object> {
- { "filename", Path.Combine("layouts", "a.html") },
- { "meta_filename", "" },
- { "extension", ".html" },
+ { "Filename", Path.Combine("layouts", "a.html") },
+ { "MetaFilename", "" },
+ { "Extension", ".html" },
{ "num", "1" }
},
expectedModificationTime),
new Layout("/b/",
"test 2",
new Dictionary<string, object> {
- { "filename", Path.Combine("layouts", "b.html") },
- { "meta_filename", Path.Combine("layouts", "b.yaml") },
- { "extension", ".html" },
+ { "Filename", Path.Combine("layouts", "b.html") },
+ { "MetaFilename", Path.Combine("layouts", "b.yaml") },
+ { "Extension", ".html" },
{ "num", "2" }
},
expectedModificationTime)
View
70 src/Mulder.Tests/Base/Extensions/DictionaryExtensionsTests.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+
+using NUnit.Framework;
+using Shouldly;
+
+using Mulder.Base.Extensions;
+
+namespace Mulder.Tests.Base.Extensions
+{
+ public class DictionaryExtensionsTests
+ {
+ [TestFixture]
+ public class when_converting_dictionary_to_expando_object
+ {
+ [Test]
+ public void should_contain_dictionary_items_and_values()
+ {
+ var dictionary = new Dictionary<string, object> {
+ { "item_one", 1 },
+ { "item_two", "two" }
+ };
+
+ dynamic expando = dictionary.ToExpando();
+ Assert.That(expando.item_one == 1);
+ Assert.That(expando.item_two == "two");
+ }
+
+ [Test]
+ public void should_be_able_to_handle_a_dictionary_as_a_value()
+ {
+ var dictionary = new Dictionary<string, object> {
+ { "item_one", 1 },
+ { "item_two", "two" },
+ {
+ "item_three",
+ new Dictionary<string, object> {
+ { "item_one", 1 },
+ { "item_two", "two" }
+ }
+ }
+ };
+
+ dynamic expando = dictionary.ToExpando();
+ Assert.That(expando.item_one == 1);
+ Assert.That(expando.item_two == "two");
+ Assert.That(expando.item_three.item_one == 1);
+ Assert.That(expando.item_three.item_two == "two");
+ }
+
+ [Test]
+ public void should_be_able_handle_a_collection_as_a_value()
+ {
+ var dictionary = new Dictionary<string, object> {
+ {
+ "item_one",
+ new List<string> { "one", "two", "three" }
+ }
+ };
+
+ dynamic expando = dictionary.ToExpando();
+ Assert.That(expando.item_one.Contains("one"));
+ Assert.That(expando.item_one.Contains("two"));
+ Assert.That(expando.item_one.Contains("three"));
+ }
+ }
+ }
+}
View
32 src/Mulder.Tests/Base/Filters/LessFilterTests.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.IO;
using NSubstitute;
using NUnit.Framework;
using Shouldly;
+using Mulder.Base.Compilation;
using Mulder.Base.Filters;
using Mulder.Base.IO;
@@ -21,21 +23,18 @@ public void should_be_able_to_transform_source()
{
string source = "@color: #4D926F;#header {color: @color;}h2 {color: @color;}";
string expected = "#header{color:#4d926f}h2{color:#4d926f}";
-
- var arguments = new Dictionary<string, object> {
- {
- "item",
- new Dictionary<string, object> {
- { "filename", Path.Combine("a", "b", "c.less") }
- }
+
+ var filterContext = new FilterContext {
+ Item = new Dictionary<string, object> {
+ { "filename", Path.Combine("a", "b", "c.less") }
}
};
var fileSystem = Substitute.For<IFileSystem>();
var lessFilter = new LessFilter(fileSystem);
- string result = lessFilter.Execute(source, arguments);
+ string result = lessFilter.Execute(source, filterContext);
result.ShouldBe(expected);
}
@@ -47,7 +46,7 @@ public class when_executing_less_filter_on_a_source_that_has_a_nested_dependency
string dependencyFilename;
string source;
string expected;
- IDictionary<string, object> arguments;
+ FilterContext filterContext;
IFileSystem fileSystem;
LessFilter lessFilter;
@@ -63,12 +62,9 @@ public void SetUp()
source = "@import \"variables.less\";#header {color: @color;}h2 {color: @color;}";
expected = "#header{color:#4d926f}h2{color:#4d926f}";
- arguments = new Dictionary<string, object> {
- {
- "item",
- new Dictionary<string, object> {
- { "filename", Path.Combine("a", "b", "c.less") }
- }
+ filterContext = new FilterContext {
+ Item = new Dictionary<string, object> {
+ { "filename", Path.Combine("a", "b", "c.less") }
}
};
@@ -84,23 +80,23 @@ public void SetUp()
[Test]
public void should_call_file_exists_on_file_system()
{
- lessFilter.Execute(source, arguments);
+ lessFilter.Execute(source, filterContext);
fileSystem.Received().FileExists(dependencyFilename);
}
[Test]
public void should_call_read_string_from_file_on_file_system()
{
- lessFilter.Execute(source, arguments);
+ lessFilter.Execute(source, filterContext);
fileSystem.Received().ReadStringFromFile(dependencyFilename);
}
[Test]
public void should_receive_expected_transformed_result()
{
- string result = lessFilter.Execute(source, arguments);
+ string result = lessFilter.Execute(source, filterContext);
result.ShouldBe(expected);
}
View
7 src/Mulder.Tests/Base/Filters/LiquidFilterTests.cs
@@ -4,6 +4,7 @@
using NUnit.Framework;
using Shouldly;
+using Mulder.Base.Compilation;
using Mulder.Base.Filters;
namespace Mulder.Tests.Base.Filters
@@ -20,7 +21,11 @@ public void should_be_able_to_transform_source()
var liquidFilter = new LiquidFilter();
- string result = liquidFilter.Execute("Hi {{name}}!", new Dictionary<string, object> { { "name", "Agent Mulder" } });
+ string result = liquidFilter.Execute("Hi {{item.name}}!", new FilterContext {
+ Item = new Dictionary<string, object> {
+ { "name", "Agent Mulder" }
+ }
+ });
result.ShouldBe(expected);
}
View
3 src/Mulder.Tests/Base/Filters/MarkdownFilterTests.cs
@@ -4,6 +4,7 @@
using NUnit.Framework;
using Shouldly;
+using Mulder.Base.Compilation;
using Mulder.Base.Filters;
namespace Mulder.Tests.Base.Filters
@@ -20,7 +21,7 @@ public void should_be_able_to_transform_source()
var markdownFilter = new MarkdownFilter();
- string result = markdownFilter.Execute("### The Truth Is Out There", new Dictionary<string, object>());
+ string result = markdownFilter.Execute("### The Truth Is Out There", new FilterContext());
result.ShouldContain(expected);
}
View
36 src/Mulder.Tests/Base/Filters/RazorFilterTests.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+
+using NUnit.Framework;
+using Shouldly;
+
+using Mulder.Base.Compilation;
+using Mulder.Base.Filters;
+
+namespace Mulder.Tests.Base.Filters
+{
+ public class RazorFilterTests
+ {
+ [TestFixture]
+ public class when_executing_razor_filter
+ {
+ [Test]
+ public void should_be_able_to_transform_source()
+ {
+ string expected = "Hi Agent Mulder!";
+
+ var razorFilter = new RazorFilter();
+
+ dynamic item = new ExpandoObject();
+ item.Name = "Agent Mulder";
+
+ string result = razorFilter.Execute("Hi @Model.Item.Name!", new FilterContext {
+ Item = item
+ });
+
+ result.ShouldBe(expected);
+ }
+ }
+ }
+}
View
12 src/Mulder.Tests/Mulder.Tests.csproj
@@ -13,22 +13,22 @@
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
+ <DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
- <Optimize>false</Optimize>
+ <Optimize>False</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <ConsolePause>false</ConsolePause>
+ <ConsolePause>False</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
- <Optimize>false</Optimize>
+ <Optimize>False</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <ConsolePause>false</ConsolePause>
+ <ConsolePause>False</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -70,6 +70,8 @@
<Compile Include="Base\Domain\SiteTests.cs" />
<Compile Include="Base\Filters\LessFilterTests.cs" />
<Compile Include="Base\Domain\ConfigurationTests.cs" />
+ <Compile Include="Base\Filters\RazorFilterTests.cs" />
+ <Compile Include="Base\Extensions\DictionaryExtensionsTests.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />

0 comments on commit 5fd7bf3

Please sign in to comment.