#16705: Themes may now override stylesheets alone by filename.

--HG--
branch : dev
This commit is contained in:
Dave Reed
2010-12-03 15:53:27 -08:00
parent f89550b7df
commit 7b4025b8cb
8 changed files with 350 additions and 39 deletions

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.DisplayManagement.Descriptors;
using Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy;
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.VirtualPath;
namespace Orchard.Tests.DisplayManagement.Descriptors {
[TestFixture]
public class StylesheetBindingStrategyTests : ContainerTestBase {
private ShellDescriptor _descriptor;
private IList<FeatureDescriptor> _features;
private TestViewEngine _testViewEngine;
private TestVirtualPathProvider _testVirtualPathProvider;
protected override void Register(Autofac.ContainerBuilder builder) {
_descriptor = new ShellDescriptor { };
_testViewEngine = new TestViewEngine();
_testVirtualPathProvider = new TestVirtualPathProvider();
builder.Register(ctx => _descriptor);
builder.RegisterType<StylesheetBindingStrategy>().As<IShapeTableProvider>();
builder.RegisterInstance(_testViewEngine).As<IShapeTemplateViewEngine>();
builder.RegisterInstance(_testVirtualPathProvider).As<IVirtualPathProvider>();
var extensionManager = new Mock<IExtensionManager>();
builder.Register(ctx => extensionManager);
builder.Register(ctx => extensionManager.Object);
}
public class TestViewEngine : Dictionary<string, object>, IShapeTemplateViewEngine {
public IEnumerable<string> DetectTemplateFileNames(IEnumerable<string> fileNames) {
return fileNames;
}
}
public class TestVirtualPathProvider : IVirtualPathProvider {
public string Combine(params string[] paths) {
throw new NotImplementedException();
}
public string ToAppRelative(string virtualPath) {
throw new NotImplementedException();
}
public string MapPath(string virtualPath) {
throw new NotImplementedException();
}
public bool FileExists(string virtualPath) {
throw new NotImplementedException();
}
public Stream OpenFile(string virtualPath) {
throw new NotImplementedException();
}
public StreamWriter CreateText(string virtualPath) {
throw new NotImplementedException();
}
public Stream CreateFile(string virtualPath) {
throw new NotImplementedException();
}
public DateTime GetFileLastWriteTimeUtc(string virtualPath) {
throw new NotImplementedException();
}
public bool DirectoryExists(string virtualPath) {
throw new NotImplementedException();
}
public void CreateDirectory(string virtualPath) {
throw new NotImplementedException();
}
public string GetDirectoryName(string virtualPath) {
throw new NotImplementedException();
}
public IEnumerable<string> ListFiles(string path) {
return new List<string> {"~/Modules/Alpha/Styles/AlphaStyle.css"};
}
public IEnumerable<string> ListDirectories(string path) {
throw new NotImplementedException();
}
}
protected override void Resolve(ILifetimeScope container) {
_features = new List<FeatureDescriptor>();
container.Resolve<Mock<IExtensionManager>>()
.Setup(em => em.AvailableFeatures())
.Returns(_features);
}
void AddFeature(string name, params string[] dependencies) {
var featureDescriptor = new FeatureDescriptor {
Id = name,
Dependencies = dependencies,
Extension = new ExtensionDescriptor {
Id = name,
Location = "~/Modules"
}
};
featureDescriptor.Extension.Features = new[] { featureDescriptor };
_features.Add(featureDescriptor);
}
void AddEnabledFeature(string name, params string[] dependencies) {
AddFeature(name, dependencies);
_descriptor.Features = _descriptor.Features.Concat(new[] { new ShellFeature { Name = name } });
}
[Test]
public void TemplateResolutionWorks() {
AddEnabledFeature("Alpha");
_testViewEngine.Add("~/Modules/Alpha/Styles/AlphaShape.css", null);
var strategy = _container.Resolve<IShapeTableProvider>();
IList<ShapeAlterationBuilder> alterationBuilders = new List<ShapeAlterationBuilder>();
var builder = new ShapeTableBuilder(alterationBuilders,null);
strategy.Discover(builder);
var alterations = alterationBuilders.Select(alterationBuilder=>alterationBuilder.Build());
Assert.That(alterations.Any(alteration => alteration.ShapeType == "Style"));
}
}
}

View File

@@ -212,6 +212,7 @@
<Compile Include="DisplayManagement\DefaultDisplayManagerTests.cs" /> <Compile Include="DisplayManagement\DefaultDisplayManagerTests.cs" />
<Compile Include="ContainerTestBase.cs" /> <Compile Include="ContainerTestBase.cs" />
<Compile Include="DisplayManagement\Descriptors\BasicShapeTemplateHarvesterTests.cs" /> <Compile Include="DisplayManagement\Descriptors\BasicShapeTemplateHarvesterTests.cs" />
<Compile Include="DisplayManagement\Descriptors\StylesheetBindingStrategyTests.cs" />
<Compile Include="DisplayManagement\Descriptors\DefaultShapeTableManagerTests.cs" /> <Compile Include="DisplayManagement\Descriptors\DefaultShapeTableManagerTests.cs" />
<Compile Include="DisplayManagement\Descriptors\InMemoryWebSiteFolder.cs" /> <Compile Include="DisplayManagement\Descriptors\InMemoryWebSiteFolder.cs" />
<Compile Include="DisplayManagement\Descriptors\PlacementFileParserTests.cs" /> <Compile Include="DisplayManagement\Descriptors\PlacementFileParserTests.cs" />

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -8,6 +9,8 @@ using System.Web.Mvc;
using System.Web.Mvc.Html; using System.Web.Mvc.Html;
using Orchard.DisplayManagement; using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors; using Orchard.DisplayManagement.Descriptors;
using Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy;
using Orchard.Mvc;
using Orchard.Settings; using Orchard.Settings;
using Orchard.UI; using Orchard.UI;
using Orchard.UI.Resources; using Orchard.UI.Resources;
@@ -19,11 +22,20 @@ using Orchard.Utility.Extensions;
namespace Orchard.Core.Shapes { namespace Orchard.Core.Shapes {
public class CoreShapes : IShapeTableProvider { public class CoreShapes : IShapeTableProvider {
private readonly IWorkContextAccessor _workContextAccessor; private readonly IWorkContextAccessor _workContextAccessor;
private readonly IHttpContextAccessor _httpContextAccessor;
public CoreShapes(IWorkContextAccessor workContextAccessor) { public CoreShapes(IWorkContextAccessor workContextAccessor, IHttpContextAccessor httpContextAccessor) {
// needed to get CurrentSite. // needed to get CurrentSite.
// note that injecting ISiteService here causes a stack overflow in AutoFac! // note that injecting ISiteService here causes a stack overflow in AutoFac!
_workContextAccessor = workContextAccessor; _workContextAccessor = workContextAccessor;
_httpContextAccessor = httpContextAccessor;
}
// not injected the usual way because this component is a 'static' dependency and RM is per-request
private IResourceManager ResourceManager {
get {
return _workContextAccessor.GetContext(_httpContextAccessor.Current()).Resolve<IResourceManager>();
}
} }
public void Discover(ShapeTableBuilder builder) { public void Discover(ShapeTableBuilder builder) {
@@ -82,6 +94,26 @@ namespace Orchard.Core.Shapes {
list.ItemClasses = new List<string>(); list.ItemClasses = new List<string>();
list.ItemAttributes = new Dictionary<string, string>(); list.ItemAttributes = new Dictionary<string, string>();
}); });
builder.Describe("Style")
.OnDisplaying(displaying => {
var resource = displaying.Shape;
string url = resource.Url;
string fileName = StylesheetBindingStrategy.GetAlternateShapeNameFromFileName(url);
if (!string.IsNullOrEmpty(fileName)) {
resource.Metadata.Alternates.Add("Style__" + fileName);
}
});
builder.Describe("Resource")
.OnDisplaying(displaying => {
var resource = displaying.Shape;
string url = resource.Url;
string fileName = StylesheetBindingStrategy.GetAlternateShapeNameFromFileName(url);
if (!string.IsNullOrEmpty(fileName)) {
resource.Metadata.Alternates.Add("Resource__" + fileName);
}
});
} }
@@ -159,51 +191,58 @@ namespace Orchard.Core.Shapes {
#endregion #endregion
[Shape] [Shape]
public void HeadScripts(HtmlHelper Html, IResourceManager ResourceManager) { public void HeadScripts(dynamic Display, TextWriter Output) {
WriteResources(Html, _workContextAccessor.GetContext(Html.ViewContext).CurrentSite, WriteResources(Display, Output, "script", ResourceLocation.Head, null);
ResourceManager, "script", ResourceLocation.Head, null); WriteLiteralScripts(Output, ResourceManager.GetRegisteredHeadScripts());
WriteLiteralScripts(Html, ResourceManager.GetRegisteredHeadScripts());
} }
[Shape] [Shape]
public void FootScripts(HtmlHelper Html, IResourceManager ResourceManager) { public void FootScripts(dynamic Display, TextWriter Output) {
WriteResources(Html, _workContextAccessor.GetContext(Html.ViewContext).CurrentSite, WriteResources(Display, Output, "script", null, ResourceLocation.Head);
ResourceManager, "script", null, ResourceLocation.Head); WriteLiteralScripts(Output, ResourceManager.GetRegisteredFootScripts());
WriteLiteralScripts(Html, ResourceManager.GetRegisteredFootScripts());
} }
[Shape] [Shape]
public void Metas(HtmlHelper Html, IResourceManager ResourceManager) { public void Metas(TextWriter Output) {
foreach (var meta in ResourceManager.GetRegisteredMetas()) { foreach (var meta in ResourceManager.GetRegisteredMetas()) {
Html.ViewContext.Writer.WriteLine(meta.GetTag()); Output.WriteLine(meta.GetTag());
} }
} }
[Shape] [Shape]
public void HeadLinks(HtmlHelper Html, IResourceManager ResourceManager) { public void HeadLinks(TextWriter Output) {
foreach (var link in ResourceManager.GetRegisteredLinks()) { foreach (var link in ResourceManager.GetRegisteredLinks()) {
Html.ViewContext.Writer.WriteLine(link.GetTag()); Output.WriteLine(link.GetTag());
} }
} }
[Shape] [Shape]
public void StylesheetLinks(HtmlHelper Html, IResourceManager ResourceManager) { public void StylesheetLinks(dynamic Display, TextWriter Output) {
WriteResources(Html, _workContextAccessor.GetContext(Html.ViewContext).CurrentSite, WriteResources(Display, Output, "stylesheet", null, null);
ResourceManager, "stylesheet", null, null);
} }
private static void WriteLiteralScripts(HtmlHelper html, IEnumerable<string> scripts) { [Shape]
public void Style(TextWriter Output, ResourceDefinition Resource, string Url, string Condition) {
UI.Resources.ResourceManager.WriteResource(Output, Resource, Url, Condition);
}
[Shape]
public void Resource(TextWriter Output, ResourceDefinition Resource, string Url, string Condition) {
UI.Resources.ResourceManager.WriteResource(Output, Resource, Url, Condition);
}
private static void WriteLiteralScripts(TextWriter output, IEnumerable<string> scripts) {
if (scripts == null) { if (scripts == null) {
return; return;
} }
var writer = html.ViewContext.Writer;
foreach (string script in scripts) { foreach (string script in scripts) {
writer.WriteLine(script); output.WriteLine(script);
} }
} }
private static void WriteResources(HtmlHelper html, ISite site, IResourceManager rm, string resourceType, ResourceLocation? includeLocation, ResourceLocation? excludeLocation) { private void WriteResources(dynamic Display, TextWriter Output, string resourceType, ResourceLocation? includeLocation, ResourceLocation? excludeLocation) {
bool debugMode; bool debugMode;
var site = _workContextAccessor.GetContext(_httpContextAccessor.Current()).CurrentSite;
switch (site.ResourceDebugMode) { switch (site.ResourceDebugMode) {
case ResourceDebugMode.Enabled: case ResourceDebugMode.Enabled:
debugMode = true; debugMode = true;
@@ -213,26 +252,29 @@ namespace Orchard.Core.Shapes {
break; break;
default: default:
Debug.Assert(site.ResourceDebugMode == ResourceDebugMode.FromAppSetting, "Unknown ResourceDebugMode value."); Debug.Assert(site.ResourceDebugMode == ResourceDebugMode.FromAppSetting, "Unknown ResourceDebugMode value.");
debugMode = html.ViewContext.HttpContext.IsDebuggingEnabled; debugMode = _httpContextAccessor.Current().IsDebuggingEnabled;
break; break;
} }
var defaultSettings = new RequireSettings { var defaultSettings = new RequireSettings {
DebugMode = debugMode, DebugMode = debugMode,
Culture = CultureInfo.CurrentUICulture.Name, Culture = CultureInfo.CurrentUICulture.Name,
}; };
var requiredResources = rm.BuildRequiredResources(resourceType); var requiredResources = ResourceManager.BuildRequiredResources(resourceType);
var appPath = html.ViewContext.HttpContext.Request.ApplicationPath; var appPath = _httpContextAccessor.Current().Request.ApplicationPath;
foreach (var context in requiredResources.Where(r => foreach (var context in requiredResources.Where(r =>
(includeLocation.HasValue ? r.Settings.Location == includeLocation.Value : true) && (includeLocation.HasValue ? r.Settings.Location == includeLocation.Value : true) &&
(excludeLocation.HasValue ? r.Settings.Location != excludeLocation.Value : true))) { (excludeLocation.HasValue ? r.Settings.Location != excludeLocation.Value : true))) {
var path = context.GetResourceUrl(defaultSettings, appPath);
var condition = context.Settings.Condition; var condition = context.Settings.Condition;
if (!string.IsNullOrEmpty(condition)) { IHtmlString result;
html.ViewContext.Writer.WriteLine("<!--[if " + condition + "]>"); if (resourceType == "stylesheet") {
result = Display.Style(Url: path, Condition: condition, Resource: context.Resource);
} }
html.ViewContext.Writer.WriteLine(context.GetTagBuilder(defaultSettings, appPath).ToString(context.Resource.TagRenderMode)); else {
if (!string.IsNullOrEmpty(condition)) { result = Display.Resource(Url: path, Condition: condition, Resource: context.Resource);
html.ViewContext.Writer.WriteLine("<![endif]-->");
} }
Output.Write(result);
} }
} }

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.VirtualPath;
using Orchard.UI.Resources;
namespace Orchard.DisplayManagement.Descriptors.ResourceBindingStrategy {
// discovers .css files and turns them into Style__<filename> shapes.
public class StylesheetBindingStrategy : IShapeTableProvider {
private readonly IExtensionManager _extensionManager;
private readonly ShellDescriptor _shellDescriptor;
private readonly IVirtualPathProvider _virtualPathProvider;
private static readonly Regex _safeName = new Regex(@"[/:?#\[\]@!&'()*+,;=\s\""<>\.\-_]+", RegexOptions.Compiled);
public StylesheetBindingStrategy(IExtensionManager extensionManager, ShellDescriptor shellDescriptor, IVirtualPathProvider virtualPathProvider) {
_extensionManager = extensionManager;
_shellDescriptor = shellDescriptor;
_virtualPathProvider = virtualPathProvider;
}
private static string SafeName(string name) {
if (string.IsNullOrWhiteSpace(name))
return String.Empty;
return _safeName.Replace(name, String.Empty);
}
public static string GetAlternateShapeNameFromFileName(string fileName) {
if (fileName == null) {
throw new ArgumentNullException("fileName");
}
string shapeName;
if (Uri.IsWellFormedUriString(fileName, UriKind.Absolute)) {
var uri = new Uri(fileName);
shapeName = uri.Authority + "$" + uri.AbsolutePath + "$" + uri.Query;
}
else {
shapeName = Path.GetFileNameWithoutExtension(fileName);
}
return SafeName(shapeName);
}
private static IEnumerable<ExtensionDescriptor> Once(IEnumerable<FeatureDescriptor> featureDescriptors) {
var once = new ConcurrentDictionary<string, object>();
return featureDescriptors.Select(fd => fd.Extension).Where(ed => once.TryAdd(ed.Id, null)).ToList();
}
public void Discover(ShapeTableBuilder builder) {
var availableFeatures = _extensionManager.AvailableFeatures();
var activeFeatures = availableFeatures.Where(FeatureIsEnabled);
var activeExtensions = Once(activeFeatures);
var hits = activeExtensions.SelectMany(extensionDescriptor => {
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
var virtualPath = Path.Combine(basePath, "Styles").Replace(Path.DirectorySeparatorChar, '/');
var shapes = _virtualPathProvider.ListFiles(virtualPath)
.Select(Path.GetFileName)
.Where(fileName => string.Equals(Path.GetExtension(fileName), ".css", System.StringComparison.OrdinalIgnoreCase))
.Select(cssFileName => new {
fileName = Path.GetFileNameWithoutExtension(cssFileName),
fileVirtualPath = Path.Combine(virtualPath, cssFileName).Replace(Path.DirectorySeparatorChar, '/'),
shapeType = "Style__" + GetAlternateShapeNameFromFileName(cssFileName),
extensionDescriptor
});
return shapes;
});
foreach (var iter in hits) {
var hit = iter;
var featureDescriptors = hit.extensionDescriptor.Features.Where(fd => fd.Id == hit.extensionDescriptor.Id);
foreach (var featureDescriptor in featureDescriptors) {
builder.Describe(iter.shapeType)
.From(new Feature {Descriptor = featureDescriptor})
.BoundAs(
hit.fileVirtualPath,
shapeDescriptor => displayContext => {
var shape = ((dynamic) displayContext.Value);
var output = displayContext.ViewContext.Writer;
ResourceDefinition resource = shape.Resource;
string condition = shape.Condition;
ResourceManager.WriteResource(output, resource, hit.fileVirtualPath, condition);
return null;
});
}
}
}
private bool FeatureIsEnabled(FeatureDescriptor fd) {
return (DefaultExtensionTypes.IsTheme(fd.Extension.ExtensionType) && (fd.Id == "TheAdmin" || fd.Id == "SafeMode")) ||
_shellDescriptor.Features.Any(sf => sf.Name == fd.Id);
}
}
}

View File

@@ -142,6 +142,7 @@
<Compile Include="ContentManagement\DefaultContentDisplay.cs" /> <Compile Include="ContentManagement\DefaultContentDisplay.cs" />
<Compile Include="ContentManagement\Drivers\ContentShapeResult.cs" /> <Compile Include="ContentManagement\Drivers\ContentShapeResult.cs" />
<Compile Include="ContentManagement\Handlers\BuildShapeContext.cs" /> <Compile Include="ContentManagement\Handlers\BuildShapeContext.cs" />
<Compile Include="DisplayManagement\Descriptors\ResourceBindingStrategy\StylesheetBindingStrategy.cs" />
<Compile Include="DisplayManagement\Descriptors\ShapeDescriptor.cs" /> <Compile Include="DisplayManagement\Descriptors\ShapeDescriptor.cs" />
<Compile Include="DisplayManagement\Descriptors\ShapeAlteration.cs" /> <Compile Include="DisplayManagement\Descriptors\ShapeAlteration.cs" />
<Compile Include="DisplayManagement\Descriptors\ShapeAlterationBuilder.cs" /> <Compile Include="DisplayManagement\Descriptors\ShapeAlterationBuilder.cs" />

View File

@@ -4,20 +4,16 @@ using Orchard.Mvc.Filters;
namespace Orchard.UI.Resources { namespace Orchard.UI.Resources {
public class ResourceFilter : FilterProvider, IResultFilter { public class ResourceFilter : FilterProvider, IResultFilter {
private readonly IResourceManager _resourceManager;
private readonly IWorkContextAccessor _workContextAccessor; private readonly IWorkContextAccessor _workContextAccessor;
private readonly dynamic _shapeFactory; private readonly dynamic _shapeFactory;
public ResourceFilter( public ResourceFilter(
IResourceManager resourceManager,
IWorkContextAccessor workContextAccessor, IWorkContextAccessor workContextAccessor,
IShapeFactory shapeFactory) { IShapeFactory shapeFactory) {
_resourceManager = resourceManager;
_workContextAccessor = workContextAccessor; _workContextAccessor = workContextAccessor;
_shapeFactory = shapeFactory; _shapeFactory = shapeFactory;
} }
public void OnResultExecuting(ResultExecutingContext filterContext) { public void OnResultExecuting(ResultExecutingContext filterContext) {
// should only run on a full view rendering result // should only run on a full view rendering result
if (!(filterContext.Result is ViewResult)) if (!(filterContext.Result is ViewResult))
@@ -26,11 +22,11 @@ namespace Orchard.UI.Resources {
var ctx = _workContextAccessor.GetContext(); var ctx = _workContextAccessor.GetContext();
var head = ctx.Layout.Head; var head = ctx.Layout.Head;
var tail = ctx.Layout.Tail; var tail = ctx.Layout.Tail;
head.Add(_shapeFactory.Metas().ResourceManager(_resourceManager)); head.Add(_shapeFactory.Metas());
head.Add(_shapeFactory.HeadLinks().ResourceManager(_resourceManager)); head.Add(_shapeFactory.HeadLinks());
head.Add(_shapeFactory.StylesheetLinks().ResourceManager(_resourceManager)); head.Add(_shapeFactory.StylesheetLinks());
head.Add(_shapeFactory.HeadScripts().ResourceManager(_resourceManager)); head.Add(_shapeFactory.HeadScripts());
tail.Add(_shapeFactory.FootScripts().ResourceManager(_resourceManager)); tail.Add(_shapeFactory.FootScripts());
} }
public void OnResultExecuted(ResultExecutedContext filterContext) { public void OnResultExecuted(ResultExecutedContext filterContext) {

View File

@@ -3,8 +3,10 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc;
using Autofac.Features.Metadata; using Autofac.Features.Metadata;
using Orchard.Environment.Extensions.Models; using Orchard.Environment.Extensions.Models;
@@ -40,6 +42,30 @@ namespace Orchard.UI.Resources {
return resourcePath; return resourcePath;
} }
private static TagBuilder GetTagBuilder(ResourceDefinition resource, string url) {
var tagBuilder = new TagBuilder(resource.TagName);
tagBuilder.MergeAttributes(resource.TagBuilder.Attributes);
if (!String.IsNullOrEmpty(resource.FilePathAttributeName)) {
if (!String.IsNullOrEmpty(url)) {
if (VirtualPathUtility.IsAppRelative(url)) {
url = VirtualPathUtility.ToAbsolute(url);
}
tagBuilder.MergeAttribute(resource.FilePathAttributeName, url, true);
}
}
return tagBuilder;
}
public static void WriteResource(TextWriter writer, ResourceDefinition resource, string url, string condition) {
if (!string.IsNullOrEmpty(condition)) {
writer.WriteLine("<!--[if " + condition + "]>");
}
writer.WriteLine(GetTagBuilder(resource, url).ToString(resource.TagRenderMode));
if (!string.IsNullOrEmpty(condition)) {
writer.WriteLine("<![endif]-->");
}
}
public ResourceManager(IEnumerable<Meta<IResourceManifestProvider>> resourceProviders) { public ResourceManager(IEnumerable<Meta<IResourceManifestProvider>> resourceProviders) {
_providers = resourceProviders; _providers = resourceProviders;
} }

View File

@@ -6,11 +6,15 @@ namespace Orchard.UI.Resources {
public ResourceDefinition Resource { get; set; } public ResourceDefinition Resource { get; set; }
public RequireSettings Settings { get; set; } public RequireSettings Settings { get; set; }
public string GetResourceUrl(RequireSettings baseSettings, string appPath) {
return Resource.ResolveUrl(baseSettings == null ? Settings : baseSettings.Combine(Settings), appPath);
}
public TagBuilder GetTagBuilder(RequireSettings baseSettings, string appPath) { public TagBuilder GetTagBuilder(RequireSettings baseSettings, string appPath) {
var tagBuilder = new TagBuilder(Resource.TagName); var tagBuilder = new TagBuilder(Resource.TagName);
tagBuilder.MergeAttributes(Resource.TagBuilder.Attributes); tagBuilder.MergeAttributes(Resource.TagBuilder.Attributes);
if (!String.IsNullOrEmpty(Resource.FilePathAttributeName)) { if (!String.IsNullOrEmpty(Resource.FilePathAttributeName)) {
var resolvedUrl = Resource.ResolveUrl(baseSettings == null ? Settings : baseSettings.Combine(Settings), appPath); var resolvedUrl = GetResourceUrl(baseSettings, appPath);
if (!String.IsNullOrEmpty(resolvedUrl)) { if (!String.IsNullOrEmpty(resolvedUrl)) {
tagBuilder.MergeAttribute(Resource.FilePathAttributeName, resolvedUrl, true); tagBuilder.MergeAttribute(Resource.FilePathAttributeName, resolvedUrl, true);
} }