using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.RegularExpressions; using System.Web; using ClientDependency.Core; using ClientDependency.Core.Config; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Manifest; using System.Linq; 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; } //used to strip comments internal static readonly Regex Comments = new Regex("(/\\*.*\\*/)", RegexOptions.Compiled); //used for dealing with js functions inside of json (which is not a supported json syntax) private const string PrefixJavaScriptObject = "@@@@"; private static readonly Regex JsFunctionParser = new Regex(string.Format("(\"{0}(.*?)\")+", PrefixJavaScriptObject), RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled); //used to replace the 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, JArray umbracoInit, JArray additionalJsFiles = null) { var result = GetJavascriptInitializationArray(httpContext, umbracoInit, additionalJsFiles); return ParseMain( result.ToString(), IOHelper.ResolveUrl(SystemDirectories.Umbraco)); } public JArray GetJavascriptInitializationArray(HttpContextBase httpContext, JArray umbracoInit, JArray additionalJsFiles = null) { foreach (var m in _parser.GetManifests()) { ManifestParser.MergeJArrays(umbracoInit, m.JavaScriptInitialize); } //merge in the additional ones specified if there are any if (additionalJsFiles != null) { ManifestParser.MergeJArrays(umbracoInit, additionalJsFiles); } //now we can optimize if in release mode umbracoInit = OptimizeAssetCollection(umbracoInit, ClientDependencyType.Javascript, httpContext); //now we need to merge in any found cdf declarations on property editors ManifestParser.MergeJArrays(umbracoInit, ScanPropertyEditors(ClientDependencyType.Javascript, httpContext)); return umbracoInit; } /// /// Returns the default config as a JArray /// /// internal static JArray GetDefaultInitialization() { var init = Resources.JsInitialize; var deserialized = JsonConvert.DeserializeObject(init); var result = new JArray(); foreach (var j in deserialized.Where(j => j.Type == JTokenType.String)) { result.Add(j); } return result; } /// /// Parses the JsResources.Main and replaces the replacement tokens accordingly. /// /// /// internal static string ParseMain(params string[] replacements) { var count = 0; return Token.Replace(Resources.Main, match => { var replaced = replacements[count]; //we need to cater for the special syntax when we have js function() objects contained in the json var jsFunctionParsed = JsFunctionParser.Replace(replaced, "$2"); count++; return jsFunctionParsed; }); } } }