YUI’s CompressorTask with MSBuild and Visual Studio

While trying to integrate YUI Compressor as a build task in my current project…

http://yuicompressor.codeplex.com/documentation

Post Build Event:

$(MSBuildBinPath)msbuild.exe "$(SolutionDir)MinificationSettings.xml" /property:SourceLocation=$(ProjectDir) /p:JavaScriptOutputFile=$(ProjectDir)ContentMinScriptsExample.min.js /p:CssOutputFile=$(ProjectDir)ContentMinCSSSite.min.css

I got the error:

MSBUILD : error MSB1008: Only one project can be specified.

C:WindowsMicrosoft.NETFrameworkv4.0.30319msbuild.exe "c:usersspadedocumentsvisual studio 2010ProjectsExampleYUICompressorTaskMinificationSettings.xml"
    /p:SourceLocation=c:usersspadedocumentsvisual studio 2010ProjectsExampleYUICompressorTaskMVCExample
    /p:JavaScriptOutputFile=c:usersspadedocumentsvisual studio 2010ProjectsExampleYUICompressorTaskMVCExampleContentMinScriptsExample.min.js
    /p:CssOutputFile=c:usersspadedocumentsvisual studio 2010ProjectsExampleYUICompressorTaskMVCExampleContentMinCSSSite.min.css

It seems that the spaces in the folder path are preventing me from enjoying YUI Compressor. Quite the same problem this person is having: MSDN Forums: Unable to correctly pass parameters to MS build. Although I suspect he gave up a bit too early.

I tried adding quotes around the value of the parameters, you would think this is going to work, it doesn’t.

Looking for a way to replace the spaces, I came across MS Build Property Functions.

With Build Property Functions, it becomes possible to run the simple replace command in all the spots where I need to, my first guess was to replace space with ‘%20’. That had mixed results, so I was left with choosing an arbitrary token for replacement.

Post Build Event:

$(MSBuildBinPath)msbuild.exe "$(SolutionDir)MinificationSettings.xml"
    /p:SourceLocation=$(ProjectDir.Replace(" ", "[[REPLACESPACE]])
    /p:JavaScriptOutputFile=$(ProjectDir.Replace(" ", "[[REPLACESPACE]])ContentMinScriptsExample.min.js
    /p:CssOutputFile=$(ProjectDir.Replace(" ", "[[REPLACESPACE]])ContentMinCSSSite.min.css

MinificationSettings.Xml:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
  <UsingTask
      TaskName="CompressorTask"
      AssemblyFile="packagesYUICompressor.NET-MsBuild-Task.1.6.0.2libNET35Yahoo.Yui.Compressor.MsBuildTask.dll" />

  <PropertyGroup>
    <CssOutputFile Condition=" '$(CssOutputFile)'=='' ">SylesSheetFinal.css</CssOutputFile>
    <JavaScriptOutputFile Condition=" '$(JavaScriptOutputFile)'=='' ">JavaScriptFinal.js</JavaScriptOutputFile>
  </PropertyGroup>

  <PropertyGroup>
    <CssOutputFileFix>$(CssOutputFile.Replace('[[REPLACESPACE]]', ' '))</CssOutputFileFix>
    <JavaScriptOutputFileFix>$(JavaScriptOutputFile.Replace('[[REPLACESPACE]]', ' '))</JavaScriptOutputFileFix>
  </PropertyGroup>

  <Target Name="MyTaskTarget">
    <ItemGroup>
      
      <JavaScriptFiles Include="$(SourceLocation.Replace('[[REPLACESPACE]]', ' '))ContentScriptsExample.js"/>
	  <CssFiles Include="$(SourceLocation.Replace('[[REPLACESPACE]]', ' '))ContentCSSSite.css"/>

    </ItemGroup>
    <CompressorTask
        CssFiles="@(CssFiles)"
        DeleteCssFiles="false"
        CssOutputFile="$(CssOutputFileFix)"
        CssCompressionType="YuiStockCompression"
        JavaScriptFiles="@(JavaScriptFiles)"
        ObfuscateJavaScript="True"
        PreserveAllSemicolons="False"
        DisableOptimizations="Nope"
        EncodingType="Default"
        DeleteJavaScriptFiles="false"
        LineBreakPosition="-1"
        JavaScriptOutputFile="$(JavaScriptOutputFileFix)"
        LoggingType="ALittleBit"
        ThreadCulture="en-au"
        IsEvalIgnored="false"
            />
  </Target>
</Project>

Source Code