Files
Umbraco-CMS/src/Umbraco.Web/UI/JavaScript/JsInitialization.cs

130 lines
5.3 KiB
C#
Raw Normal View History

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
{
/// <summary>
/// Reads from all defined manifests and ensures that any of their initialization is output with the
/// main Umbraco initialization output.
/// </summary>
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);
/// <summary>
/// Processes all found manifest files and outputs the main.js file containing all plugin manifests
/// </summary>
public string GetJavascriptInitialization(HttpContextBase httpContext, JArray umbracoInit, JArray additionalJsFiles = null)
{
var result = GetJavascriptInitializationArray(httpContext, umbracoInit, additionalJsFiles);
var noCache = Resources.JsNoCache;
//if debugging, add timestamp, if in production we tell yepNope to append umb+cdf version
//this is needed even tho cdf does this on its serverside merged js
//as assetsService.load() also need to append these versions to ensure cache bursting on updates + pack installs
if (httpContext.IsDebuggingEnabled)
noCache = noCache.Replace("##rnd##", "(new Date).getTime()");
else
{
//create a unique hash code of the current umb version and the current cdf version
var versionHash = UrlHelperExtensions.GetCacheBustHash();
var version = "'" + versionHash + "'";
noCache = noCache.Replace("##rnd##", version);
}
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 = CheckIfReleaseAndOptimized(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;
}
/// <summary>
/// Returns the default config as a JArray
/// </summary>
/// <returns></returns>
internal static JArray GetDefaultInitialization()
{
var init = Resources.JsInitialize;
var deserialized = JsonConvert.DeserializeObject<JArray>(init);
var result = new JArray();
foreach (var j in deserialized.Where(j => j.Type == JTokenType.String))
{
result.Add(j);
}
return result;
}
/// <summary>
/// Parses the JsResources.Main and replaces the replacement tokens accordingly.
/// </summary>
/// <param name="replacements"></param>
/// <returns></returns>
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;
});
}
}
}