using System.Collections.Generic; using System.Text.RegularExpressions; using System.Web; using ClientDependency.Core; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.IO; using Umbraco.Core.Manifest; using System.Linq; using System.Text; namespace Umbraco.Web.UI.JavaScript { /// /// Reads from all defined manifests and ensures that any of their initialization is output with the /// main Umbraco initialization output. /// internal class JsInitialization : AssetInitialization { private readonly ManifestParser _parser; public JsInitialization(ManifestParser parser) { _parser = parser; } // 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); /// /// Processes all found manifest files and outputs the main.js file containing all plugin manifests /// public string GetJavascriptInitialization(HttpContextBase httpContext, IEnumerable umbracoInit, IEnumerable additionalJsFiles = null) { var files = GetScriptFiles(httpContext, umbracoInit, additionalJsFiles); var jarray = new StringBuilder(); jarray.AppendLine("["); var first = true; foreach (var file in files) { if (first) first = false; else jarray.AppendLine(","); jarray.Append("\""); jarray.Append(file); jarray.Append("\""); } jarray.Append("]"); return WriteScript(jarray.ToString(), IOHelper.ResolveUrl(SystemDirectories.Umbraco)); } public IEnumerable GetScriptFiles(HttpContextBase httpContext, IEnumerable umbracoInit, IEnumerable additionalJsFiles = null) { var scripts = new HashSet(); foreach (var script in umbracoInit) scripts.Add(script); foreach (var script in _parser.Manifest.Scripts) scripts.Add(script); if (additionalJsFiles != null) foreach (var script in additionalJsFiles) scripts.Add(script); scripts = new HashSet(OptimizeAssetCollection(scripts, ClientDependencyType.Javascript, httpContext)); foreach (var script in ScanPropertyEditors(ClientDependencyType.Javascript, httpContext)) scripts.Add(script); return scripts.ToArray(); } /// /// Returns the default config as a JArray /// /// internal static IEnumerable GetDefaultInitialization() { var resources = JsonConvert.DeserializeObject(Resources.JsInitialize); return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString()); } /// /// Parses the JsResources.Main and replaces the replacement tokens accordingly. /// /// /// internal static string WriteScript(params string[] replacements) { var count = 0; // 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"); }); } } }