Skip to content

Commit

Permalink
This sassy commit is all the rage this summer.
Browse files Browse the repository at this point in the history
Solves Code52#192 - introduces Sass for CSS generation. Uses Libsassnet to provide the Sassyness.

Switches out ILMerge for Fody/Costura. When handling unmanaged assemblies, this is the best solution. This required some modifications to how MEF was used.
It uses a very specific version of Fody/Costura because of issues with VS15, I think. Please don't update it.
  • Loading branch information
vikingcode committed Feb 21, 2015
1 parent 9e50d67 commit 62ad269
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 16 deletions.
88 changes: 88 additions & 0 deletions src/Pretzel.Logic/Minification/SassTransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using HtmlAgilityPack;
using LibSassNet;
using Pretzel.Logic.Extensibility;
using Pretzel.Logic.Templating.Context;

namespace Pretzel.Logic.Minification
{
public class SassTransform : ITransform
{
private static readonly string[] ExternalProtocols = { "http", "https", "//" };

#pragma warning disable 0649
private readonly IFileSystem fileSystem;
#pragma warning restore 0649

[ImportingConstructor]
public SassTransform(IFileSystem fileSystem)
{
this.fileSystem = fileSystem;
}

private string filePath = string.Empty;

private readonly ISassCompiler compiler = new SassCompiler();

public void Transform(SiteContext siteContext)
{
var shouldCompile = new List<Page>();
//Process to see if the site has a CSS file that doesn't exist, and should be created from LESS files.
//This is "smarter" than just compiling all Less files, which will crash if they're part of a larger Less project
//ie, one file pulls in imports, individually they don't know about each other but use variables
foreach (var file in siteContext.Pages.Where(p => p.OutputFile.EndsWith(".html") && fileSystem.File.Exists(p.OutputFile)))
{
var doc = new HtmlDocument();
var fileContents = fileSystem.File.ReadAllText(file.OutputFile);
doc.LoadHtml(fileContents);

var nodes = doc.DocumentNode.SelectNodes("/html/head/link[@rel='stylesheet']");
if (nodes != null)
foreach (HtmlNode link in nodes)
{
var cssfile = link.Attributes["href"].Value;

// If the file is not local, ignore it
var matchingIgnoreProtocol = ExternalProtocols.FirstOrDefault(cssfile.StartsWith);
if (matchingIgnoreProtocol != null)
continue;

//If the file exists, ignore it
if (fileSystem.File.Exists(Path.Combine(siteContext.OutputFolder, cssfile)))
continue;

//If there is a CSS file that matches the name, ignore, could be another issue
if (siteContext.Pages.Any(p => p.OutputFile.Contains(cssfile)))
continue;


var n = cssfile.Replace(".css", ".scss");
n = n.Replace('/', '\\');

var cssPageToCompile = siteContext.Pages.FirstOrDefault(f => f.OutputFile.Contains(n));
if (cssPageToCompile != null && !shouldCompile.Contains(cssPageToCompile))
{
shouldCompile.Add(cssPageToCompile);
}
}
}

foreach (var less in shouldCompile)
{
filePath = less.OutputFile;
fileSystem.File.WriteAllText(less.OutputFile.Replace(".scss", ".css"), ProcessCss(siteContext, less.Filepath));
fileSystem.File.Delete(less.OutputFile);
}
}

public string ProcessCss(SiteContext siteContext, string file)
{
var x = compiler.CompileFile(file).CSS;
return x;
}
}
}
11 changes: 9 additions & 2 deletions src/Pretzel.Logic/Pretzel.Logic.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -49,6 +50,12 @@
<Reference Include="HtmlAgilityPack">
<HintPath>..\packages\HtmlAgilityPack.1.4.9\lib\Net40\HtmlAgilityPack.dll</HintPath>
</Reference>
<Reference Include="LibSass.x86">
<HintPath>..\packages\libsassnet.3.0.1.1\lib\net40\LibSass.x86.dll</HintPath>
</Reference>
<Reference Include="libsassnet">
<HintPath>..\packages\libsassnet.3.0.1.1\lib\net40\libsassnet.dll</HintPath>
</Reference>
<Reference Include="NDesk.Options">
<HintPath>..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -113,6 +120,7 @@
<Compile Include="Minification\LessTransform.cs" />
<Compile Include="Extensibility\ITransform.cs" />
<Compile Include="Minification\JsMinifier.cs" />
<Compile Include="Minification\SassTransform.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Liquid.Designer.cs">
<AutoGen>True</AutoGen>
Expand Down Expand Up @@ -286,5 +294,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>

</Project>
1 change: 1 addition & 0 deletions src/Pretzel.Logic/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<package id="DotlessClientOnly" version="1.4.1.0" targetFramework="net40" />
<package id="DotLiquid" version="1.8.0" targetFramework="net40" />
<package id="HtmlAgilityPack" version="1.4.9" targetFramework="net40" />
<package id="libsassnet" version="3.0.1.1" targetFramework="net40" />
<package id="MarkdownDeep.NET" version="1.5" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
<package id="NDesk.Options" version="0.2.1" />
Expand Down
9 changes: 9 additions & 0 deletions src/Pretzel/FodyWeavers.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Costura>
<Unmanaged32Assemblies>
LibSass.x86
</Unmanaged32Assemblies>
</Costura>

</Weavers>
25 changes: 13 additions & 12 deletions src/Pretzel/Pretzel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<NuGetPackageImportStamp>46fc839a</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
Expand Down Expand Up @@ -156,21 +157,21 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="FodyWeavers.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="pretzel.ico" />
</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.
<Target Name="BeforeBuild">
<Import Project="..\packages\Fody.1.26.4\build\Fody.targets" Condition="Exists('..\packages\Fody.1.26.4\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.1.26.4\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.26.4\build\Fody.targets'))" />
</Target>
-->
<Target Name="AfterBuild" Condition="(($(MSBuildTargets) == '') Or ($(MSBuildTargets) == 'CSharp')) And '$(OS)' == 'Windows_NT' And '$(NCrunch)' == ''">
<CreateItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)'=='.dll'">
<Output ItemName="AssembliesToMerge" TaskParameter="Include" />
</CreateItem>
<exec command="&quot;$(MSBuildProjectDirectory)\..\..\tools\Ilmerge\ILMerge.exe&quot; /out:@(MainAssembly) &quot;/targetplatform:v4,$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0&quot; &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
<delete files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
<Target AfterTargets="AfterBuild;NonWinFodyTarget" Name="CleanReferenceCopyLocalPaths">
<Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>
</Project>

</Project>
15 changes: 13 additions & 2 deletions src/Pretzel/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,19 @@ public void Compose()
{
try
{
var first = new AssemblyCatalog(Assembly.GetExecutingAssembly());
catalog = new AggregateCatalog(first);
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();

loadedAssemblies
.SelectMany(x => x.GetReferencedAssemblies())
.Distinct()
.Where(y => loadedAssemblies.Any((a) => a.FullName == y.FullName) == false)
.ToList()
.ForEach(x => loadedAssemblies.Add(AppDomain.CurrentDomain.Load(x)));

catalog = new AggregateCatalog();

foreach (var l in loadedAssemblies)
catalog.Catalogs.Add(new AssemblyCatalog(l));
container = new CompositionContainer(catalog);

var batch = new CompositionBatch();
Expand Down
2 changes: 2 additions & 0 deletions src/Pretzel/packages.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="1.3.3.0" targetFramework="net40" developmentDependency="true" />
<package id="Firefly" version="0.6.3" targetFramework="net40" />
<package id="Fody" version="1.26.4" targetFramework="net40" developmentDependency="true" />
<package id="Gate.Middleware.Sources" version="0.27" targetFramework="net40" />
<package id="Gate.Sources" version="0.27" targetFramework="net40" />
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net40" />
Expand Down

0 comments on commit 62ad269

Please sign in to comment.