diff --git a/umbraco.Juno/Properties/AssemblyInfo.cs b/umbraco.Juno/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..d5b59a2a3d
--- /dev/null
+++ b/umbraco.Juno/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("umbraco.Juno")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("umbraco.Juno")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6a24821f-2031-4e6b-af37-c045c9de9ce3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/umbraco.Juno/umbraco.Juno.csproj b/umbraco.Juno/umbraco.Juno.csproj
new file mode 100644
index 0000000000..015aca1f88
--- /dev/null
+++ b/umbraco.Juno/umbraco.Juno.csproj
@@ -0,0 +1,58 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {6C9A6403-6457-4989-BF20-A575535B89AF}
+ Library
+ Properties
+ umbraco.Juno
+ umbraco.Juno
+ v4.0
+ 512
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/umbraco.Juno/umbraco.Juno.csproj.vspscc b/umbraco.Juno/umbraco.Juno.csproj.vspscc
new file mode 100644
index 0000000000..feffdecaa4
--- /dev/null
+++ b/umbraco.Juno/umbraco.Juno.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/umbraco.MacroEngines.Juno/DLRScriptingEngine.cs b/umbraco.MacroEngines.Juno/DLRScriptingEngine.cs
new file mode 100644
index 0000000000..37c3acb2d2
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/DLRScriptingEngine.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using umbraco.cms.businesslogic.macro;
+using umbraco.interfaces;
+using umbraco.IO;
+using umbraco.MacroEngines.Scripting;
+
+namespace umbraco.MacroEngines
+{
+ public class DLRScriptingEngine : IMacroEngine
+ {
+ #region IMacroEngine Members
+
+ public string Name
+ {
+ get { return "Umbraco DLR Macro Engine"; }
+ }
+
+ public List SupportedExtensions
+ {
+ get
+ {
+ var exts = new List {"py", "rb"};
+ return exts;
+ }
+ }
+
+ public Dictionary SupportedProperties
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+
+ public bool Validate(string code, INode currentPage, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public string Execute(MacroModel macro, INode currentPage)
+ {
+ string fileEnding = macro.ScriptName.Substring(macro.ScriptName.LastIndexOf('.')).Trim('.');
+
+ MacroScriptEngine mse = MacroScriptEngine.LoadEngineByFileExtension(fileEnding);
+
+ var vars = new SortedDictionary {{"currentPage", currentPage}};
+ foreach (MacroPropertyModel prop in macro.Properties)
+ {
+ vars.Add(prop.Key, prop.Value);
+ }
+ mse.ScriptVariables = vars;
+
+ return mse.ExecuteFile(IOHelper.MapPath(SystemDirectories.Python + "/" + macro.ScriptName));
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/DynamicNode.cs b/umbraco.MacroEngines.Juno/DynamicNode.cs
new file mode 100644
index 0000000000..df4c0fb6d9
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/DynamicNode.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Text;
+using umbraco.interfaces;
+using umbraco.presentation.nodeFactory;
+
+namespace umbraco.MacroEngines
+{
+ public class DynamicNode : DynamicObject
+ {
+ private INode n;
+ public DynamicNode(INode n)
+ {
+ this.n = n;
+ }
+
+ public List GetChildrenAsList
+ {
+ get
+ {
+ List nodes = new List();
+ foreach(Node nn in n.ChildrenAsList)
+ nodes.Add(new DynamicNode(nn));
+
+ return nodes;
+ }
+ }
+
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+
+ var name = binder.Name;
+
+ if (name == "ChildrenAsList" || name == "Children")
+ {
+ result = GetChildrenAsList;
+ return true;
+ } else if (name == "Parent")
+ {
+ result = new DynamicNode(n.Parent);
+ return true;
+ }
+
+ var data = n.GetProperty(name);
+ // check for nicer support of Pascal Casing EVEN if alias is camelCasing:
+ if (data == null && name.Substring(0,1).ToUpper() == name.Substring(0,1))
+ {
+ data = n.GetProperty(name.Substring(0, 1).ToLower() + name.Substring((1)));
+ }
+
+
+ if (data != null)
+ {
+ result = data.Value;
+ return true;
+ } else
+ {
+ try
+ {
+ result = n.GetType().InvokeMember(binder.Name,
+ System.Reflection.BindingFlags.GetProperty |
+ System.Reflection.BindingFlags.Instance |
+ System.Reflection.BindingFlags.Public |
+ System.Reflection.BindingFlags.NonPublic,
+ null,
+ n,
+ null);
+ return true;
+ } catch
+ {
+ result = "";
+ return false;
+ }
+ }
+
+
+ return base.TryGetMember(binder, out result);
+ }
+ }
+}
diff --git a/umbraco.MacroEngines.Juno/Properties/AssemblyInfo.cs b/umbraco.MacroEngines.Juno/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..142b376615
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("umbraco.MacroEngines")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("umbraco.MacroEngines")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("207a5ae9-5f35-4dec-a649-d3cf4d0efbd9")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/umbraco.MacroEngines.Juno/Razor/CSharpRazorProvider.cs b/umbraco.MacroEngines.Juno/Razor/CSharpRazorProvider.cs
new file mode 100644
index 0000000000..e9b9f8d4c9
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/CSharpRazorProvider.cs
@@ -0,0 +1,33 @@
+namespace umbraco.MacroEngines.Razor
+{
+ using System.CodeDom.Compiler;
+ using System.Web.Razor;
+
+ using Microsoft.CSharp;
+
+ ///
+ /// Provides a razor provider that supports the C# syntax.
+ ///
+ public class CSharpRazorProvider : IRazorProvider
+ {
+ #region Methods
+ ///
+ /// Creates a code language service.
+ ///
+ /// Creates a language service.
+ public RazorCodeLanguage CreateLanguageService()
+ {
+ return new CSharpRazorCodeLanguage();
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The a code dom provider.
+ public CodeDomProvider CreateCodeDomProvider()
+ {
+ return new CSharpCodeProvider();
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/IRazorProvider.cs b/umbraco.MacroEngines.Juno/Razor/IRazorProvider.cs
new file mode 100644
index 0000000000..b66a602322
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/IRazorProvider.cs
@@ -0,0 +1,26 @@
+namespace umbraco.MacroEngines.Razor
+{
+ using System.CodeDom;
+ using System.CodeDom.Compiler;
+ using System.Web.Razor;
+
+ ///
+ /// Defines a provider used to create associated compiler types.
+ ///
+ public interface IRazorProvider
+ {
+ #region Methods
+ ///
+ /// Creates a code language service.
+ ///
+ /// Creates a language service.
+ RazorCodeLanguage CreateLanguageService();
+
+ ///
+ /// Creates a .
+ ///
+ /// The a code dom provider.
+ CodeDomProvider CreateCodeDomProvider();
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/ITemplate.cs b/umbraco.MacroEngines.Juno/Razor/ITemplate.cs
new file mode 100644
index 0000000000..9a549bab65
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/ITemplate.cs
@@ -0,0 +1,58 @@
+using System.Dynamic;
+namespace umbraco.MacroEngines.Razor
+{
+ ///
+ /// A razor template.
+ ///
+ public interface ITemplate
+ {
+ #region Properties
+ ///
+ /// Gets the parsed result of the template.
+ ///
+ string Result { get; }
+ #endregion
+
+ #region Methods
+ ///
+ /// Clears the template.
+ ///
+ void Clear();
+
+ ///
+ /// Executes the template.
+ ///
+ void Execute();
+
+ ///
+ /// Writes the specified object to the template.
+ ///
+ ///
+ void Write(object @object);
+
+ ///
+ /// Writes a literal to the template.
+ ///
+ ///
+ void WriteLiteral(string literal);
+ #endregion
+ }
+
+ ///
+ /// A razor template with a model.
+ ///
+ /// The model type
+ public interface ITemplate : ITemplate
+ {
+ #region Properties
+ ///
+ /// Gets or sets the model.
+ ///
+ TModel Model { get; set; }
+ #endregion
+ }
+
+ public interface ITemplateDynamic : ITemplate {
+ dynamic Model { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/Razor.cs b/umbraco.MacroEngines.Juno/Razor/Razor.cs
new file mode 100644
index 0000000000..54b084b29d
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/Razor.cs
@@ -0,0 +1,87 @@
+namespace umbraco.MacroEngines.Razor
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// Process razor templates.
+ ///
+ public static class Razor
+ {
+ #region Fields
+ private static RazorCompiler Compiler;
+ private static readonly IDictionary Templates;
+ #endregion
+
+ #region Constructor
+ ///
+ /// Statically initialises the type.
+ ///
+ static Razor()
+ {
+ Compiler = new RazorCompiler(new CSharpRazorProvider());
+ Templates = new Dictionary();
+ }
+ #endregion
+
+ #region Methods
+ ///
+ /// Gets an for the specified template.
+ ///
+ /// The template to parse.
+ /// The model to use in the template.
+ /// [Optional] The name of the template.
+ ///
+ private static ITemplate GetTemplate(string template, Type modelType, string name = null)
+ {
+ if (!string.IsNullOrEmpty(name))
+ {
+ if (Templates.ContainsKey(name))
+ return Templates[name];
+ }
+
+ var instance = Compiler.CreateTemplate(template, modelType);
+
+ if (!string.IsNullOrEmpty(name))
+ {
+ if (!Templates.ContainsKey(name))
+ Templates.Add(name, instance);
+ }
+
+ return instance;
+ }
+
+ ///
+ /// Parses the specified template using the specified model.
+ ///
+ /// The model type.
+ /// The template to parse.
+ /// The model to use in the template.
+ /// [Optional] A name for the template used for caching.
+ /// The parsed template.
+ public static string Parse(string template, T model, string name = null)
+ {
+ var instance = GetTemplate(template, typeof(T), name);
+ if (instance is ITemplate)
+ ((ITemplate)instance).Model = model;
+ else if (instance is ITemplateDynamic)
+ ((ITemplateDynamic)instance).Model = model;
+
+ instance.Execute();
+ return instance.Result;
+ }
+
+ ///
+ /// Sets the razor provider used for compiling templates.
+ ///
+ /// The razor provider.
+ public static void SetRazorProvider(IRazorProvider provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException("provider");
+
+ Compiler = new RazorCompiler(provider);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/RazorCompiler.cs b/umbraco.MacroEngines.Juno/Razor/RazorCompiler.cs
new file mode 100644
index 0000000000..94c2525352
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/RazorCompiler.cs
@@ -0,0 +1,108 @@
+using System.CodeDom;
+
+namespace umbraco.MacroEngines.Razor {
+ using System;
+ using System.CodeDom.Compiler;
+ using System.IO;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Web.Razor;
+ using System.Web.Razor.Parser;
+ using System.Runtime.CompilerServices;
+
+ ///
+ /// Compiles razor templates.
+ ///
+ internal class RazorCompiler {
+ #region Fields
+ private readonly IRazorProvider provider;
+ #endregion
+
+ #region Constructor
+ ///
+ /// Initialises a new instance of .
+ ///
+ /// The provider used to compile templates.
+ public RazorCompiler(IRazorProvider provider) {
+ if (provider == null)
+ throw new ArgumentNullException("provider");
+
+ this.provider = provider;
+ }
+ #endregion
+
+ #region Methods
+ ///
+ /// Compiles the template.
+ ///
+ /// The class name of the dynamic type.
+ /// The template to compile.
+ /// [Optional] The mode type.
+ private CompilerResults Compile(string className, string template, Type modelType = null) {
+ var languageService = provider.CreateLanguageService();
+ var codeDom = provider.CreateCodeDomProvider();
+ var host = new RazorEngineHost(languageService);
+
+ var generator = languageService.CreateCodeGenerator(className, "Razor.Dynamic", null, host);
+ var parser = new RazorParser(languageService.CreateCodeParser(), new HtmlMarkupParser());
+
+ // Umbraco hack for use with DynamicNode
+ bool anonymousType = modelType.FullName == "umbraco.MacroEngines.DynamicNode" || (modelType.IsClass && modelType.IsSealed && modelType.BaseType == typeof(object) && modelType.Name.StartsWith("<>") && modelType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true) != null);
+
+ //There's no simple way of determining if an object is an anonymous type - this seems like a problem
+ Type baseType = (modelType == null)
+ ? typeof(TemplateBase)
+ : (anonymousType
+ ? typeof(TemplateBaseDynamic)
+ : typeof(TemplateBase<>).MakeGenericType(modelType));
+
+ generator.GeneratedClass.BaseTypes.Add(baseType);
+
+ using (var reader = new StreamReader(new MemoryStream(Encoding.ASCII.GetBytes(template)))) {
+ parser.Parse(reader, generator);
+ }
+
+ var statement = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Clear");
+ generator.GeneratedExecuteMethod.Statements.Insert(0, new CodeExpressionStatement(statement));
+
+ var builder = new StringBuilder();
+ using (var writer = new StringWriter(builder)) {
+ codeDom.GenerateCodeFromCompileUnit(generator.GeneratedCode, writer, new CodeGeneratorOptions());
+ }
+
+ var @params = new CompilerParameters();
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) {
+ if (!assembly.IsDynamic)
+ @params.ReferencedAssemblies.Add(assembly.Location);
+ }
+
+ @params.GenerateInMemory = true;
+ @params.IncludeDebugInformation = false;
+ @params.GenerateExecutable = false;
+ @params.CompilerOptions = "/target:library /optimize";
+
+ var result = codeDom.CompileAssemblyFromSource(@params, new[] { builder.ToString() });
+ return result;
+ }
+
+ ///
+ /// Creates a from the specified template string.
+ ///
+ /// The template to compile.
+ /// [Optional] The model type.
+ /// An instance of .
+ public ITemplate CreateTemplate(string template, Type modelType = null) {
+ string className = Regex.Replace(Guid.NewGuid().ToString("N"), @"[^A-Za-z]*", "");
+
+ var result = Compile(className, template, modelType);
+
+ if (result.Errors != null && result.Errors.Count > 0)
+ throw new TemplateException(result.Errors);
+
+ ITemplate instance = (ITemplate)result.CompiledAssembly.CreateInstance("Razor.Dynamic." + className);
+
+ return instance;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/TemplateBase.cs b/umbraco.MacroEngines.Juno/Razor/TemplateBase.cs
new file mode 100644
index 0000000000..6a88a5b6cb
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/TemplateBase.cs
@@ -0,0 +1,146 @@
+namespace umbraco.MacroEngines.Razor
+{
+ using System.Text;
+ using System.IO;
+ using System.Globalization;
+ using System.Dynamic;
+ using System;
+ using System.Runtime.CompilerServices;
+
+ ///
+ /// Provides a base implementation of a template.
+ ///
+ public abstract class TemplateBase : ITemplate
+ {
+ #region Fields
+ private TextWriter builder = new StringWriter(CultureInfo.InvariantCulture);
+
+ #endregion
+
+ #region Properties
+ ///
+ /// Gets the parsed result of the template.
+ ///
+ public string Result { get { return builder.ToString(); } }
+ #endregion
+
+ #region Methods
+ ///
+ /// Clears the template.
+ ///
+ public void Clear()
+ {
+ builder = new StringWriter(CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Executes the template.
+ ///
+ public virtual void Execute() { }
+
+ ///
+ /// Writes the specified object to the template.
+ ///
+ ///
+ public void Write(object @object)
+ {
+ if (@object == null)
+ return;
+
+ builder.Write(@object);
+ }
+
+ ///
+ /// Writes a literal to the template.
+ ///
+ ///
+ public void WriteLiteral(string literal)
+ {
+ if (literal == null)
+ return;
+
+ builder.Write(literal);
+ }
+ #endregion
+ }
+
+ ///
+ /// Provides a base implementation of a template.
+ ///
+ /// The model type.
+ public abstract class TemplateBase : TemplateBase, ITemplate
+ {
+ #region Properties
+ public TModel Model { get; set; }
+
+ ///
+ /// Gets or sets the model.
+ ///
+ #endregion
+
+ }
+
+ ///
+ /// Inherits form TemplateBase and provides an anonymous type implementation
+ ///
+ public abstract class TemplateBaseDynamic : TemplateBase, ITemplateDynamic
+ {
+
+ dynamic model;
+
+ ///
+ /// Gets or sets an anonymous type model
+ ///
+ public dynamic Model
+ {
+ get
+ {
+ return model;
+ }
+ set
+ {
+ model = new RazorDynamicObject() { Model = value };
+ }
+ }
+
+
+ ///
+ /// Dynamic object that we'll utilize to return anonymous type parameters
+ ///
+ class RazorDynamicObject : DynamicObject
+ {
+ internal object Model { get; set; }
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ bool isDynamicNode = false;
+ object tempResult = null;
+ try
+ {
+ if (Model.GetType().FullName == "RazorControl.DynamicNode")
+ {
+ isDynamicNode = ((DynamicObject)Model).TryGetMember(binder, out tempResult);
+ }
+
+ }
+ catch
+ {
+ result = "";
+ }
+ if (!isDynamicNode)
+ {
+ tempResult = Model.GetType().InvokeMember(binder.Name,
+ System.Reflection.BindingFlags.GetProperty |
+ System.Reflection.BindingFlags.Instance |
+ System.Reflection.BindingFlags.Public |
+ System.Reflection.BindingFlags.NonPublic,
+ null,
+ Model,
+ null);
+ }
+ result = tempResult;
+ return true;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/TemplateException.cs b/umbraco.MacroEngines.Juno/Razor/TemplateException.cs
new file mode 100644
index 0000000000..27a65976d1
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/TemplateException.cs
@@ -0,0 +1,37 @@
+namespace umbraco.MacroEngines.Razor
+{
+ using System;
+ using System.CodeDom.Compiler;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Linq;
+
+ ///
+ /// Defines an exception that occurs during compilation of a template.
+ ///
+ public class TemplateException : Exception
+ {
+ #region Constructors
+ ///
+ /// Initialises a new instance of
+ ///
+ /// The collection of compilation errors.
+ internal TemplateException(CompilerErrorCollection errors) : base("Unable to compile template.")
+ {
+ var list = new List();
+ foreach (CompilerError error in errors)
+ {
+ list.Add(error);
+ }
+ Errors = new ReadOnlyCollection(list);
+ }
+ #endregion
+
+ #region Properties
+ ///
+ /// Gets the collection of compiler errors.
+ ///
+ public ReadOnlyCollection Errors { get; private set; }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/Razor/VBRazorProvider.cs b/umbraco.MacroEngines.Juno/Razor/VBRazorProvider.cs
new file mode 100644
index 0000000000..a18c388fed
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Razor/VBRazorProvider.cs
@@ -0,0 +1,33 @@
+namespace umbraco.MacroEngines.Razor
+{
+ using System.CodeDom.Compiler;
+ using System.Web.Razor;
+
+ using Microsoft.VisualBasic;
+
+ ///
+ /// Provides a razor provider that supports the VB syntax.
+ ///
+ public class VBRazorProvider : IRazorProvider
+ {
+ #region Methods
+ ///
+ /// Creates a code language service.
+ ///
+ /// Creates a language service.
+ public RazorCodeLanguage CreateLanguageService()
+ {
+ return new VBRazorCodeLanguage();
+ }
+
+ ///
+ /// Creates a .
+ ///
+ /// The a code dom provider.
+ public CodeDomProvider CreateCodeDomProvider()
+ {
+ return new VBCodeProvider();
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/umbraco.MacroEngines.Juno/RazorEngine.cs b/umbraco.MacroEngines.Juno/RazorEngine.cs
new file mode 100644
index 0000000000..b1b96eee68
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/RazorEngine.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Web;
+using umbraco.cms.businesslogic.macro;
+using umbraco.interfaces;
+using umbraco.IO;
+
+namespace umbraco.MacroEngines
+{
+ public class RazorEngine : IMacroEngine
+ {
+ public string Name
+ {
+ get { return "Razor Enggine"; }
+ }
+
+ public List SupportedExtensions
+ {
+ get
+ {
+ var exts = new List { "razor" };
+ return exts;
+ }
+ }
+
+ public Dictionary SupportedProperties
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool Validate(string code, INode currentPage, out string errorMessage)
+ {
+ throw new NotImplementedException();
+ }
+
+ public string Execute(MacroModel macro, INode currentPage)
+ {
+ string result = String.Empty;
+ string template = !String.IsNullOrEmpty(macro.ScriptCode) ? macro.ScriptCode : loadScript(IOHelper.MapPath(SystemDirectories.Python + "/" + macro.ScriptName));
+ try
+ {
+ //TODO: Add caching support
+ // if (CacheTemplate)
+ // result = Razor.Parse(template, new DynamicNode(currentPage), this.ID + "_razorTemplate");
+ // else
+ // {
+ result = Razor.Razor.Parse(template, new DynamicNode(currentPage));
+ }
+ // }
+ catch (Exception ee)
+ {
+ result = string.Format(
+ "Razor Macro Engine
An error occured while rendering the following code:{0}
{1} ",
+ ee.ToString(),
+ HttpContext.Current.Server.HtmlEncode(template));
+ }
+
+ return result;
+ }
+
+ private string loadScript(string scriptName)
+ {
+ if (File.Exists(scriptName))
+ {
+ return File.ReadAllText(scriptName);
+ }
+
+ return String.Empty;
+ }
+ }
+}
diff --git a/umbraco.MacroEngines.Juno/Scripting/MacroScript.cs b/umbraco.MacroEngines.Juno/Scripting/MacroScript.cs
new file mode 100644
index 0000000000..973f949ce6
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Scripting/MacroScript.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Scripting.Hosting;
+
+namespace umbraco.MacroEngines.Scripting
+{
+ public class MacroScript
+ {
+ public static string Execute(string script, string scriptType, Hashtable variables)
+ {
+ MacroScriptEngine mse = new MacroScriptEngine(scriptType);
+ mse.ScriptVariables = ConvertHashTable(variables);
+ mse.Script = script;
+ return mse.Execute();
+ }
+
+ public static string Evaluate(string script, string scriptType, Hashtable variables)
+ {
+ MacroScriptEngine mse = new MacroScriptEngine(scriptType);
+ mse.ScriptVariables = ConvertHashTable(variables);
+ mse.Script = script;
+ return mse.Evaluate();
+ }
+
+ public static string ExecuteFile(string path, Hashtable variables)
+ {
+ string fileEnding = path.Substring(path.LastIndexOf('.')).Trim('.');
+
+ MacroScriptEngine mse = MacroScriptEngine.LoadEngineByFileExtension(fileEnding);
+ mse.ScriptVariables = ConvertHashTable(variables);
+
+ return mse.ExecuteFile(path);
+ }
+
+ //friendly helpers....
+ public static string ExecutePython(string script, Hashtable variables)
+ {
+ return Execute(script, "python", variables);
+ }
+
+ public static string ExecuteRuby(string script, Hashtable variables)
+ {
+ return Execute(script, "ruby", variables);
+ }
+
+ private static SortedDictionary ConvertHashTable(Hashtable ht)
+ {
+ SortedDictionary retval = new SortedDictionary();
+ foreach (DictionaryEntry de in ht)
+ {
+ retval.Add(de.Key.ToString(), de.Value);
+ }
+
+ return retval;
+ }
+
+ public static List GetAvailableLanguages()
+ {
+ return ScriptRuntimeSetup.ReadConfiguration().LanguageSetups.ToList();
+ }
+ }
+}
diff --git a/umbraco.MacroEngines.Juno/Scripting/ScriptEngine.cs b/umbraco.MacroEngines.Juno/Scripting/ScriptEngine.cs
new file mode 100644
index 0000000000..bcec3b5ab8
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/Scripting/ScriptEngine.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Microsoft.Scripting;
+using Microsoft.Scripting.Hosting;
+
+namespace umbraco.MacroEngines.Scripting
+{
+ internal class MacroScriptEngine
+ {
+ ScriptRuntime m_runTime;
+ ScriptEngine m_engine;
+ ExceptionOperations m_exceptionOperations;
+ SortedDictionary m_inputVariables;
+ SortedDictionary m_outputVariables;
+ string m_script;
+ MemoryStream m_output;
+
+ internal MacroScriptEngine() { }
+
+ internal MacroScriptEngine(string scriptType)
+ {
+ loadRunTime();
+ m_engine = m_runTime.GetEngine(scriptType);
+ m_exceptionOperations = m_engine.GetService();
+ }
+
+ internal static MacroScriptEngine LoadEngineByFileExtension(string fileExtension)
+ {
+ MacroScriptEngine mse = new MacroScriptEngine();
+ mse.loadRunTime();
+ mse.m_engine = mse.m_runTime.GetEngineByFileExtension(fileExtension);
+ mse.m_exceptionOperations = mse.m_engine.GetService();
+ return mse;
+ }
+
+ internal static MacroScriptEngine GetEngineByType(string scriptType)
+ {
+ MacroScriptEngine mse = new MacroScriptEngine();
+ mse.loadRunTime();
+ mse.m_engine = mse.m_runTime.GetEngine(scriptType);
+ mse.m_exceptionOperations = mse.m_engine.GetService();
+ return mse;
+ }
+
+ private void loadRunTime()
+ {
+ m_output = new MemoryStream();
+ m_runTime = ScriptRuntime.CreateFromConfiguration();
+
+ m_runTime.IO.SetOutput(m_output, new StreamWriter(m_output));
+ m_runTime.IO.SetErrorOutput(m_output, new StreamWriter(m_output));
+
+ Assembly pluginsAssembly = Assembly.LoadFile(IO.IOHelper.MapPath(IO.SystemDirectories.Bin + "/umbraco.dll"));
+ m_runTime.LoadAssembly(pluginsAssembly);
+
+ m_runTime.LoadAssembly(typeof(String).Assembly);
+ m_runTime.LoadAssembly(typeof(Uri).Assembly);
+ m_runTime.LoadAssembly(typeof(umbraco.presentation.nodeFactory.Node).Assembly);
+ }
+
+
+ internal SortedDictionary ScriptVariables
+ {
+ set { m_inputVariables = value; }
+ }
+
+ internal SortedDictionary OutPutVariables
+ {
+ get { return m_outputVariables; }
+ }
+
+ internal string Script
+ {
+ set { m_script = value; }
+ }
+
+ internal ExceptionOperations ExceptionOperations
+ {
+ get { return m_exceptionOperations; }
+ }
+
+ internal string Evaluate()
+ {
+ //Create structures
+ SourceCodeKind sc = SourceCodeKind.Expression;
+ ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc);
+ ScriptScope scope = m_engine.CreateScope();
+
+ //Fill input variables
+ foreach (KeyValuePair variable in m_inputVariables)
+ {
+ scope.SetVariable(variable.Key, variable.Value);
+ }
+
+ string result = "";
+
+ try
+ {
+ object r = source.Execute(scope);
+
+ if (r != null)
+ result = r.ToString();
+ }
+ catch (Exception e)
+ {
+ umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, e.ToString());
+ result = m_exceptionOperations.FormatException(e);
+ }
+
+ return result;
+ }
+
+ internal string Execute()
+ {
+ SourceCodeKind sc = SourceCodeKind.Statements;
+ ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc);
+ ScriptScope scope = m_engine.CreateScope();
+
+ //Fill input variables
+ foreach (KeyValuePair variable in m_inputVariables)
+ {
+ scope.SetVariable(variable.Key, variable.Value);
+ }
+
+ source.Execute(scope);
+
+ m_outputVariables = new SortedDictionary();
+ foreach (string variable in scope.GetVariableNames())
+ {
+ m_outputVariables.Add(variable, scope.GetVariable(variable));
+ }
+
+ return ReadFromStream(m_output);
+ }
+
+ internal string ExecuteFile(string path)
+ {
+ string rbCode;
+
+ // OpenText will strip the BOM and keep the Unicode intact
+ using (var rdr = File.OpenText(path))
+ {
+ rbCode = rdr.ReadToEnd();
+ }
+
+ m_script = rbCode;
+ return Execute();
+ }
+
+ internal SortedDictionary _Execute()
+ {
+ //Create structures
+ SourceCodeKind sc = SourceCodeKind.Statements;
+ ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc);
+ ScriptScope scope = m_engine.CreateScope();
+
+ //Fill input variables
+ foreach (KeyValuePair variable in m_inputVariables)
+ {
+ scope.SetVariable(variable.Key, variable.Value);
+ }
+
+ SortedDictionary outputVariables = new SortedDictionary();
+ //Execute the script
+ try
+ {
+
+ source.Execute(scope);
+ //Recover variables
+ foreach (string variable in scope.GetVariableNames())
+ {
+ outputVariables.Add(variable, scope.GetVariable(variable));
+ }
+ }
+ catch (Exception e)
+ {
+ string error = m_exceptionOperations.FormatException(e);
+ //Do something with the pretty printed error
+ throw;
+ }
+ return outputVariables;
+ }
+
+ private static string ReadFromStream(MemoryStream ms)
+ {
+ int length = (int)ms.Length;
+ Byte[] bytes = new Byte[length];
+
+ ms.Seek(0, SeekOrigin.Begin);
+ ms.Read(bytes, 0, (int)ms.Length);
+
+ return Encoding.GetEncoding("utf-8").GetString(bytes, 0, (int)ms.Length);
+ }
+ }
+}
diff --git a/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj b/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj
new file mode 100644
index 0000000000..2aa193c95f
--- /dev/null
+++ b/umbraco.MacroEngines.Juno/umbraco.MacroEngines.csproj
@@ -0,0 +1,96 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {89C09045-1064-466B-B94A-DB3AFE2A5853}
+ Library
+ Properties
+ umbraco.MacroEngines
+ umbraco.MacroEngines
+ v4.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\foreign dlls\DLR 4.0\Microsoft.Scripting.dll
+
+
+
+
+
+ False
+ ..\foreign dlls\System.Web.Razor.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {E469A9CE-1BEC-423F-AC44-713CD72457EA}
+ umbraco.businesslogic
+
+
+ {CCD75EC3-63DB-4184-B49D-51C1DD337230}
+ umbraco.cms
+
+
+ {511F6D8D-7717-440A-9A57-A507E9A8B27F}
+ umbraco.interfaces
+
+
+ {651E1350-91B6-44B7-BD60-7207006D7003}
+ umbraco.presentation
+
+
+
+
+ xcopy "$(TargetPath)" "$(SolutionDir)\umbraco\presentation\bin" /Y
+xcopy "$(SolutionDir)foreign dlls\System.Web.Razor.dll" "$(SolutionDir)\umbraco\presentation\bin" /Y
+
+
+
\ No newline at end of file
diff --git a/umbraco.MacroEngines/DLRScriptingEngine.cs b/umbraco.MacroEngines/DLRScriptingEngine.cs
index f9a5e01e21..f406d08844 100644
--- a/umbraco.MacroEngines/DLRScriptingEngine.cs
+++ b/umbraco.MacroEngines/DLRScriptingEngine.cs
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using umbraco.cms.businesslogic.macro;
using umbraco.interfaces;
using umbraco.IO;
-using umbraco.MacroEngines.Scripting;
+using umbraco.MacroEngines.Legacy.Scripting;
-namespace umbraco.MacroEngines
+namespace umbraco.MacroEngines.Legacy
{
public class DLRScriptingEngine : IMacroEngine
{
diff --git a/umbraco.MacroEngines/Scripting/MacroScript.cs b/umbraco.MacroEngines/Scripting/MacroScript.cs
index 973f949ce6..a5575a5ae9 100644
--- a/umbraco.MacroEngines/Scripting/MacroScript.cs
+++ b/umbraco.MacroEngines/Scripting/MacroScript.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using Microsoft.Scripting.Hosting;
-namespace umbraco.MacroEngines.Scripting
+namespace umbraco.MacroEngines.Legacy.Scripting
{
public class MacroScript
{
diff --git a/umbraco.MacroEngines/Scripting/ScriptEngine.cs b/umbraco.MacroEngines/Scripting/ScriptEngine.cs
index bcec3b5ab8..c0f97c3f60 100644
--- a/umbraco.MacroEngines/Scripting/ScriptEngine.cs
+++ b/umbraco.MacroEngines/Scripting/ScriptEngine.cs
@@ -7,7 +7,7 @@ using System.Text;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
-namespace umbraco.MacroEngines.Scripting
+namespace umbraco.MacroEngines.Legacy.Scripting
{
internal class MacroScriptEngine
{
diff --git a/umbraco.MacroEngines/umbraco.MacroEngines.csproj b/umbraco.MacroEngines/umbraco.MacroEngines.Legacy.csproj
similarity index 93%
rename from umbraco.MacroEngines/umbraco.MacroEngines.csproj
rename to umbraco.MacroEngines/umbraco.MacroEngines.Legacy.csproj
index 76dd19286e..75b5b8d5a9 100644
--- a/umbraco.MacroEngines/umbraco.MacroEngines.csproj
+++ b/umbraco.MacroEngines/umbraco.MacroEngines.Legacy.csproj
@@ -8,9 +8,9 @@
{6AE67079-2C00-476C-81DE-2800D1AC14BC}
Library
Properties
- umbraco.MacroEngines
- umbraco.MacroEngines
- v3.5
+ umbraco.MacroEngines.Legacy
+ umbraco.MacroEngines.Legacy
+ v4.0
512
SAK
SAK
diff --git a/umbraco.sln b/umbraco.sln
index 8c441a1420..0dccbb9cdf 100644
--- a/umbraco.sln
+++ b/umbraco.sln
@@ -105,7 +105,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{194009
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlCE4Umbraco", "components\SQLCE4Umbraco\SqlCE4Umbraco.csproj", "{5BA5425F-27A7-4677-865E-82246498AA2E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.MacroEngines", "umbraco.MacroEngines\umbraco.MacroEngines.csproj", "{6AE67079-2C00-476C-81DE-2800D1AC14BC}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.MacroEngines.Legacy", "umbraco.MacroEngines\umbraco.MacroEngines.Legacy.csproj", "{6AE67079-2C00-476C-81DE-2800D1AC14BC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.MacroEngines", "umbraco.MacroEngines.Juno\umbraco.MacroEngines.csproj", "{89C09045-1064-466B-B94A-DB3AFE2A5853}"
EndProject
Global
GlobalSection(TeamFoundationVersionControl) = preSolution
@@ -221,9 +223,12 @@ Global
{5BA5425F-27A7-4677-865E-82246498AA2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BA5425F-27A7-4677-865E-82246498AA2E}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE67079-2C00-476C-81DE-2800D1AC14BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6AE67079-2C00-476C-81DE-2800D1AC14BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE67079-2C00-476C-81DE-2800D1AC14BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AE67079-2C00-476C-81DE-2800D1AC14BC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {89C09045-1064-466B-B94A-DB3AFE2A5853}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {89C09045-1064-466B-B94A-DB3AFE2A5853}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {89C09045-1064-466B-B94A-DB3AFE2A5853}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {89C09045-1064-466B-B94A-DB3AFE2A5853}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE