Removes unneeded methods/properties in abstraction, removes unneeded usages of it, changes everything to pre-defined bundles, fixes cdf implementation and reduces reflection, renames namespace

This commit is contained in:
Shannon
2020-04-02 17:41:00 +11:00
parent e42c63693f
commit 32deaa12d2
57 changed files with 766 additions and 830 deletions
-45
View File
@@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Umbraco.Core.Assets
{
/// <summary>
/// Represents a dependency file
/// </summary>
[DebuggerDisplay("Type: {DependencyType}, File: {FilePath}")]
public class AssetFile : IAssetFile
{
#region IAssetFile Members
public string FilePath { get; set; }
public AssetType DependencyType { get; }
public int Priority { get; set; }
public int Group { get; set; }
public string PathNameAlias { get; set; }
public string ForceProvider { get; set; }
public string Bundle { get; }
/// <summary>
/// Used to store additional attributes in the HTML markup for the item
/// </summary>
/// <remarks>
/// Mostly used for CSS Media, but could be for anything
/// </remarks>
public IDictionary<string, string> HtmlAttributes { get; }
#endregion
public AssetFile(AssetType type, string bundleName = "unspecfed")
{
DependencyType = type;
HtmlAttributes = new Dictionary<string, string>();
// Set to 100 for the case when a developer doesn't specify a priority it will come after all other dependencies that
// have unless the priority is explicitly set above 100.
Priority = 100;
//Unless a group is specified, all dependencies will go into the same, default, group.
Group = 100;
Bundle = bundleName;
}
}
}
-16
View File
@@ -1,16 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.Assets
{
public interface IAssetFile
{
string FilePath { get; set; }
AssetType DependencyType { get; }
int Priority { get; set; }
int Group { get; set; }
string PathNameAlias { get; set; }
string ForceProvider { get; set; }
string Bundle { get; }
IDictionary<string, string> HtmlAttributes { get; }
}
}
@@ -1,31 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Umbraco.Core.Assets;
namespace Umbraco.Core.Runtime
{
public interface IRuntimeMinifier
{
string GetHashValue { get; }
//return type HtmlHelper
void RequiresCss(string bundleName, params string[] filePaths);
//return type IHtmlString
//IClientDependencyPath[]
string RenderCssHere(string bundleName);
// return type HtmlHelper
void RequiresJs(string bundleName, params string[] filePaths);
// return type IHtmlString
string RenderJsHere(string bundleName);
Task<IEnumerable<string>> GetAssetPathsAsync(AssetType assetType, List<IAssetFile> attributes);
Task<string> MinifyAsync(string fileContent, AssetType assetType);
void Reset();
Task<string> GetScriptForBackOfficeAsync();
Task<IEnumerable<string>> GetAssetListAsync();
}
}
+23
View File
@@ -0,0 +1,23 @@
using System.Diagnostics;
namespace Umbraco.Core.WebAssets
{
/// <summary>
/// Represents a dependency file
/// </summary>
[DebuggerDisplay("Type: {DependencyType}, File: {FilePath}")]
public class AssetFile : IAssetFile
{
#region IAssetFile Members
public string FilePath { get; set; }
public AssetType DependencyType { get; }
#endregion
public AssetFile(AssetType type)
{
DependencyType = type;
}
}
}
@@ -1,4 +1,4 @@
namespace Umbraco.Core.Assets
namespace Umbraco.Core.WebAssets
{
public enum AssetType
{
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Umbraco.Core.Assets
namespace Umbraco.Core.WebAssets
{
/// <summary>
/// Represents a CSS asset file
+8
View File
@@ -0,0 +1,8 @@
namespace Umbraco.Core.WebAssets
{
public interface IAssetFile
{
string FilePath { get; set; }
AssetType DependencyType { get; }
}
}
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Umbraco.Core.WebAssets
{
/// <summary>
/// Used for bundling and minifying web assets at runtime
/// </summary>
public interface IRuntimeMinifier
{
/// <summary>
/// Returns the cache buster value
/// </summary>
string CacheBuster { get; }
/// <summary>
/// Creates a css bundle
/// </summary>
/// <param name="bundleName"></param>
/// <param name="filePaths"></param>
void CreateCssBundle(string bundleName, params string[] filePaths);
/// <summary>
/// Renders the html link tag for the bundle
/// </summary>
/// <param name="bundleName"></param>
/// <returns>
/// An html encoded string
/// </returns>
string RenderCssHere(string bundleName);
/// <summary>
/// Creates a JS bundle
/// </summary>
/// <param name="bundleName"></param>
/// <param name="filePaths"></param>
void CreateJsBundle(string bundleName, params string[] filePaths);
/// <summary>
/// Renders the html script tag for the bundle
/// </summary>
/// <param name="bundleName"></param>
/// <returns>
/// An html encoded string
/// </returns>
string RenderJsHere(string bundleName);
/// <summary>
/// Returns the asset paths for the bundle name
/// </summary>
/// <param name="bundleName"></param>
/// <returns>
/// If debug mode is enabled this will return all asset paths (not bundled), else it will return a bundle URL
/// </returns>
Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName);
Task<string> MinifyAsync(string fileContent, AssetType assetType);
void Reset();
}
}
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Umbraco.Core.Assets
namespace Umbraco.Core.WebAssets
{
/// <summary>
/// Represents a JS asset file
@@ -1,34 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Assets;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Runtime;
using Umbraco.Web.PropertyEditors;
namespace Umbraco.Web.JavaScript
{
public abstract class AssetInitialization
{
private readonly IRuntimeMinifier _runtimeMinifier;
private readonly PropertyEditorCollection _propertyEditorCollection;
public AssetInitialization(IRuntimeMinifier runtimeMinifier, PropertyEditorCollection propertyEditorCollection)
{
_runtimeMinifier = runtimeMinifier;
_propertyEditorCollection = propertyEditorCollection;
}
protected async Task<IEnumerable<string>> ScanPropertyEditorsAsync(AssetType assetType)
{
var attributes = _propertyEditorCollection
.SelectMany(x => x.GetType().GetCustomAttributes<PropertyEditorAssetAttribute>(false))
.Where(x => x.AssetType == assetType)
.Select(x => x.DependencyFile)
.ToList();
return await _runtimeMinifier.GetAssetPathsAsync(assetType, attributes);
}
}
}
@@ -1,60 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Assets;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Runtime;
namespace Umbraco.Web.JavaScript
{
public class CssInitialization : AssetInitialization
{
private readonly IManifestParser _parser;
private readonly IRuntimeMinifier _runtimeMinifier;
public CssInitialization(
IManifestParser parser,
IRuntimeMinifier runtimeMinifier,
PropertyEditorCollection propertyEditorCollection)
: base(runtimeMinifier, propertyEditorCollection)
{
_parser = parser;
_runtimeMinifier = runtimeMinifier;
}
/// <summary>
/// Processes all found manifest files, and outputs css inject calls for all css files found in all manifests.
/// </summary>
public async Task<string> GetStylesheetInitializationAsync(Uri requestUrl)
{
var files = await GetStylesheetFilesAsync(requestUrl);
return WriteScript(files);
}
public async Task<IEnumerable<string>> GetStylesheetFilesAsync(Uri requestUrl)
{
var stylesheets = new HashSet<string>();
var optimizedManifest = await JavaScriptHelper.OptimizeAssetCollectionAsync(_parser.Manifest.Stylesheets, AssetType.Css, requestUrl, _runtimeMinifier);
foreach (var stylesheet in optimizedManifest)
stylesheets.Add(stylesheet);
foreach (var stylesheet in await ScanPropertyEditorsAsync(AssetType.Css))
stylesheets.Add(stylesheet);
return stylesheets.ToArray();
}
internal static string WriteScript(IEnumerable<string> files)
{
var sb = new StringBuilder();
foreach (var file in files)
sb.AppendFormat("{0}LazyLoad.css('{1}');", Environment.NewLine, file);
return sb.ToString();
}
}
}
@@ -1,143 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
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 Umbraco.Infrastructure.RuntimeMinification;
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);
/// <summary>
/// Gets the JS initialization script to boot the back office application
/// </summary>
/// <param name="scripts"></param>
/// <param name="angularModule">
/// The angular module name to boot
/// </param>
/// <returns></returns>
public static string GetJavascriptInitialization(IEnumerable<string> 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);
}
/// <summary>
/// Parses the JsResources.Main and replaces the replacement tokens accordingly
/// </summary>
/// <param name="scripts"></param>
/// <param name="umbracoPath"></param>
/// <param name="angularModule"></param>
/// <returns></returns>
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<string> GetTinyMceInitialization()
{
var resources = JsonConvert.DeserializeObject<JArray>(Resources.TinyMceInitialize);
return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
}
public static async Task<IEnumerable<string>> OptimizeTinyMceScriptFilesAsync(Uri requestUrl, IRuntimeMinifier runtimeMinifier)
{
return await OptimizeScriptFilesAsync(requestUrl, GetTinyMceInitialization(), runtimeMinifier);
}
/// <summary>
/// Returns the default config as a JArray
/// </summary>
/// <returns></returns>
public static IEnumerable<string> GetPreviewInitialization()
{
var resources = JsonConvert.DeserializeObject<JArray>(Resources.PreviewInitialize);
return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
}
/// <summary>
/// Returns a list of optimized script paths
/// </summary>
/// <param name="requestUrl"></param>
/// <param name="scriptFiles"></param>
/// <param name="runtimeMinifier"></param>
/// <returns></returns>
/// <remarks>
/// Used to cache bust and optimize script paths
/// </remarks>
public static async Task<IEnumerable<string>> OptimizeScriptFilesAsync(Uri requestUrl, IEnumerable<string> scriptFiles, IRuntimeMinifier runtimeMinifier)
{
var scripts = new HashSet<string>();
foreach (var script in scriptFiles)
scripts.Add(script);
scripts = new HashSet<string>(await OptimizeAssetCollectionAsync(scripts, AssetType.Javascript, requestUrl, runtimeMinifier));
return scripts.ToArray();
}
internal static async Task<IEnumerable<string>> OptimizeAssetCollectionAsync(IEnumerable<string> assets, AssetType assetType, Uri requestUrl, IRuntimeMinifier runtimeMinifier)
{
if (requestUrl == null) throw new ArgumentNullException(nameof(requestUrl));
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 await runtimeMinifier.GetAssetPathsAsync(assetType, dependencies);
}
}
}
@@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Assets;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Runtime;
using Umbraco.Infrastructure.RuntimeMinification;
namespace Umbraco.Web.JavaScript
{
/// <summary>
/// Reads from all defined manifests and ensures that any of their initialization is output with the
/// main Umbraco initialization output.
/// </summary>
public class JsInitialization : AssetInitialization
{
private readonly IManifestParser _parser;
private readonly IRuntimeMinifier _runtimeMinifier;
public JsInitialization(IManifestParser parser, IRuntimeMinifier runtimeMinifier, PropertyEditorCollection propertyEditorCollection) : base(runtimeMinifier, propertyEditorCollection)
{
_parser = parser;
_runtimeMinifier = runtimeMinifier;
}
/// <summary>
/// Returns a list of optimized script paths for the back office
/// </summary>
/// <param name="requestUrl"></param>
/// <param name="umbracoInit"></param>
/// <param name="additionalJsFiles"></param>
/// <returns>
/// Cache busted/optimized script paths for the back office including manifest and property editor scripts
/// </returns>
/// <remarks>
/// Used to cache bust and optimize script paths for the back office
/// </remarks>
public async Task<IEnumerable<string>> OptimizeBackOfficeScriptFilesAsync(Uri requestUrl, IEnumerable<string> umbracoInit, IEnumerable<string> additionalJsFiles = null)
{
var scripts = new HashSet<string>();
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<string>(await JavaScriptHelper.OptimizeAssetCollectionAsync(scripts, AssetType.Javascript, requestUrl, _runtimeMinifier));
foreach (var script in await ScanPropertyEditorsAsync(AssetType.Javascript))
scripts.Add(script);
return scripts.ToArray();
}
/// <summary>
/// Returns the default config as a JArray
/// </summary>
/// <returns></returns>
public static IEnumerable<string> GetDefaultInitialization()
{
var resources = JsonConvert.DeserializeObject<JArray>(Resources.JsInitialize);
return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
}
}
}
@@ -43,20 +43,20 @@
<ItemGroup>
<Compile Remove="obj\**" />
<Compile Update="RuntimeMinification\Resources.Designer.cs">
<Compile Update="WebAssets\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources2.resx</DependentUpon>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="obj\**" />
<EmbeddedResource Include="RuntimeMinification\JsInitialize.js" />
<EmbeddedResource Include="RuntimeMinification\Main.js" />
<EmbeddedResource Include="RuntimeMinification\PreviewInitialize.js" />
<EmbeddedResource Include="RuntimeMinification\ServerVariables.js" />
<EmbeddedResource Update="RuntimeMinification\Resources.resx">
<EmbeddedResource Include="WebAssets\JsInitialize.js" />
<EmbeddedResource Include="WebAssets\Main.js" />
<EmbeddedResource Include="WebAssets\PreviewInitialize.js" />
<EmbeddedResource Include="WebAssets\ServerVariables.js" />
<EmbeddedResource Update="WebAssets\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Hosting;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.WebAssets;
using Umbraco.Infrastructure.WebAssets;
using Umbraco.Web.PropertyEditors;
namespace Umbraco.Web.JavaScript
{
public class BackOfficeWebAssets
{
public const string UmbracoPreviewJsBundleName = "umbraco-preview-js";
public const string UmbracoPreviewCssBundleName = "umbraco-preview-css";
public const string UmbracoCssBundleName = "umbraco-backoffice-css";
public const string UmbracoInitCssBundleName = "umbraco-backoffice-init-css";
public const string UmbracoJsBundleName = "umbraco-backoffice-js";
public const string UmbracoTinyMceJsBundleName = "umbraco-tinymce-js";
public const string UmbracoUpgradeCssBundleName = "umbraco-authorize-upgrade-css";
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IRuntimeMinifier _runtimeMinifier;
private readonly IManifestParser _parser;
private readonly PropertyEditorCollection _propertyEditorCollection;
public BackOfficeWebAssets(
IHostingEnvironment hostingEnvironment,
IRuntimeMinifier runtimeMinifier,
IManifestParser parser,
PropertyEditorCollection propertyEditorCollection)
{
_hostingEnvironment = hostingEnvironment;
_runtimeMinifier = runtimeMinifier;
_parser = parser;
_propertyEditorCollection = propertyEditorCollection;
}
public void CreateBundles()
{
// Create bundles
_runtimeMinifier.CreateCssBundle(UmbracoInitCssBundleName,
"lib/bootstrap-social/bootstrap-social.css",
"assets/css/umbraco.css",
"lib/font-awesome/css/font-awesome.min.css");
_runtimeMinifier.CreateCssBundle(UmbracoUpgradeCssBundleName,
"assets/css/umbraco.css",
"lib/bootstrap-social/bootstrap-social.css",
"lib/font-awesome/css/font-awesome.min.css");
_runtimeMinifier.CreateCssBundle(UmbracoPreviewCssBundleName,
"assets/css/canvasdesigner.css");
_runtimeMinifier.CreateJsBundle(UmbracoPreviewJsBundleName,
GetScriptsForPreview().ToArray());
_runtimeMinifier.CreateJsBundle(UmbracoTinyMceJsBundleName,
GetScriptsForTinyMce().ToArray());
var propertyEditorAssets = ScanPropertyEditors().GroupBy(x => x.AssetType);
foreach (var assetGroup in propertyEditorAssets)
{
switch (assetGroup.Key)
{
case AssetType.Javascript:
_runtimeMinifier.CreateJsBundle(
UmbracoJsBundleName,
GetScriptsForBackoffice(assetGroup.Select(x => x.FilePath)).ToArray());
break;
case AssetType.Css:
_runtimeMinifier.CreateCssBundle(
UmbracoCssBundleName,
GetStylesheetsForBackoffice(assetGroup.Select(x => x.FilePath)).ToArray());
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
/// <summary>
/// Returns scripts used to load the back office
/// </summary>
/// <returns></returns>
private IEnumerable<string> GetScriptsForBackoffice(IEnumerable<string> propertyEditorScripts)
{
var umbracoInit = JsInitialization.GetDefaultInitialization();
var scripts = new HashSet<string>();
foreach (var script in umbracoInit)
scripts.Add(script);
foreach (var script in _parser.Manifest.Scripts)
scripts.Add(script);
foreach (var script in propertyEditorScripts)
scripts.Add(script);
return new HashSet<string>(FormatPaths(scripts));
}
/// <summary>
/// Returns stylesheets used to load the back office
/// </summary>
/// <returns></returns>
private IEnumerable<string> GetStylesheetsForBackoffice(IEnumerable<string> propertyEditorStyles)
{
var stylesheets = new HashSet<string>();
foreach (var script in _parser.Manifest.Stylesheets)
stylesheets.Add(script);
foreach (var stylesheet in propertyEditorStyles)
stylesheets.Add(stylesheet);
return new HashSet<string>(FormatPaths(stylesheets));
}
/// <summary>
/// Returns the scripts used for tinymce
/// </summary>
/// <returns></returns>
private IEnumerable<string> GetScriptsForTinyMce()
{
var resources = JsonConvert.DeserializeObject<JArray>(Resources.TinyMceInitialize);
return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
}
/// <summary>
/// Returns the scripts used for preview
/// </summary>
/// <returns></returns>
private IEnumerable<string> GetScriptsForPreview()
{
var resources = JsonConvert.DeserializeObject<JArray>(Resources.PreviewInitialize);
return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
}
/// <summary>
/// Re-format asset paths to be absolute paths
/// </summary>
/// <param name="assets"></param>
/// <returns></returns>
private IEnumerable<string> FormatPaths(IEnumerable<string> assets)
{
return assets
.Where(x => x.IsNullOrWhiteSpace() == false)
.Select(x => !x.StartsWith("/") && Uri.IsWellFormedUriString(x, UriKind.Relative)
// 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
? _hostingEnvironment.ApplicationVirtualPath.EnsureStartsWith('/').TrimEnd("/") + x.EnsureStartsWith('/')
: x).ToList();
}
/// <summary>
/// Returns the web asset paths to load for property editors that have the <see cref="PropertyEditorAssetAttribute"/> attribute applied
/// </summary>
/// <returns></returns>
private IEnumerable<PropertyEditorAssetAttribute> ScanPropertyEditors()
{
return _propertyEditorCollection
.SelectMany(x => x.GetType().GetCustomAttributes<PropertyEditorAssetAttribute>(false));
}
}
}
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.JavaScript
{
public class CssInitialization
{
private readonly IRuntimeMinifier _runtimeMinifier;
public CssInitialization(IRuntimeMinifier runtimeMinifier)
{
_runtimeMinifier = runtimeMinifier;
}
/// <summary>
/// Processes all found manifest files, and outputs css inject calls for all css files found in all manifests.
/// </summary>
public async Task<string> GetStylesheetInitializationAsync()
{
var files = await _runtimeMinifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoCssBundleName);
return WriteScript(files);
}
internal static string WriteScript(IEnumerable<string> files)
{
var sb = new StringBuilder();
foreach (var file in files)
sb.AppendFormat("{0}LazyLoad.css('{1}');", Environment.NewLine, file);
return sb.ToString();
}
}
}
@@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.WebAssets;
using Umbraco.Infrastructure.WebAssets;
namespace Umbraco.Web.JavaScript
{
// TODO: Rename this
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);
/// <summary>
/// Gets the JS initialization script to boot the back office application
/// </summary>
/// <param name="scripts"></param>
/// <param name="angularModule">
/// The angular module name to boot
/// </param>
/// <param name="globalSettings"></param>
/// <param name="ioHelper"></param>
/// <returns></returns>
public static string GetJavascriptInitialization(IEnumerable<string> 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);
}
/// <summary>
/// Parses the JsResources.Main and replaces the replacement tokens accordingly
/// </summary>
/// <param name="scripts"></param>
/// <param name="umbracoPath"></param>
/// <param name="angularModule"></param>
/// <returns></returns>
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");
});
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Hosting;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.WebAssets;
using Umbraco.Infrastructure.WebAssets;
namespace Umbraco.Web.JavaScript
{
/// <summary>
/// Reads from all defined manifests and ensures that any of their initialization is output with the
/// main Umbraco initialization output.
/// </summary>
public class JsInitialization
{
/// <summary>
/// Returns the default config as a JArray
/// </summary>
/// <returns></returns>
public static IEnumerable<string> GetDefaultInitialization()
{
var resources = JsonConvert.DeserializeObject<JArray>(Resources.JsInitialize);
return resources.Where(x => x.Type == JTokenType.String).Select(x => x.ToString());
}
}
}
@@ -1,5 +1,5 @@
using System;
using Umbraco.Core.Assets;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.PropertyEditors
{
@@ -12,23 +12,13 @@ namespace Umbraco.Web.PropertyEditors
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class PropertyEditorAssetAttribute : Attribute
{
public AssetType AssetType { get; private set; }
public string FilePath { get; private set; }
public int Priority { get; set; }
/// <summary>
/// Returns a CDF file reference
/// </summary>
public IAssetFile DependencyFile =>
Priority == int.MinValue
? new AssetFile(AssetType) {FilePath = FilePath}
: new AssetFile(AssetType) {FilePath = FilePath, Priority = Priority};
public AssetType AssetType { get; }
public string FilePath { get; }
public PropertyEditorAssetAttribute(AssetType assetType, string filePath)
{
AssetType = assetType;
FilePath = filePath;
Priority = int.MinValue;
}
}
}
@@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace Umbraco.Infrastructure.RuntimeMinification {
namespace Umbraco.Infrastructure.WebAssets {
using System;
@@ -19,7 +19,7 @@ namespace Umbraco.Infrastructure.RuntimeMinification {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -39,7 +39,7 @@ namespace Umbraco.Infrastructure.RuntimeMinification {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Infrastructure.RuntimeMinification.Resources", typeof(Resources).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Infrastructure.WebAssets.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -0,0 +1,24 @@
using System.Threading.Tasks;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.JavaScript
{
public static class RuntimeMinifierExtensions
{
/// <summary>
/// Returns the JavaScript to load the back office's assets
/// </summary>
/// <returns></returns>
public static async Task<string> GetScriptForLoadingBackOfficeAsync(this IRuntimeMinifier minifier, IGlobalSettings globalSettings, IIOHelper ioHelper)
{
var initCss = new CssInitialization(minifier);
var files = await minifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoJsBundleName);
var result = JavaScriptHelper.GetJavascriptInitialization(files, "umbraco", globalSettings, ioHelper);
result += await initCss.GetStylesheetInitializationAsync();
return result;
}
}
}
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Umbraco.Infrastructure.RuntimeMinification;
using Umbraco.Infrastructure.WebAssets;
namespace Umbraco.Web.JavaScript
{
@@ -2,7 +2,6 @@
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web.JavaScript;
using Umbraco.Web.JavaScript.CDF;
namespace Umbraco.Tests.Web.AngularIntegration
{
@@ -1,18 +1,26 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.ActionResults;
using Umbraco.Web.JavaScript;
namespace Umbraco.Web.BackOffice.Controllers
{
public class BackOfficeController : Controller
{
private readonly IRuntimeMinifier _runtimeMinifier;
private readonly IGlobalSettings _globalSettings;
private readonly IIOHelper _ioHelper;
public BackOfficeController(IRuntimeMinifier runtimeMinifier)
public BackOfficeController(IRuntimeMinifier runtimeMinifier, IGlobalSettings globalSettings, IIOHelper ioHelper)
{
_runtimeMinifier = runtimeMinifier;
_globalSettings = globalSettings;
_ioHelper = ioHelper;
}
// GET
@@ -28,7 +36,7 @@ namespace Umbraco.Web.BackOffice.Controllers
[MinifyJavaScriptResult(Order = 0)]
public async Task<IActionResult> Application()
{
var result = await _runtimeMinifier.GetScriptForBackOfficeAsync();
var result = await _runtimeMinifier.GetScriptForLoadingBackOfficeAsync(_globalSettings, _ioHelper);
return new JavaScriptResult(result);
}
@@ -2,8 +2,8 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Umbraco.Core.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.Assets;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.BackOffice.Controllers;
using Umbraco.Web.Common.ActionResults;
@@ -1,6 +1,7 @@
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.Common.RuntimeMinification
{
@@ -1,21 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Smidge;
using Smidge.CompositeFiles;
using Smidge.FileProcessors;
using Smidge.Models;
using Smidge.Nuglify;
using Umbraco.Core;
using Umbraco.Core.Assets;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.JavaScript;
using CssFile = Smidge.Models.CssFile;
using JavaScriptFile = Smidge.Models.JavaScriptFile;
@@ -25,36 +20,30 @@ namespace Umbraco.Web.Common.RuntimeMinification
public class SmidgeRuntimeMinifier : IRuntimeMinifier
{
private readonly IGlobalSettings _globalSettings;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IIOHelper _ioHelper;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly ISmidgeConfig _smidgeConfig;
private readonly IConfigManipulator _configManipulator;
private readonly IManifestParser _manifestParser;
private readonly PreProcessPipelineFactory _preProcessPipelineFactory;
private readonly PropertyEditorCollection _propertyEditorCollection;
private readonly BundleManager _bundles;
private readonly SmidgeHelper _smidge;
private PreProcessPipeline _jsPipeline;
private PreProcessPipeline _cssPipeline;
public SmidgeRuntimeMinifier(
BundleManager bundles,
SmidgeHelper smidge,
PreProcessPipelineFactory preProcessPipelineFactory,
IManifestParser manifestParser,
IHttpContextAccessor httpContextAccessor,
PropertyEditorCollection propertyEditorCollection,
IGlobalSettings globalSettings,
IIOHelper ioHelper,
IHostingEnvironment hostingEnvironment,
ISmidgeConfig smidgeConfig,
IConfigManipulator configManipulator)
{
_bundles = bundles;
_smidge = smidge;
_preProcessPipelineFactory = preProcessPipelineFactory;
_manifestParser = manifestParser;
_httpContextAccessor = httpContextAccessor;
_propertyEditorCollection = propertyEditorCollection;
_globalSettings = globalSettings;
_ioHelper = ioHelper;
_hostingEnvironment = hostingEnvironment;
@@ -62,41 +51,42 @@ namespace Umbraco.Web.Common.RuntimeMinification
_configManipulator = configManipulator;
}
private PreProcessPipeline JsPipeline => _jsPipeline ??= _preProcessPipelineFactory.Create(typeof(JsMinifier));
private PreProcessPipeline CssPipeline => _cssPipeline ??= _preProcessPipelineFactory.Create(typeof(NuglifyCss));
private PreProcessPipeline JsPipeline => _jsPipeline ??= _preProcessPipelineFactory.Create(typeof(JsMinifier));
private PreProcessPipeline CssPipeline => _cssPipeline ??= _preProcessPipelineFactory.Create(typeof(NuglifyCss));
private Uri GetRequestUrl() => new Uri(_httpContextAccessor.HttpContext.Request.GetEncodedUrl(), UriKind.Absolute);
public string GetHashValue => _smidgeConfig.Version;
public string CacheBuster => _smidgeConfig.Version;
public void RequiresCss(string bundleName, params string[] filePaths) => _smidge.CreateCssBundle(bundleName).RequiresCss(filePaths);
public string RenderCssHere(string bundleName) => _smidge.CssHereAsync(bundleName).ToString();
public void RequiresJs(string bundleName, params string[] filePaths) => _smidge.CreateJsBundle(bundleName).RequiresJs(filePaths);
public string RenderJsHere(string bundleName) => _smidge.JsHereAsync(bundleName).ToString();
public async Task<IEnumerable<string>> GetAssetPathsAsync(AssetType assetType, List<IAssetFile> attributes)
// only issue with creating bundles like this is that we don't have full control over the bundle options, though that could
public void CreateCssBundle(string bundleName, params string[] filePaths)
{
if (_bundles.Exists(bundleName))
throw new InvalidOperationException($"The bundle name {bundleName} already exists");
var files = attributes
.Where(x => x.DependencyType == assetType)
.Select(x=>x.FilePath)
.ToArray();
var bundle = _bundles.Create(bundleName, WebFileType.Css, filePaths);
if (files.Length == 0) return Array.Empty<string>();
// Here we could configure bundle options instead of using smidge's global defaults.
// For example we can use our own custom cache buster for this bundle without having the global one
// affect this or vice versa.
}
if (assetType == AssetType.Javascript)
{
_smidge.RequiresJs(files);
public string RenderCssHere(string bundleName) => _smidge.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
return await _smidge.GenerateJsUrlsAsync(JsPipeline, _hostingEnvironment.IsDebugMode);
}
else
{
_smidge.RequiresCss(files);
public void CreateJsBundle(string bundleName, params string[] filePaths)
{
if (_bundles.Exists(bundleName))
throw new InvalidOperationException($"The bundle name {bundleName} already exists");
return await _smidge.GenerateCssUrlsAsync(CssPipeline, _hostingEnvironment.IsDebugMode);
}
var bundle = _bundles.Create(bundleName, WebFileType.Js, filePaths);
// Here we could configure bundle options instead of using smidge's global defaults.
// For example we can use our own custom cache buster for this bundle without having the global one
// affect this or vice versa.
}
public string RenderJsHere(string bundleName) => _smidge.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
public async Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName) => await _smidge.GenerateJsUrlsAsync(bundleName, _hostingEnvironment.IsDebugMode);
public async Task<string> MinifyAsync(string fileContent, AssetType assetType)
{
if (assetType == AssetType.Javascript)
@@ -126,31 +116,6 @@ namespace Umbraco.Web.Common.RuntimeMinification
_configManipulator.SaveConfigValue(Constants.Configuration.ConfigRuntimeMinificationVersion, version.ToString());
}
public async Task<string> GetScriptForBackOfficeAsync()
{
var initJs = new JsInitialization(_manifestParser, this, _propertyEditorCollection);
var initCss = new CssInitialization(_manifestParser, this, _propertyEditorCollection);
var requestUrl = GetRequestUrl();
var files = await initJs.OptimizeBackOfficeScriptFilesAsync(requestUrl, JsInitialization.GetDefaultInitialization());
var result = JavaScriptHelper.GetJavascriptInitialization(files, "umbraco", _globalSettings, _ioHelper);
result += await initCss.GetStylesheetInitializationAsync(requestUrl);
return result;
}
public async Task<IEnumerable<string>> GetAssetListAsync()
{
var initJs = new JsInitialization(_manifestParser, this, _propertyEditorCollection);
var initCss = new CssInitialization(_manifestParser, this, _propertyEditorCollection);
var assets = new List<string>();
var requestUrl = GetRequestUrl();
assets.AddRange(await initJs.OptimizeBackOfficeScriptFilesAsync(requestUrl, Enumerable.Empty<string>()));
assets.AddRange(await initCss.GetStylesheetFilesAsync(requestUrl));
return assets;
}
}
}
@@ -10,18 +10,12 @@
Html.EnableClientValidation();
Html.EnableUnobtrusiveJavaScript();
var runtimeMinifier = Current.RuntimeMinifier;
runtimeMinifier.RequiresJs("umbraco",
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js");
var success = TempData["ProfileUpdateSuccess"] != null;
}
@*NOTE: This RenderJsHere code should be put on your main template page where the rest of your script tags are placed*@
@Html.Raw(runtimeMinifier.RenderJsHere("umbraco"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
@if (Current.MembershipHelper.IsLoggedIn() && profileModel != null)
{
@@ -12,16 +12,11 @@
Html.EnableClientValidation();
Html.EnableUnobtrusiveJavaScript();
var runtimeMinifier = Current.RuntimeMinifier;
runtimeMinifier.RequiresJs("umbraco",
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js");
}
@* NOTE: This RenderJsHere code should be put on your main template page where the rest of your script tags are placed *@
@Html.Raw(runtimeMinifier.RenderJsHere("umbraco"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
@using (Html.BeginUmbracoForm<UmbLoginController>("HandleLogin"))
{
@@ -34,18 +34,12 @@
Html.EnableClientValidation();
Html.EnableUnobtrusiveJavaScript();
var runtimeMinifier = Current.RuntimeMinifier;
runtimeMinifier.RequiresJs("umbraco",
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js");
var success = TempData["FormSuccess"] != null;
}
@*NOTE: This RenderJsHere code should be put on your main template page where the rest of your script tags are placed*@
@Html.Raw(runtimeMinifier.RenderJsHere("umbraco"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
@if (success)
{
@@ -1,17 +1,13 @@
@using Umbraco.Core
@using Umbraco.Web.Composing
@using Umbraco.Web
@using Umbraco.Web.JavaScript
@inherits System.Web.Mvc.WebViewPage<Umbraco.Web.Editors.BackOfficeModel>
@{
Layout = null;
var runtimeMinifier = Current.RuntimeMinifier;
runtimeMinifier.RequiresCss("umbraco",
"assets/css/umbraco.css",
"lib/bootstrap-social/bootstrap-social.css",
"lib/font-awesome/css/font-awesome.min.css");
}
<!DOCTYPE html>
@@ -23,8 +19,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Umbraco</title>
@Html.Raw(runtimeMinifier.RenderJsHere("umbraco"));
@Html.Raw(runtimeMinifier.RenderCssHere(BackOfficeWebAssets.UmbracoUpgradeCssBundleName));
@*Because we're lazy loading angular js, the embedded cloak style will not be loaded initially, but we need it*@
<style>
@@ -1,6 +1,7 @@
@using Umbraco.Core
@using Umbraco.Web.Composing
@using Umbraco.Web
@using Umbraco.Web.JavaScript
@inherits WebViewPage<Umbraco.Web.Editors.BackOfficeModel>
@@ -16,12 +17,8 @@
isDebug = true;
}
}
var runtimeMinifier = Current.RuntimeMinifier;
runtimeMinifier.RequiresCss("umbraco",
"lib/bootstrap-social/bootstrap-social.css",
"assets/css/umbraco.css",
"lib/font-awesome/css/font-awesome.min.css");
var runtimeMinifier = Current.RuntimeMinifier;
}
<!DOCTYPE html>
@@ -38,7 +35,7 @@
<title ng-bind="$root.locationTitle">Umbraco</title>
@Html.Raw(runtimeMinifier.RenderCssHere("Umbraco"))
@Html.Raw(runtimeMinifier.RenderCssHere(BackOfficeWebAssets.UmbracoInitCssBundleName))
</head>
<body ng-class="{'touch':touchDevice, 'emptySection':emptySection, 'umb-drawer-is-visible':drawer.show, 'umb-tour-is-visible': tour.show, 'tabbing-active':tabbingActive}" ng-controller="Umbraco.MainController" id="umbracoMainPageBody">
@@ -1,13 +1,11 @@
@using Umbraco.Web.Composing
@using Umbraco.Web.JavaScript
@inherits System.Web.Mvc.WebViewPage<Umbraco.Web.Editors.BackOfficePreviewModel>
@{
var disableDevicePreview = Model.DisableDevicePreview.ToString().ToLowerInvariant();
var runtimeMinifier = Current.RuntimeMinifier;
runtimeMinifier.RequiresCss("umbraco-preview",
"assets/css/canvasdesigner.css");
}
<!DOCTYPE html>
<html lang="en">
@@ -18,7 +16,7 @@
<meta name="pinterest" content="nopin" />
@Html.Raw(runtimeMinifier.RenderCssHere("umbraco-preview"))
@Html.Raw(runtimeMinifier.RenderCssHere(BackOfficeWebAssets.UmbracoPreviewCssBundleName))
</head>
+1
View File
@@ -20,6 +20,7 @@ using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Core.WebAssets;
using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.Editors;
@@ -31,6 +31,7 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.Trees;
namespace Umbraco.Web.Editors
@@ -247,38 +248,11 @@ namespace Umbraco.Web.Editors
[OutputCache(Order = 1, VaryByParam = "none", Location = OutputCacheLocation.Server, Duration = 5000)]
public async Task<JavaScriptResult> Application()
{
var result = await _runtimeMinifier.GetScriptForBackOfficeAsync();
var result = await _runtimeMinifier.GetScriptForLoadingBackOfficeAsync(GlobalSettings, _ioHelper);
return JavaScript(result);
}
/// <summary>
/// Returns a js array of all of the manifest assets
/// </summary>
/// <returns></returns>
[UmbracoAuthorize(Order = 0)]
[HttpGet]
public async Task<JsonNetResult> GetManifestAssetList()
{
async Task<JArray> GetAssetList()
{
var assets = new JArray(await _runtimeMinifier.GetAssetListAsync());
return new JArray(assets);
}
var assetList = await GetAssetList();
//cache the result if debugging is disabled
var result = _hostingEnvironment.IsDebugMode
? assetList
: AppCaches.RuntimeCache.GetCacheItem<JArray>(
"Umbraco.Web.Editors.BackOfficeController.GetManifestAssetList",
() => assetList,
new TimeSpan(0, 2, 0));
return new JsonNetResult { Data = result, Formatting = Formatting.None };
}
[UmbracoAuthorize(Order = 0)]
[HttpGet]
public JsonNetResult GetGridConfig()
@@ -20,6 +20,7 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.Editors
{
@@ -138,7 +139,6 @@ namespace Umbraco.Web.Editors
{"externalLoginsUrl", _urlHelper.Action("ExternalLogin", "BackOffice")},
{"externalLinkLoginsUrl", _urlHelper.Action("LinkLogin", "BackOffice")},
{"manifestAssetList", _urlHelper.Action("GetManifestAssetList", "BackOffice")},
{"gridConfig", _urlHelper.Action("GetGridConfig", "BackOffice")},
// TODO: This is ultra confusing! this same key is used for different things, when returning the full app when authenticated it is this URL but when not auth'd it's actually the ServerVariables address
{"serverVarsJs", _urlHelper.Action("Application", "BackOffice")},
@@ -478,7 +478,7 @@ namespace Umbraco.Web.Editors
var version = _runtimeState.SemanticVersion.ToSemanticString();
//the value is the hash of the version, cdf version and the configured state
app.Add("cacheBuster", $"{version}.{_runtimeState.Level}.{_runtimeMinifier.GetHashValue}".GenerateHash());
app.Add("cacheBuster", $"{version}.{_runtimeState.Level}.{_runtimeMinifier.CacheBuster}".GenerateHash());
//useful for dealing with virtual paths on the client side when hosted in virtual directories especially
app.Add("applicationPath", _httpContextAccessor.GetRequiredHttpContext().Request.ApplicationPath.EnsureEndsWith('/'));
@@ -20,6 +20,7 @@ using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.WebAssets;
using Umbraco.Net;
using Umbraco.Web.JavaScript;
using Umbraco.Web.Models;
+3 -4
View File
@@ -11,6 +11,7 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Runtime;
using Umbraco.Core.Services;
using Umbraco.Core.WebAssets;
using Umbraco.Web.Composing;
using Umbraco.Web.Features;
using Umbraco.Web.JavaScript;
@@ -36,7 +37,7 @@ namespace Umbraco.Web.Editors
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly ICookieManager _cookieManager;
private IRuntimeSettings _runtimeSettings;
private readonly IRuntimeSettings _runtimeSettings;
private readonly ISecuritySettings _securitySettings;
private readonly IRuntimeMinifier _runtimeMinifier;
@@ -102,9 +103,7 @@ namespace Umbraco.Web.Editors
[OutputCache(Order = 1, VaryByParam = "none", Location = OutputCacheLocation.Server, Duration = 5000)]
public async Task<JavaScriptResult> Application()
{
var files = await JavaScriptHelper.OptimizeScriptFilesAsync(HttpContext.Request.Url, JavaScriptHelper.GetPreviewInitialization(), _runtimeMinifier);
var files = await _runtimeMinifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoPreviewJsBundleName);
var result = JavaScriptHelper.GetJavascriptInitialization(files, "umbraco.preview", _globalSettings, _ioHelper);
return JavaScript(result);
@@ -5,21 +5,21 @@ using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.Composing;
using Umbraco.Web.Editors;
using Umbraco.Web.Features;
using Umbraco.Web.JavaScript;
using Umbraco.Web.Models;
using Umbraco.Web.Trees;
namespace Umbraco.Web
{
using Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Web.JavaScript;
/// <summary>
/// HtmlHelper extensions for the back office
/// </summary>
@@ -129,8 +129,7 @@ namespace Umbraco.Web
public static IHtmlString AngularValueTinyMceAssets(this HtmlHelper html, IRuntimeMinifier runtimeMinifier)
{
var ctx = new HttpContextWrapper(HttpContext.Current);
var files = JavaScriptHelper.OptimizeTinyMceScriptFilesAsync(ctx.Request.Url, runtimeMinifier).GetAwaiter().GetResult();
var files = runtimeMinifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoTinyMceJsBundleName).GetAwaiter().GetResult();
var sb = new StringBuilder();
@@ -6,6 +6,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.JavaScript;
using Umbraco.Web.Mvc;
using Umbraco.Web.Security;
@@ -1,228 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Web.Mvc;
using ClientDependency.Core;
using ClientDependency.Core.CompositeFiles;
using ClientDependency.Core.Config;
using ClientDependency.Core.Mvc;
using Umbraco.Core.Assets;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Runtime;
namespace Umbraco.Web.JavaScript.CDF
{
public class ClientDependencyRuntimeMinifier : IRuntimeMinifier
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IIOHelper _ioHelper;
private readonly ILogger _logger;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IManifestParser _manifestParser;
private readonly IGlobalSettings _globalSettings;
private readonly PropertyEditorCollection _propertyEditorCollection;
public string GetHashValue => ClientDependencySettings.Instance.Version.ToString();
public ClientDependencyRuntimeMinifier(
IHttpContextAccessor httpContextAccessor,
IIOHelper ioHelper,
ILogger logger,
IUmbracoVersion umbracoVersion,
IManifestParser manifestParser,
IGlobalSettings globalSettings,
PropertyEditorCollection propertyEditorCollection)
{
_httpContextAccessor = httpContextAccessor;
_ioHelper = ioHelper;
_logger = logger;
_umbracoVersion = umbracoVersion;
_manifestParser = manifestParser;
_globalSettings = globalSettings;
_propertyEditorCollection = propertyEditorCollection;
}
private DependencyRenderer GetDependencyRenderer
{
get
{
return (DependencyRenderer) typeof(DependencyRenderer)
.GetMethod("TryCreate", BindingFlags.Static |BindingFlags.NonPublic)
.Invoke(null, new object[]
{
_httpContextAccessor.GetRequiredHttpContext(),
null
});
}
}
public void RequiresCss(string bundleName, params string[] filePaths)
{
foreach (var filePath in filePaths)
{
GetDependencyRenderer.RegisterDependency(filePath, bundleName, ClientDependencyType.Css);
}
}
public string RenderCssHere(string bundleName)
{
var path = new BasicPath(bundleName, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath));
return typeof(DependencyRenderer)
.GetMethod("RenderPlaceholder",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new []{typeof(ClientDependencyType), typeof(IEnumerable<IClientDependencyPath>)},
null)
?.Invoke(GetDependencyRenderer, new object[]
{
ClientDependencyType.Css,
new IClientDependencyPath[]{path}
}) as string;
//return new HtmlString(_htmlHelper.ViewContext.GetLoader().RenderPlaceholder(
// ClientDependencyType.Css, path));
}
public void RequiresJs(string bundleName, params string[] filePaths)
{
foreach (var filePath in filePaths)
{
GetDependencyRenderer.RegisterDependency(filePath, bundleName, ClientDependencyType.Javascript);
}
}
public string RenderJsHere(string bundleName)
{
var path = new BasicPath(bundleName, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath));
return typeof(DependencyRenderer)
.GetMethod("RenderPlaceholder",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new []{typeof(ClientDependencyType), typeof(IEnumerable<IClientDependencyPath>)},
null)
?.Invoke(GetDependencyRenderer, new object[]
{
ClientDependencyType.Javascript,
new IClientDependencyPath[]{path}
}) as string;
}
public Task<IEnumerable<string>> GetAssetPathsAsync(AssetType assetType, List<IAssetFile> attributes)
{
// get the output string for these registrations which will be processed by CDF correctly to stagger the output based
// on internal vs external resources. The output will be delimited based on our custom Umbraco.Web.JavaScript.DependencyPathRenderer
var dependencies = new List<IClientDependencyFile>();
foreach (var assetFile in attributes)
{
if (!((AssetFile)assetFile is null))
dependencies.Add(MapAssetFile(assetFile));
}
var renderer = ClientDependencySettings.Instance.MvcRendererCollection["Umbraco.DependencyPathRenderer"];
renderer.RegisterDependencies(dependencies, new HashSet<IClientDependencyPath>(), out var scripts, out var stylesheets, _httpContextAccessor.HttpContext);
var toParse = assetType == AssetType.Javascript ? scripts : stylesheets;
return Task.FromResult<IEnumerable<string>>(toParse.Split(new[] { DependencyPathRenderer.Delimiter }, StringSplitOptions.RemoveEmptyEntries));
}
public async Task<string> MinifyAsync(string fileContent, AssetType assetType)
{
TextReader reader = new StringReader(fileContent);
if (assetType == AssetType.Javascript)
{
var jsMinifier = new JSMin();
return jsMinifier.Minify(reader);
}
// asset type is Css
var cssMinifier = new CssMinifier();
return cssMinifier.Minify(reader);
}
public void Reset()
{
// Update ClientDependency version
var clientDependencyConfig = new ClientDependencyConfiguration(_logger, _ioHelper);
var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber(
_umbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd");
// Delete ClientDependency temp directories to make sure we get fresh caches
var clientDependencyTempFilesDeleted = clientDependencyConfig.ClearTempFiles(_httpContextAccessor.HttpContext);
}
public async Task<string> GetScriptForBackOfficeAsync()
{
var initJs = new JsInitialization(_manifestParser, this, _propertyEditorCollection);
var initCss = new CssInitialization(_manifestParser, this, _propertyEditorCollection);
var requestUrl = _httpContextAccessor.GetRequiredHttpContext().Request.Url;
var files = await initJs.OptimizeBackOfficeScriptFilesAsync(requestUrl, JsInitialization.GetDefaultInitialization());
var result = JavaScriptHelper.GetJavascriptInitialization(files, "umbraco", _globalSettings, _ioHelper);
result += await initCss.GetStylesheetInitializationAsync(requestUrl);
return result;
}
public async Task<IEnumerable<string>> GetAssetListAsync()
{
var initJs = new JsInitialization(_manifestParser, this, _propertyEditorCollection);
var initCss = new CssInitialization(_manifestParser, this, _propertyEditorCollection);
var assets = new List<string>();
var requestUrl = _httpContextAccessor.GetRequiredHttpContext().Request.Url;
assets.AddRange(await initJs.OptimizeBackOfficeScriptFilesAsync(requestUrl, Enumerable.Empty<string>()));
assets.AddRange(await initCss.GetStylesheetFilesAsync(requestUrl));
return assets;
}
private ClientDependencyType MapDependencyTypeValue(AssetType type)
{
switch (type)
{
case AssetType.Javascript:
return ClientDependencyType.Javascript;
case AssetType.Css:
return ClientDependencyType.Css;
}
return (ClientDependencyType)Enum.Parse(typeof(ClientDependencyType), type.ToString(), true);
}
private IClientDependencyFile MapAssetFile(IAssetFile assetFile)
{
var assetFileType = (AssetFile)assetFile;
var basicFile = new BasicFile(MapDependencyTypeValue(assetFileType.DependencyType))
{
Group = assetFile.Group,
Priority = assetFile.Priority,
//ForceBundle = assetFile.Bundle, //TODO
FilePath = assetFile.FilePath,
ForceProvider = assetFile.ForceProvider,
PathNameAlias = assetFile.PathNameAlias,
};
foreach (var kvp in assetFile.HtmlAttributes)
{
basicFile.HtmlAttributes.Add(kvp.Key, kvp.Value);
}
return basicFile;
}
}
}
@@ -1,8 +1,8 @@
using System.Web.Mvc;
using Umbraco.Core.Assets;
using Umbraco.Web.Composing;
using Umbraco.Core.Hosting;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.Mvc
{
+7 -6
View File
@@ -144,7 +144,7 @@
<Compile Include="Compose\BackOfficeUserAuditEventsComposer.cs" />
<Compile Include="Composing\CompositionExtensions\Installer.cs" />
<Compile Include="Composing\LightInject\LightInjectContainer.cs" />
<Compile Include="JavaScript\CDF\ClientDependencyRuntimeMinifier.cs" />
<Compile Include="WebAssets\CDF\ClientDependencyRuntimeMinifier.cs" />
<Compile Include="Models\NoNodesViewModel.cs" />
<Compile Include="Mvc\RenderNoContentController.cs" />
<Compile Include="Editors\BackOfficePreviewModel.cs" />
@@ -192,8 +192,8 @@
<Compile Include="Profiling\WebProfilingController.cs" />
<Compile Include="RoutableDocumentFilter.cs" />
<Compile Include="Runtime\AspNetUmbracoBootPermissionChecker.cs" />
<Compile Include="JavaScript\CDF\ClientDependencyComponent.cs" />
<Compile Include="JavaScript\CDF\ClientDependencyComposer.cs" />
<Compile Include="WebAssets\CDF\ClientDependencyComponent.cs" />
<Compile Include="WebAssets\CDF\ClientDependencyComposer.cs" />
<Compile Include="Security\BackOfficeUserStore.cs" />
<Compile Include="Security\BackOfficeUserValidator.cs" />
<Compile Include="Security\ConfiguredPasswordValidator.cs" />
@@ -242,7 +242,7 @@
<Compile Include="Security\SessionIdValidator.cs" />
<Compile Include="SignalR\PreviewHubComposer.cs" />
<Compile Include="Trees\FilesTreeController.cs" />
<Compile Include="JavaScript\CDF\ClientDependencyConfiguration.cs" />
<Compile Include="WebAssets\CDF\ClientDependencyConfiguration.cs" />
<Compile Include="Editors\Binders\BlueprintItemBinder.cs" />
<Compile Include="UmbracoApplicationBase.cs" />
<Compile Include="WebApi\Filters\HttpQueryStringModelBinder.cs" />
@@ -336,7 +336,7 @@
<Compile Include="Trees\MediaTypeTreeController.cs" />
<Compile Include="Trees\MemberTypeTreeController.cs" />
<Compile Include="Security\WebAuthExtensions.cs" />
<Compile Include="JavaScript\CDF\UmbracoClientDependencyLoader.cs" />
<Compile Include="WebAssets\CDF\UmbracoClientDependencyLoader.cs" />
<Compile Include="UmbracoDefaultOwinStartup.cs" />
<Compile Include="HtmlStringUtilities.cs" />
<Compile Include="IUmbracoComponentRenderer.cs" />
@@ -396,7 +396,7 @@
<Compile Include="Trees\MenuRenderingEventArgs.cs" />
<Compile Include="Trees\TemplatesTreeController.cs" />
<Compile Include="Trees\TreeControllerBase.cs" />
<Compile Include="JavaScript\CDF\DependencyPathRenderer.cs" />
<Compile Include="WebAssets\CDF\DependencyPathRenderer.cs" />
<Compile Include="UmbracoComponentRenderer.cs" />
<Compile Include="WebApi\AngularJsonMediaTypeFormatter.cs" />
<Compile Include="WebApi\AngularJsonOnlyConfigurationAttribute.cs" />
@@ -547,6 +547,7 @@
<Compile Include="UmbracoWebService.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="WebAssets\WebAssetsComponent.cs" />
<Compile Include="WebViewPageExtensions.cs" />
<Compile Include="Runtime\WebFinalComponent.cs" />
<Compile Include="Runtime\WebFinalComposer.cs" />
+1 -1
View File
@@ -146,7 +146,7 @@ namespace Umbraco.Web
}
var version = Current.UmbracoVersion.SemanticVersion.ToSemanticString();
return $"{version}.{Current.RuntimeMinifier.GetHashValue}".GenerateHash();
return $"{version}.{Current.RuntimeMinifier.CacheBuster}".GenerateHash();
}
}
}
@@ -9,7 +9,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Web.Runtime;
namespace Umbraco.Web.JavaScript.CDF
namespace Umbraco.Web.WebAssets.CDF
{
[ComposeAfter(typeof(WebInitialComponent))]
public sealed class ClientDependencyComponent : IComponent
@@ -1,8 +1,8 @@
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
namespace Umbraco.Web.JavaScript.CDF
namespace Umbraco.Web.WebAssets.CDF
{
public sealed class ClientDependencyComposer : ComponentComposer<ClientDependencyComponent>
{
@@ -12,7 +12,7 @@ using Semver;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Web.JavaScript.CDF
namespace Umbraco.Web.WebAssets.CDF
{
/// <summary>
/// A utility class for working with CDF config and cache files - use sparingly!
@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using ClientDependency.Core;
using ClientDependency.Core.CompositeFiles;
using ClientDependency.Core.Config;
using ClientDependency.Core.Mvc;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.WebAssets;
using Umbraco.Web.JavaScript;
using CssFile = ClientDependency.Core.CssFile;
using JavascriptFile = ClientDependency.Core.JavascriptFile;
namespace Umbraco.Web.WebAssets.CDF
{
public class ClientDependencyRuntimeMinifier : IRuntimeMinifier
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IIOHelper _ioHelper;
private readonly ILogger _logger;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IManifestParser _manifestParser;
private readonly IGlobalSettings _globalSettings;
private readonly PropertyEditorCollection _propertyEditorCollection;
public string CacheBuster => ClientDependencySettings.Instance.Version.ToString();
public ClientDependencyRuntimeMinifier(
IHttpContextAccessor httpContextAccessor,
IIOHelper ioHelper,
ILogger logger,
IUmbracoVersion umbracoVersion,
IManifestParser manifestParser,
IGlobalSettings globalSettings,
PropertyEditorCollection propertyEditorCollection)
{
_httpContextAccessor = httpContextAccessor;
_ioHelper = ioHelper;
_logger = logger;
_umbracoVersion = umbracoVersion;
_manifestParser = manifestParser;
_globalSettings = globalSettings;
_propertyEditorCollection = propertyEditorCollection;
}
public void CreateCssBundle(string bundleName, params string[] filePaths)
{
BundleManager.CreateCssBundle(
bundleName,
filePaths.Select(x => new CssFile(x)).ToArray());
}
public string RenderCssHere(string bundleName)
{
var bundleFiles = GetCssBundleFiles(bundleName);
if (bundleFiles == null) return string.Empty;
return RenderOutput(bundleFiles, AssetType.Css);
}
public void CreateJsBundle(string bundleName, params string[] filePaths)
{
BundleManager.CreateJsBundle(
bundleName,
filePaths.Select(x => new JavascriptFile(x)).ToArray());
}
public string RenderJsHere(string bundleName)
{
var bundleFiles = GetJsBundleFiles(bundleName);
if (bundleFiles == null) return string.Empty;
return RenderOutput(bundleFiles, AssetType.Javascript);
}
public Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName)
{
var bundleFiles = GetJsBundleFiles(bundleName)?.ToList() ?? GetCssBundleFiles(bundleName)?.ToList();
if (bundleFiles == null || bundleFiles.Count == 0) return Task.FromResult(Enumerable.Empty<string>());
var assetType = bundleFiles[0].DependencyType == ClientDependencyType.Css ? AssetType.Css : AssetType.Javascript;
// get the output string for these registrations which will be processed by CDF correctly to stagger the output based
// on internal vs external resources. The output will be delimited based on our custom Umbraco.Web.JavaScript.DependencyPathRenderer
var dependencies = new List<IClientDependencyFile>();
// This is a hack on CDF so that we can resolve CDF urls directly since that isn't directly supported by the lib
var renderer = ClientDependencySettings.Instance.MvcRendererCollection["Umbraco.DependencyPathRenderer"];
renderer.RegisterDependencies(dependencies, new HashSet<IClientDependencyPath>(), out var scripts, out var stylesheets, _httpContextAccessor.HttpContext);
var toParse = assetType == AssetType.Javascript ? scripts : stylesheets;
return Task.FromResult<IEnumerable<string>>(toParse.Split(new[] { DependencyPathRenderer.Delimiter }, StringSplitOptions.RemoveEmptyEntries));
}
public Task<string> MinifyAsync(string fileContent, AssetType assetType)
{
TextReader reader = new StringReader(fileContent);
if (assetType == AssetType.Javascript)
{
var jsMinifier = new JSMin();
return Task.FromResult(jsMinifier.Minify(reader));
}
// asset type is Css
var cssMinifier = new CssMinifier();
return Task.FromResult(cssMinifier.Minify(reader));
}
public void Reset()
{
// Update ClientDependency version
var clientDependencyConfig = new ClientDependencyConfiguration(_logger, _ioHelper);
var clientDependencyUpdated = clientDependencyConfig.UpdateVersionNumber(
_umbracoVersion.SemanticVersion, DateTime.UtcNow, "yyyyMMdd");
// Delete ClientDependency temp directories to make sure we get fresh caches
var clientDependencyTempFilesDeleted = clientDependencyConfig.ClearTempFiles(_httpContextAccessor.HttpContext);
}
private string RenderOutput(IEnumerable<IClientDependencyFile> bundleFiles, AssetType assetType)
{
var renderer = ClientDependencySettings.Instance.DefaultMvcRenderer;
renderer.RegisterDependencies(
bundleFiles.ToList(),
new HashSet<IClientDependencyPath>(),
out var jsOutput, out var cssOutput, _httpContextAccessor.GetRequiredHttpContext());
return HttpUtility.HtmlEncode(assetType == AssetType.Css ? cssOutput : jsOutput);
}
private IEnumerable<IClientDependencyFile> GetCssBundleFiles(string bundleName)
{
// the result of this is internal too, so use dynamic
dynamic bundle = typeof(BundleManager)
.GetMethod("GetCssBundle", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(null, new object[] { bundleName });
if (bundle == null) return null;
IEnumerable<IClientDependencyFile> bundleFiles = bundle.Files;
return bundleFiles;
}
private IEnumerable<IClientDependencyFile> GetJsBundleFiles(string bundleName)
{
// the result of this is internal too, so use dynamic
dynamic bundle = typeof(BundleManager)
.GetMethod("GetJsBundle", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(null, new object[] { bundleName });
if (bundle == null) return null;
IEnumerable<IClientDependencyFile> bundleFiles = bundle.Files;
return bundleFiles;
}
private ClientDependencyType MapDependencyTypeValue(AssetType type)
{
return type switch
{
AssetType.Javascript => ClientDependencyType.Javascript,
AssetType.Css => ClientDependencyType.Css,
_ => (ClientDependencyType) Enum.Parse(typeof(ClientDependencyType), type.ToString(), true)
};
}
private IClientDependencyFile MapAssetFile(IAssetFile assetFile)
{
var assetFileType = (AssetFile)assetFile;
var basicFile = new BasicFile(MapDependencyTypeValue(assetFileType.DependencyType))
{
FilePath = assetFile.FilePath
};
return basicFile;
}
}
}
@@ -3,7 +3,7 @@ using System.Web;
using ClientDependency.Core;
using ClientDependency.Core.FileRegistration.Providers;
namespace Umbraco.Web.JavaScript.CDF
namespace Umbraco.Web.WebAssets.CDF
{
/// <summary>
/// A custom renderer that only outputs a dependency path instead of script tags - for use with the js loader with yepnope
@@ -4,7 +4,7 @@ using ClientDependency.Core.FileRegistration.Providers;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Web.JavaScript.CDF
namespace Umbraco.Web.WebAssets.CDF
{
/// <summary>
/// Used to load in all client dependencies for Umbraco.
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Hosting;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.WebAssets;
using Umbraco.Web.JavaScript;
using Umbraco.Web.PropertyEditors;
using Umbraco.Infrastructure.WebAssets;
namespace Umbraco.Web.WebAssets
{
public sealed class WebAssetsComposer : ComponentComposer<WebAssetsComponent>
{
}
public sealed class WebAssetsComponent : IComponent
{
private readonly BackOfficeWebAssets _backOfficeWebAssets;
public WebAssetsComponent(BackOfficeWebAssets backOfficeWebAssets)
{
_backOfficeWebAssets = backOfficeWebAssets;
}
public void Initialize()
{
// TODO: This will eagerly scan types but we don't really want that, however it works for now.
// We don't actually have to change Smidge or anything, all we have to do is postpone this call for when the first request on the website arrives.
_backOfficeWebAssets.CreateBundles();
}
public void Terminate()
{
}
}
}