diff --git a/src/Umbraco.Core/Assets/JavascriptFile.cs b/src/Umbraco.Core/Assets/JavascriptFile.cs
index 477c8eabab..51d4a26d82 100644
--- a/src/Umbraco.Core/Assets/JavascriptFile.cs
+++ b/src/Umbraco.Core/Assets/JavascriptFile.cs
@@ -7,9 +7,9 @@ namespace Umbraco.Core.Assets
///
/// Represents a JS asset file
///
- public class JavascriptFile : AssetFile
+ public class JavaScriptFile : AssetFile
{
- public JavascriptFile(string filePath)
+ public JavaScriptFile(string filePath)
: base(AssetType.Javascript)
{
FilePath = filePath;
diff --git a/src/Umbraco.Tests/Web/AngularIntegration/JsInitializationTests.cs b/src/Umbraco.Tests/Web/AngularIntegration/JsInitializationTests.cs
index c4b5e3247b..71e7963d61 100644
--- a/src/Umbraco.Tests/Web/AngularIntegration/JsInitializationTests.cs
+++ b/src/Umbraco.Tests/Web/AngularIntegration/JsInitializationTests.cs
@@ -2,6 +2,7 @@
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web.JavaScript;
+using Umbraco.Web.JavaScript.CDF;
namespace Umbraco.Tests.Web.AngularIntegration
{
@@ -19,7 +20,7 @@ namespace Umbraco.Tests.Web.AngularIntegration
[Test]
public void Parse_Main()
{
- var result = JsInitialization.WriteScript("[World]", "Hello", "Blah");
+ var result = JavaScriptHelper.WriteScript("[World]", "Hello", "Blah");
Assert.AreEqual(@"LazyLoad.js([World], function () {
//we need to set the legacy UmbClientMgr path
diff --git a/src/Umbraco.Web/Editors/PreviewController.cs b/src/Umbraco.Web/Editors/PreviewController.cs
index b1f9d15feb..93c7da9962 100644
--- a/src/Umbraco.Web/Editors/PreviewController.cs
+++ b/src/Umbraco.Web/Editors/PreviewController.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
@@ -14,7 +13,6 @@ using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Features;
using Umbraco.Web.JavaScript;
-using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Trees;
@@ -103,8 +101,8 @@ namespace Umbraco.Web.Editors
[OutputCache(Order = 1, VaryByParam = "none", Location = OutputCacheLocation.Server, Duration = 5000)]
public JavaScriptResult Application()
{
- var files = JsInitialization.OptimizeScriptFiles(HttpContext, JsInitialization.GetPreviewInitialization(), _runtimeMinifier);
- var result = JsInitialization.GetJavascriptInitialization(HttpContext, files, "umbraco.preview", _globalSettings, _ioHelper);
+ var files = JavaScriptHelper.OptimizeScriptFiles(HttpContext, JavaScriptHelper.GetPreviewInitialization(), _runtimeMinifier);
+ var result = JavaScriptHelper.GetJavascriptInitialization(HttpContext, files, "umbraco.preview", _globalSettings, _ioHelper);
return JavaScript(result);
}
diff --git a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs
index 3fa6b604d5..2093984e54 100644
--- a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs
+++ b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs
@@ -130,7 +130,7 @@ namespace Umbraco.Web
public static IHtmlString AngularValueTinyMceAssets(this HtmlHelper html, IRuntimeMinifier runtimeMinifier)
{
var ctx = new HttpContextWrapper(HttpContext.Current);
- var files = JsInitialization.OptimizeTinyMceScriptFiles(ctx, runtimeMinifier);
+ var files = JavaScriptHelper.OptimizeTinyMceScriptFiles(ctx, runtimeMinifier);
var sb = new StringBuilder();
diff --git a/src/Umbraco.Web/JavaScript/JavaScriptHelper.cs b/src/Umbraco.Web/JavaScript/JavaScriptHelper.cs
new file mode 100644
index 0000000000..d42526be05
--- /dev/null
+++ b/src/Umbraco.Web/JavaScript/JavaScriptHelper.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Web;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Umbraco.Core;
+using Umbraco.Core.Assets;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.IO;
+using Umbraco.Core.Runtime;
+using CssFile = Umbraco.Core.Assets.CssFile;
+
+namespace Umbraco.Web.JavaScript
+{
+ public class JavaScriptHelper
+ {
+ // deal with javascript functions inside of json (not a supported json syntax)
+ private const string PrefixJavaScriptObject = "@@@@";
+ private static readonly Regex JsFunctionParser = new Regex($"(\"{PrefixJavaScriptObject}(.*?)\")+",
+ RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled);
+
+ // replace tokens in the js main
+ private static readonly Regex Token = new Regex("(\"##\\w+?##\")", RegexOptions.Compiled);
+
+
+ ///
+ /// Gets the JS initialization script to boot the back office application
+ ///
+ ///
+ ///
+ ///
+ /// The angular module name to boot
+ ///
+ ///
+ public static string GetJavascriptInitialization(HttpContextBase httpContext, IEnumerable scripts, string angularModule, IGlobalSettings globalSettings, IIOHelper ioHelper)
+ {
+ var jarray = new StringBuilder();
+ jarray.AppendLine("[");
+ var first = true;
+ foreach (var file in scripts)
+ {
+ if (first) first = false;
+ else jarray.AppendLine(",");
+ jarray.Append("\"");
+ jarray.Append(file);
+ jarray.Append("\"");
+
+ }
+ jarray.Append("]");
+
+ return WriteScript(jarray.ToString(), ioHelper.ResolveUrl(globalSettings.UmbracoPath), angularModule);
+ }
+
+ ///
+ /// Parses the JsResources.Main and replaces the replacement tokens accordingly
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal static string WriteScript(string scripts, string umbracoPath, string angularModule)
+ {
+ var count = 0;
+ var replacements = new[] { scripts, umbracoPath, angularModule };
+ // replace, catering for the special syntax when we have
+ // js function() objects contained in the json
+
+ return Token.Replace(Resources.Main, match =>
+ {
+ var replacement = replacements[count++];
+ return JsFunctionParser.Replace(replacement, "$2");
+ });
+ }
+
+ internal static IEnumerable GetTinyMceInitialization()
+ {
+ var resources = JsonConvert.DeserializeObject(Resources.TinyMceInitialize);
+ return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
+ }
+
+ internal static IEnumerable OptimizeTinyMceScriptFiles(HttpContextBase httpContext, IRuntimeMinifier runtimeMinifier)
+ {
+ return OptimizeScriptFiles(httpContext, GetTinyMceInitialization(), runtimeMinifier);
+ }
+
+
+ ///
+ /// Returns the default config as a JArray
+ ///
+ ///
+ internal static IEnumerable GetPreviewInitialization()
+ {
+ var resources = JsonConvert.DeserializeObject(Resources.PreviewInitialize);
+ return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
+ }
+
+
+ ///
+ /// Returns a list of optimized script paths
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Used to cache bust and optimize script paths
+ ///
+ public static IEnumerable OptimizeScriptFiles(HttpContextBase httpContext, IEnumerable scriptFiles, IRuntimeMinifier runtimeMinifier)
+ {
+ var scripts = new HashSet();
+ foreach (var script in scriptFiles)
+ scripts.Add(script);
+
+ scripts = new HashSet(OptimizeAssetCollection(scripts, AssetType.Javascript, httpContext, runtimeMinifier));
+
+ return scripts.ToArray();
+ }
+
+ internal static IEnumerable OptimizeAssetCollection(IEnumerable assets, AssetType assetType, HttpContextBase httpContext, IRuntimeMinifier runtimeMinifier)
+ {
+ if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
+
+ var requestUrl = httpContext.Request.Url;
+ if (requestUrl == null) throw new ArgumentException("HttpContext.Request.Url is null.", nameof(httpContext));
+
+ var dependencies = assets.Where(x => x.IsNullOrWhiteSpace() == false).Select(x =>
+ {
+ // most declarations with be made relative to the /umbraco folder, so things
+ // like lib/blah/blah.js so we need to turn them into absolutes here
+ if (x.StartsWith("/") == false && Uri.IsWellFormedUriString(x, UriKind.Relative))
+ {
+ return new AssetFile(assetType) { FilePath = new Uri(requestUrl, x).AbsolutePath };
+ }
+
+ return assetType == AssetType.Javascript
+ ? new JavaScriptFile(x)
+ : new CssFile(x) as IAssetFile;
+ }).ToList();
+
+
+ return runtimeMinifier.GetAssetPaths(assetType, dependencies);;
+ }
+ }
+}