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:
75
src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs
Normal file
75
src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using ClientDependency.Core.CompositeFiles.Providers;
|
||||
using ClientDependency.Core.Config;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Web.Runtime;
|
||||
|
||||
namespace Umbraco.Web.WebAssets.CDF
|
||||
{
|
||||
[ComposeAfter(typeof(WebInitialComponent))]
|
||||
public sealed class ClientDependencyComponent : IComponent
|
||||
{
|
||||
private readonly IHostingSettings _hostingSettings;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IRuntimeSettings _settings;
|
||||
|
||||
public ClientDependencyComponent(
|
||||
IHostingSettings hostingSettings,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IRuntimeSettings settings)
|
||||
{
|
||||
_hostingSettings = hostingSettings;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (_hostingEnvironment.IsHosted)
|
||||
{
|
||||
ConfigureClientDependency();
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureClientDependency()
|
||||
{
|
||||
// Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK]
|
||||
XmlFileMapper.FileMapDefaultFolder = Core.Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "ClientDependency";
|
||||
BaseCompositeFileProcessingProvider.UrlTypeDefault = CompositeUrlType.Base64QueryStrings;
|
||||
|
||||
// Now we need to detect if we are running 'Umbraco.Core.LocalTempStorage' as EnvironmentTemp and in that case we want to change the CDF file
|
||||
// location to be there
|
||||
if (_hostingSettings.LocalTempStorageLocation == LocalTempStorage.EnvironmentTemp)
|
||||
{
|
||||
var cachePath = _hostingEnvironment.LocalTempPath;
|
||||
|
||||
//set the file map and composite file default location to the %temp% location
|
||||
BaseCompositeFileProcessingProvider.CompositeFilePathDefaultFolder
|
||||
= XmlFileMapper.FileMapDefaultFolder
|
||||
= Path.Combine(cachePath, "ClientDependency");
|
||||
}
|
||||
|
||||
if (_settings.MaxQueryStringLength.HasValue || _settings.MaxRequestLength.HasValue)
|
||||
{
|
||||
//set the max url length for CDF to be the smallest of the max query length, max request length
|
||||
ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(_settings.MaxQueryStringLength.GetValueOrDefault(), _settings.MaxRequestLength.GetValueOrDefault());
|
||||
}
|
||||
|
||||
//Register a custom renderer - used to process property editor dependencies
|
||||
var renderer = new DependencyPathRenderer();
|
||||
renderer.Initialize("Umbraco.DependencyPathRenderer", new NameValueCollection
|
||||
{
|
||||
{ "compositeFileHandlerPath", ClientDependencySettings.Instance.CompositeFileHandlerPath }
|
||||
});
|
||||
|
||||
ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer);
|
||||
}
|
||||
public void Terminate()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
15
src/Umbraco.Web/WebAssets/CDF/ClientDependencyComposer.cs
Normal file
15
src/Umbraco.Web/WebAssets/CDF/ClientDependencyComposer.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.WebAssets;
|
||||
|
||||
namespace Umbraco.Web.WebAssets.CDF
|
||||
{
|
||||
public sealed class ClientDependencyComposer : ComponentComposer<ClientDependencyComponent>
|
||||
{
|
||||
public override void Compose(Composition composition)
|
||||
{
|
||||
base.Compose(composition);
|
||||
composition.RegisterUnique<IRuntimeMinifier, ClientDependencyRuntimeMinifier>();
|
||||
}
|
||||
}
|
||||
}
|
||||
151
src/Umbraco.Web/WebAssets/CDF/ClientDependencyConfiguration.cs
Normal file
151
src/Umbraco.Web/WebAssets/CDF/ClientDependencyConfiguration.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using ClientDependency.Core.CompositeFiles.Providers;
|
||||
using ClientDependency.Core.Config;
|
||||
using Semver;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Web.WebAssets.CDF
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class for working with CDF config and cache files - use sparingly!
|
||||
/// </summary>
|
||||
public class ClientDependencyConfiguration
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _fileName;
|
||||
|
||||
private string FileMapDefaultFolder
|
||||
{
|
||||
get => XmlFileMapper.FileMapDefaultFolder;
|
||||
set => XmlFileMapper.FileMapDefaultFolder = value;
|
||||
}
|
||||
|
||||
public ClientDependencyConfiguration(ILogger logger, IIOHelper ioHelper)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
_logger = logger;
|
||||
_fileName = ioHelper.MapPath(string.Format("{0}/ClientDependency.config", Core.Constants.SystemDirectories.Config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a hashed value for the version and the DateTime.Day
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="SemVersion">version</see> of Umbraco we're upgrading to</param>
|
||||
/// <param name="date">A <see cref="DateTime">date</see> value to use in the hash to prevent this method from updating the version on each startup</param>
|
||||
/// <param name="dateFormat">Allows the developer to specify the <see cref="string">date precision</see> for the hash (i.e. "yyyyMMdd" would be a precision for the day)</param>
|
||||
/// <returns>Boolean to indicate successful update of the ClientDependency.config file</returns>
|
||||
public bool UpdateVersionNumber(SemVersion version, DateTime date, string dateFormat)
|
||||
{
|
||||
var byteContents = Encoding.Unicode.GetBytes(version + date.ToString(dateFormat));
|
||||
|
||||
//This is a way to convert a string to a long
|
||||
//see https://www.codeproject.com/Articles/34309/Convert-String-to-bit-Integer
|
||||
//We could much more easily use MD5 which would create us an INT but since that is not compliant with
|
||||
//hashing standards we have to use SHA
|
||||
int intHash;
|
||||
using (var hash = SHA256.Create())
|
||||
{
|
||||
var bytes = hash.ComputeHash(byteContents);
|
||||
|
||||
var longResult = new[] { 0, 8, 16, 24 }
|
||||
.Select(i => BitConverter.ToInt64(bytes, i))
|
||||
.Aggregate((x, y) => x ^ y);
|
||||
|
||||
//CDF requires an INT, and although this isn't fail safe, it will work for our purposes. We are not hashing for crypto purposes
|
||||
//so there could be some collisions with this conversion but it's not a problem for our purposes
|
||||
//It's also important to note that the long.GetHashCode() implementation in .NET is this: return (int) this ^ (int) (this >> 32);
|
||||
//which means that this value will not change per AppDomain like some GetHashCode implementations.
|
||||
intHash = longResult.GetHashCode();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(intHash).ToString();
|
||||
|
||||
//don't update if it's the same version
|
||||
if (oldVersion == newVersion)
|
||||
return false;
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>("Updated version number from {OldVersion} to {NewVersion}", oldVersion, newVersion);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>(ex, "Couldn't update ClientDependency version number");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the temporary files stored for the ClientDependency folder
|
||||
/// </summary>
|
||||
/// <param name="currentHttpContext"></param>
|
||||
public bool ClearTempFiles(HttpContextBase currentHttpContext)
|
||||
{
|
||||
var cdfTempDirectories = new HashSet<string>();
|
||||
foreach (BaseCompositeFileProcessingProvider provider in ClientDependencySettings.Instance
|
||||
.CompositeFileProcessingProviderCollection)
|
||||
{
|
||||
var path = provider.CompositeFilePath.FullName;
|
||||
cdfTempDirectories.Add(path);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var fullPath = FileMapDefaultFolder.StartsWith("~/")
|
||||
? currentHttpContext.Server.MapPath(FileMapDefaultFolder)
|
||||
: FileMapDefaultFolder;
|
||||
if (fullPath != null)
|
||||
{
|
||||
cdfTempDirectories.Add(fullPath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//invalid path format or something... try/catch to be safe
|
||||
_logger.Error<ClientDependencyConfiguration>(ex, "Could not get path from ClientDependency.config");
|
||||
}
|
||||
|
||||
var success = true;
|
||||
foreach (var directory in cdfTempDirectories)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
continue;
|
||||
|
||||
Directory.Delete(directory, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Something could be locking the directory or the was another error, making sure we don't break the upgrade installer
|
||||
_logger.Error<ClientDependencyConfiguration>(ex, "Could not clear temp files");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
182
src/Umbraco.Web/WebAssets/CDF/ClientDependencyRuntimeMinifier.cs
Normal file
182
src/Umbraco.Web/WebAssets/CDF/ClientDependencyRuntimeMinifier.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/Umbraco.Web/WebAssets/CDF/DependencyPathRenderer.cs
Normal file
49
src/Umbraco.Web/WebAssets/CDF/DependencyPathRenderer.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using ClientDependency.Core;
|
||||
using ClientDependency.Core.FileRegistration.Providers;
|
||||
|
||||
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
|
||||
/// </summary>
|
||||
public class DependencyPathRenderer : StandardRenderer
|
||||
{
|
||||
public override string Name
|
||||
{
|
||||
get { return "Umbraco.DependencyPathRenderer"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to delimit each dependency so we can split later
|
||||
/// </summary>
|
||||
public const string Delimiter = "||||";
|
||||
|
||||
/// <summary>
|
||||
/// Override because the StandardRenderer replaces & with & but we don't want that so we'll reverse it
|
||||
/// </summary>
|
||||
/// <param name="allDependencies"></param>
|
||||
/// <param name="paths"></param>
|
||||
/// <param name="jsOutput"></param>
|
||||
/// <param name="cssOutput"></param>
|
||||
/// <param name="http"></param>
|
||||
public override void RegisterDependencies(List<IClientDependencyFile> allDependencies, HashSet<IClientDependencyPath> paths, out string jsOutput, out string cssOutput, HttpContextBase http)
|
||||
{
|
||||
base.RegisterDependencies(allDependencies, paths, out jsOutput, out cssOutput, http);
|
||||
|
||||
jsOutput = jsOutput.Replace("&", "&");
|
||||
cssOutput = cssOutput.Replace("&", "&");
|
||||
}
|
||||
|
||||
protected override string RenderSingleJsFile(string js, IDictionary<string, string> htmlAttributes)
|
||||
{
|
||||
return js + Delimiter;
|
||||
}
|
||||
|
||||
protected override string RenderSingleCssFile(string css, IDictionary<string, string> htmlAttributes)
|
||||
{
|
||||
return css + Delimiter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Web.UI;
|
||||
using ClientDependency.Core.Controls;
|
||||
using ClientDependency.Core.FileRegistration.Providers;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Web.WebAssets.CDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to load in all client dependencies for Umbraco.
|
||||
/// Ensures that both UmbracoClient and UmbracoRoot paths are added to the loader.
|
||||
/// </summary>
|
||||
public class UmbracoClientDependencyLoader : ClientDependencyLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the defaults
|
||||
/// </summary>
|
||||
public UmbracoClientDependencyLoader(IGlobalSettings globalSettings, IIOHelper ioHelper)
|
||||
: base()
|
||||
{
|
||||
this.AddPath("UmbracoRoot", ioHelper.ResolveUrl(globalSettings.UmbracoPath));
|
||||
this.ProviderName = LoaderControlProvider.DefaultName;
|
||||
|
||||
}
|
||||
|
||||
public static ClientDependencyLoader TryCreate(Control parent, out bool isNew, IGlobalSettings globalSettings, IIOHelper ioHelper)
|
||||
{
|
||||
if (ClientDependencyLoader.Instance == null)
|
||||
{
|
||||
var loader = new UmbracoClientDependencyLoader(globalSettings, ioHelper);
|
||||
parent.Controls.Add(loader);
|
||||
isNew = true;
|
||||
return loader;
|
||||
}
|
||||
else
|
||||
{
|
||||
isNew = false;
|
||||
return ClientDependencyLoader.Instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user