Skip to content

Commit

Permalink
Added a simple ColorSpinPlugin. Fixes to LessEngine.
Browse files Browse the repository at this point in the history
minor clean up
prevent double evaluation
  • Loading branch information
jamesfoster-excelpoint authored and lukeapage committed Feb 17, 2012
1 parent cd0d3fd commit fa5d7cf
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 40 deletions.
3 changes: 2 additions & 1 deletion src/dotless.Core/Engine/LessEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace dotless.Core
using Exceptions;
using Loggers;
using Parser.Infrastructure;
using Parser.Tree;

public class LessEngine : ILessEngine
{
Expand Down Expand Up @@ -46,7 +47,7 @@ public string TransformToCss(string source, string fileName)

var env = Env ?? new Env { Compress = Compress };

tree.Evaluate(env);
tree = (Ruleset) tree.Evaluate(env);

tree = Plugins
.Where(p => p.AppliesTo == PluginType.AfterEvaluation)
Expand Down
30 changes: 16 additions & 14 deletions src/dotless.Core/Parser/Infrastructure/Nodes/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ public static bool operator false(Node n)
/// <summary>
/// Copies common properties when evaluating multiple nodes into one
/// </summary>
/// <typeparam name="TN1">Type to return - for convenience</typeparam>
/// <typeparam name="T">Type to return - for convenience</typeparam>
/// <param name="nodes">The nodes this new node is derived from</param>
/// <returns>The new node</returns>
public TN1 ReducedFrom<TN1>(params Node[] nodes) where TN1 : Node
{
foreach (Node node in nodes)
public T ReducedFrom<T>(params Node[] nodes) where T : Node
{
foreach (var node in nodes)
{
if (node == this)
{
Expand Down Expand Up @@ -86,9 +86,9 @@ public TN1 ReducedFrom<TN1>(params Node[] nodes) where TN1 : Node
}
}
}
return (TN1)this;
}
return (T)this;
}

public virtual void AppendCSS(Env env)
{
Expand All @@ -98,13 +98,15 @@ public virtual void AppendCSS(Env env)
Evaluate(env).AppendCSS(env);
}

public virtual string ToCSS(Env env)
{
env.Output.Push()
.Append(this);
return env.Output.Pop().ToString();
}

public virtual string ToCSS(Env env)
{
return env.Output
.Push()
.Append(this)
.Pop()
.ToString();
}

public virtual Node Evaluate(Env env)
{
return this;
Expand Down
21 changes: 16 additions & 5 deletions src/dotless.Core/Parser/Tree/Root.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,25 @@ public override void AppendCSS(Env env)

public override Node Evaluate(Env env)
{
env = env ?? new Env();
if(Evaluated) return this;

NodeHelper.ExpandNodes<Import>(env, this.Rules);
try
{
env = env ?? new Env();

NodeHelper.ExpandNodes<Import>(env, Rules);

Root clone = new Root(new NodeList(Rules), Error, OriginalRuleset).ReducedFrom<Root>(this);
clone.EvaluateRules(env);
var clone = new Root(new NodeList(Rules), Error, OriginalRuleset).ReducedFrom<Root>(this);

return clone;
clone.EvaluateRules(env);
clone.Evaluated = true;

return clone;
}
catch (ParsingException e)
{
throw Error(e);
}
}
}
}
38 changes: 22 additions & 16 deletions src/dotless.Core/Parser/Tree/Ruleset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ namespace dotless.Core.Parser.Tree
public class Ruleset : Node
{
public NodeList<Selector> Selectors { get; set; }
public NodeList Rules { get; set; }
public NodeList Rules { get; set; }
public bool Evaluated { get; protected set; }

/// <summary>
/// The original Ruleset this was cloned from during evaluation
Expand Down Expand Up @@ -121,26 +122,32 @@ public virtual bool MatchArguments(List<NamedArgument> arguements, Env env)

public override Node Evaluate(Env env)
{
if(Evaluated) return this;

// create a clone so it is non destructive
Ruleset clone = new Ruleset(Selectors, new NodeList(Rules), this.OriginalRuleset)
.ReducedFrom<Ruleset>(this);
clone.EvaluateRules(env);
var clone = new Ruleset(Selectors, new NodeList(Rules), OriginalRuleset).ReducedFrom<Ruleset>(this);

clone.EvaluateRules(env);
clone.Evaluated = true;

return clone;
}

public override void Accept(IVisitor visitor)
{
visitor.Visit(Selectors);

foreach (var rule in Rules)
{
rule.Accept(visitor);
}
}

/// <summary>
/// Evaluate Rules. Must only be run on a copy of the ruleset otherwise it will
/// overwrite defintions that might be required later..
/// </summary>
protected void EvaluateRules(Env env)

public override void Accept(IVisitor visitor)
{
visitor.Visit(Selectors);

Rules.ForEach(visitor.Visit);
}

{
env.Frames.Push(this);

Expand All @@ -157,10 +164,9 @@ public override void Accept(IVisitor visitor)
public override void AppendCSS(Env env)
{
if (!Rules.Any())
return;

((Ruleset)Evaluate(env))
.AppendCSS(env, new Context());
return;

((Ruleset) Evaluate(env)).AppendCSS(env, new Context());
}

/// <summary>
Expand Down
40 changes: 40 additions & 0 deletions src/dotless.Core/Plugins/ColorSpinPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace dotless.Core.Plugins
{
using System;
using Parser.Infrastructure.Nodes;
using Parser.Tree;
using Utils;

public class ColorSpinPlugin : VisitorPlugin
{
public double Spin { get; set; }

public ColorSpinPlugin(double spin)
{
Spin = spin;
}

public override PluginType AppliesTo
{
get { return PluginType.AfterEvaluation; }
}

public override bool Execute(Node node)
{
if(node is Color)
{
var color = node as Color;

var hslColor = HslColor.FromRgbColor(color);
hslColor.Hue += Spin/360.0d;
var newColor = hslColor.ToRgbColor();

color.R = newColor.R;
color.G = newColor.G;
color.B = newColor.B;
}

return true;
}
}
}
1 change: 1 addition & 0 deletions src/dotless.Core/dotless.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
<Compile Include="Parser\Tree\KeyFrame.cs" />
<Compile Include="Parser\Tree\Script.cs" />
<Compile Include="Parser\Tree\Root.cs" />
<Compile Include="Plugins\ColorSpinPlugin.cs" />
<Compile Include="Plugins\IPlugin.cs" />
<Compile Include="Plugins\IVisitor.cs" />
<Compile Include="Plugins\VisitorPlugin.cs" />
Expand Down
38 changes: 38 additions & 0 deletions src/dotless.Test/Plugins/ColorSpinPluginFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace dotless.Test.Plugins
{
using System.Collections.Generic;
using System.Linq;
using Core.Parser.Infrastructure;
using Core.Parser.Infrastructure.Nodes;
using Core.Parser.Tree;
using Core.Plugins;
using NUnit.Framework;

public class ColorSpinPluginFixture : SpecFixtureBase
{
protected List<Color> Colors;
protected Ruleset Tree { get; set; }
protected ColorSpinPlugin Plugin { get; set; }

[SetUp]
public void Setup()
{
Plugins.Clear();
Plugins.Add(new ColorSpinPlugin(60));
}

[Test]
public void ColorIsRotated60Degrees()
{
AssertExpression("#646400", "#640000");
AssertExpression("#00c8c8", "#00c800");
}

[Test]
public void ExpressionIsRotatedAfterEvaluation()
{
AssertExpression("#00c864", "#640000 + #00c800");
}

}
}
25 changes: 21 additions & 4 deletions src/dotless.Test/SpecFixtureBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
using Core.Parser;
using System.Collections.Generic;
using System.Linq;
using Core.Parser.Infrastructure;
using Core.Parser.Infrastructure;
using Core.Parser.Tree;
using Core.Plugins;
using Core.Stylizers;
using NUnit.Framework;

public class SpecFixtureBase
{
protected Func<IStylizer> DefaultStylizer;
protected Func<Parser> DefaultParser;
protected Func<Env> DefaultEnv;
protected Func<Env> DefaultEnv;
protected List<IPlugin> Plugins { get; set; }
protected int Optimisation { get; set; }

[SetUp]
Expand All @@ -24,6 +27,7 @@ public void SetupParser()
DefaultStylizer = () => new PlainStylizer();
DefaultParser = () => new Parser(Optimisation, DefaultStylizer(), new Importer());
DefaultEnv = () => new Env();
Plugins = new List<IPlugin>();
}

protected void AssertLess(string input, string expected)
Expand Down Expand Up @@ -137,8 +141,21 @@ public string Evaluate(string input)

public string Evaluate(string input, Parser parser)
{
var tree = parser.Parse(input.Trim(), null);
return tree.ToCSS(DefaultEnv());
var tree = parser.Parse(input.Trim(), null);

var env = DefaultEnv();

tree = Plugins
.Where(p => p.AppliesTo == PluginType.BeforeEvaluation)
.Aggregate(tree, (current, plugin) => plugin.Apply(current));

tree = (Ruleset) tree.Evaluate(env);

tree = Plugins
.Where(p => p.AppliesTo == PluginType.AfterEvaluation)
.Aggregate(tree, (current, plugin) => plugin.Apply(current));

return tree.ToCSS(env);
}
}
}
2 changes: 2 additions & 0 deletions src/dotless.Test/dotless.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Plugins\ColorSpinPluginFixture.cs" />
<Compile Include="Specs\Compression\ColorsFixture.cs" />
<Compile Include="Specs\Compression\CommentsFixture.cs" />
<Compile Include="CompressedSpecFixtureBase.cs" />
Expand Down Expand Up @@ -169,6 +170,7 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down

0 comments on commit fa5d7cf

Please sign in to comment.