Skip to content

Instantly share code, notes, and snippets.

@adbrowne
Created March 18, 2012 03:05
Show Gist options
  • Save adbrowne/2068290 to your computer and use it in GitHub Desktop.
Save adbrowne/2068290 to your computer and use it in GitHub Desktop.
Replacing variables in javascript files with Cassette IAssetTransformer
public class ConstantsGenerator : IAssetTransformer
{
private const char ConstantStartToken = '#';
private const char OpeningBraceToken = '{';
private const char ClosingBraceToken = '}';
private readonly Dictionary<string, string> values;
public ConstantsGenerator(Dictionary<string, string> values)
{
this.values = values;
}
public Func<Stream> Transform(Func<Stream> openSourceStream, IAsset asset)
{
return delegate
{
using (var input = new StreamReader(new BufferedStream(openSourceStream())))
{
var outputStream = new MemoryStream();
var writer = new StreamWriter(outputStream);
TransformStream(input, writer);
writer.Flush();
outputStream.Position = 0;
return outputStream;
}
};
}
private void TransformStream(StreamReader input, StreamWriter writer)
{
while (!input.EndOfStream)
{
var currentChar = (char)input.Read();
var nextChar = (char)input.Peek();
if (currentChar == ConstantStartToken && nextChar == OpeningBraceToken)
{
ReadVariable(input, writer);
}
else
{
writer.Write(currentChar);
}
}
}
private enum ReadState
{
Continue,
Eos,
Complete
}
private void ReadVariable(StreamReader input, StreamWriter writer)
{
var variableName = new StringBuilder();
//throw away starting brace
input.Read();
var state = ReadState.Continue;
while (state == ReadState.Continue)
{
if(input.EndOfStream)
{
state = ReadState.Eos;
}
else
{
var currentChar = (char)input.Read();
if (currentChar != ClosingBraceToken)
{
variableName.Append(currentChar);
}
if(currentChar == ClosingBraceToken)
{
state = ReadState.Complete;
}
}
}
if (state == ReadState.Complete)
{
var key = variableName.ToString().Trim();
if (values.ContainsKey(key))
{
WriteValue(writer, key);
}
else
{
WriteVariableAsInput(writer, variableName);
}
}
else if(state == ReadState.Eos)
{
WriteVariableCharactersAsRead(writer, variableName);
}
}
private void WriteValue(StreamWriter writer, string key)
{
string variableValue = values[key];
writer.Write(variableValue);
}
private static void WriteVariableAsInput(StreamWriter writer, StringBuilder variableName)
{
writer.Write(ConstantStartToken);
writer.Write(OpeningBraceToken);
writer.Write(variableName.ToString());
writer.Write(ClosingBraceToken);
}
private static void WriteVariableCharactersAsRead(StreamWriter writer, StringBuilder variableName)
{
writer.Write(ConstantStartToken);
writer.Write(OpeningBraceToken);
writer.Write(variableName.ToString());
}
}
//From CassetteConfiguration
bundles.AddPerSubDirectory("js", (Action<ScriptBundle>) (b => b.Processor = new ScriptPipeline().Prepend(new ReplaceConstants(constants))));
public class ReplaceConstants : IBundleProcessor<ScriptBundle>
{
private readonly Dictionary<string, string> values;
public ReplaceConstants(Dictionary<string, string> values)
{
this.values = values;
}
public void Process(ScriptBundle bundle, CassetteSettings settings)
{
foreach (var asset in bundle.Assets)
{
if (asset.SourceFile.FullPath.EndsWith("constants.js"))
{
asset.AddAssetTransformer(new ConstantsGenerator(values));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment