@Html.NopCssFiles(ResourceLocation.Footer)
@Html.NopScripts(ResourceLocation.Footer)
@Html.NopInlineScripts(ResourceLocation.Footer)
=>Nop.Web.Framework.UI->class LayoutExtensions
using System.Linq;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.WebUtilities;
using Nop.Core.Infrastructure;
namespace Nop.Web.Framework.UI
{
/// <summary>
/// Layout extensions
/// </summary>
public static class LayoutExtensions
{
/// <summary>
/// Append CSS class to the <![CDATA[<head>]]> element
/// </summary>
/// <param name="html">HTML helper</param>
/// <param name="part">CSS class</param>
public static void AppendPageCssClassParts(this IHtmlHelper html, string part)
{
var pageHeadBuilder = EngineContext.Current.Resolve<IPageHeadBuilder>();
pageHeadBuilder.AppendPageCssClassParts(part);
}
/// <summary>
/// Generate all title parts
/// </summary>
/// <param name="html">HTML helper</param>
/// <param name="part">CSS class</param>
/// <param name="includeClassElement">A value indicating whether to include "class" attributes</param>
/// <returns>Generated string</returns>
public static IHtmlContent NopPageCssClasses(this IHtmlHelper html, string part = "", bool includeClassElement = true)
{
var pageHeadBuilder = EngineContext.Current.Resolve<IPageHeadBuilder>();
html.AppendPageCssClassParts(part);
var classes = pageHeadBuilder.GeneratePageCssClasses();
if (string.IsNullOrEmpty(classes))
return null;
var result = includeClassElement ? $"class=\"{classes}\"" : classes;
return new HtmlString(result);
}
/// <summary>
/// Generate all CSS parts
/// </summary>
/// <param name="html">HTML helper</param>
/// <param name="location">A location of the script element</param>
/// <param name="bundleFiles">A value indicating whether to bundle script elements</param>
/// <returns>Generated string</returns>
public static IHtmlContent NopCssFiles(this IHtmlHelper html, ResourceLocation location, bool? bundleFiles = null)
{
var pageHeadBuilder = EngineContext.Current.Resolve<IPageHeadBuilder>();
return new HtmlString(pageHeadBuilder.GenerateCssFiles(location, bundleFiles));
}
}
=>Nop.Web.Framework.UI->class PageHeadBuilder
namespace Nop.Web.Framework.UI
{
/// <summary>
/// Page head builder
/// </summary>
public partial class PageHeadBuilder : IPageHeadBuilder
{
#region Fields
private static readonly object _lock = new object();
private readonly BundleFileProcessor _processor;
private readonly CachingSettings _cachingSettings;
private readonly CommonSettings _commonSettings;
private readonly IActionContextAccessor _actionContextAccessor;
private readonly ICacheKeyService _cacheKeyService;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly INopFileProvider _fileProvider;
private readonly IStaticCacheManager _staticCacheManager;
private readonly IUrlHelperFactory _urlHelperFactory;
private readonly IUrlRecordService _urlRecordService;
private readonly SeoSettings _seoSettings;
private readonly List<string> _titleParts;
private readonly List<string> _metaDescriptionParts;
private readonly List<string> _metaKeywordParts;
private readonly Dictionary<ResourceLocation, List<ScriptReferenceMeta>> _scriptParts;
private readonly Dictionary<ResourceLocation, List<string>> _inlineScriptParts;
private readonly Dictionary<ResourceLocation, List<CssReferenceMeta>> _cssParts;
private readonly List<string> _canonicalUrlParts;
private readonly List<string> _headCustomParts;
private readonly List<string> _pageCssClassParts;
private string _activeAdminMenuSystemName;
private string _editPageUrl;
#endregion
/// Generate all CSS parts
/// </summary>
/// <param name="location">A location of the script element</param>
/// <param name="bundleFiles">A value indicating whether to bundle script elements</param>
/// <returns>Generated string</returns>
public virtual string GenerateCssFiles(ResourceLocation location, bool? bundleFiles = null)
{
if (!_cssParts.ContainsKey(location) || _cssParts[location] == null)
return "";
if (!_cssParts.Any())
return "";
var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext);
var debugModel = _webHostEnvironment.IsDevelopment();
if (!bundleFiles.HasValue)
{
//use setting if no value is specified
bundleFiles = _commonSettings.EnableCssBundling;
}
//CSS bundling is not allowed in virtual directories
if (urlHelper.ActionContext.HttpContext.Request.PathBase.HasValue)
bundleFiles = false;
if (bundleFiles.Value)
{
var partsToBundle = _cssParts[location]
.Where(x => !x.ExcludeFromBundle)
.Distinct()
.ToArray();
var partsToDontBundle = _cssParts[location]
.Where(x => x.ExcludeFromBundle)
.Distinct()
.ToArray();
var result = new StringBuilder();
//parts to bundle
if (partsToBundle.Any())
{
//ensure \bundles directory exists
_fileProvider.CreateDirectory(_fileProvider.GetAbsolutePath("bundles"));
var bundle = new Bundle();
foreach (var item in partsToBundle)
{
new PathString(urlHelper.Content(debugModel ? item.DebugSrc : item.Src))
.StartsWithSegments(urlHelper.ActionContext.HttpContext.Request.PathBase, out PathString path);
var src = path.Value.TrimStart('/');
//check whether this file exists
if (!_fileProvider.FileExists(_fileProvider.MapPath(path)))
src = _fileProvider.Combine(_webHostEnvironment.WebRootPath, _fileProvider.Combine(src.Split("/").ToArray()));
else
src = _fileProvider.MapPath(path);
bundle.InputFiles.Add(src);
}
//output file
var outputFileName = GetBundleFileName(partsToBundle.Select(x => { return debugModel ? x.DebugSrc : x.Src; }).ToArray());
bundle.OutputFileName = _fileProvider.Combine(_webHostEnvironment.WebRootPath, "bundles", outputFileName + ".css");
//save
var configFilePath = _fileProvider.MapPath($"/{outputFileName}.json");
bundle.FileName = configFilePath;
//performance optimization. do not bundle and minify for each HTTP request
//we periodically re-check already bundles file
//so if we have minification enabled, it could take up to several minutes to see changes in updated resource files (or just reset the cache or restart the site)
var cacheKey = new CacheKey($"Nop.minification.shouldrebuild.css-{outputFileName}")
{
CacheTime = _cachingSettings.BundledFilesCacheTime
};
var shouldRebuild = _staticCacheManager.Get(_cacheKeyService.PrepareKey(cacheKey), () => true);
if (shouldRebuild)
{
lock (_lock)
{
//store json file to see a generated config file (for debugging purposes)
//BundleHandler.AddBundle(configFilePath, bundle);
//process
_processor.Process(configFilePath, new List<Bundle> {bundle});
}
_staticCacheManager.Set(cacheKey, false);
}
//render
result.AppendFormat("<link href=\"{0}\" rel=\"stylesheet\" type=\"{1}\" />", urlHelper.Content("~/bundles/" + outputFileName + ".min.css"), MimeTypes.TextCss);
result.Append(Environment.NewLine);
}
//parts not to bundle
foreach (var item in partsToDontBundle)
{
var src = debugModel ? item.DebugSrc : item.Src;
result.AppendFormat("<link href=\"{0}\" rel=\"stylesheet\" type=\"{1}\" />", urlHelper.Content(src), MimeTypes.TextCss);
result.Append(Environment.NewLine);
}
return result.ToString();
}
else
{
//bundling is disabled
var result = new StringBuilder();
foreach (var item in _cssParts[location].Distinct())
{
var src = debugModel ? item.DebugSrc : item.Src;
result.AppendFormat("<link href=\"{0}\" rel=\"stylesheet\" type=\"{1}\" />", urlHelper.Content(src), MimeTypes.TextCss);
result.AppendLine();
}
return result.ToString();
}
}