private ResourceDefinition FindResource(RequireSettings settings, bool resolveInlineDefinitions) { // find the resource with the given type and name // that has at least the given version number. If multiple, // return the resource with the greatest version number. // If not found and an inlineDefinition is given, define the resource on the fly // using the action. var name = settings.Name ?? ""; var type = settings.Type; var stream = ResourceManifests.SelectMany(x => x.GetResources(type)); var resource = FindMatchingResource(stream, settings, name); if (resource == null && _dynamicManifest != null) { stream = _dynamicManifest.GetResources(type); resource = FindMatchingResource(stream, settings, name); } if (resolveInlineDefinitions && resource == null) { // Does not seem to exist, but it's possible it is being // defined by a Define() from a RequireSettings somewhere. if (ResolveInlineDefinitions(settings.Type)) { // if any were defined, now try to find it resource = FindResource(settings, false); } } return(resource); }
public RequireSettings RegisterResource(string resourceType, string resourceName) { if (resourceType == null) { return(ThrowArgumentNullException <RequireSettings>(nameof(resourceType))); } if (resourceName == null) { return(ThrowArgumentNullException <RequireSettings>(nameof(resourceName))); } var key = new ResourceTypeName(resourceType, resourceName); if (!_required.TryGetValue(key, out var settings)) { settings = new RequireSettings(_options) { Type = resourceType, Name = resourceName }; _required[key] = settings; } _builtResources[resourceType] = null; return(settings); }
public void AddExpandingResource(ResourceDefinition resource, RequireSettings settings) { if (_expanding.Contains(resource)) { throw new InvalidOperationException($"Circular dependency of type '{settings.Type}' detected between '{settings.Name}' and '{resource.Name}'"); } _expanding.Push(resource); }
protected virtual void ExpandDependencies( ResourceDefinition resource, RequireSettings settings, OrderedDictionary allResources) { if (resource == null) { return; } // Settings is given so they can cascade down into dependencies. For example, if Foo depends on Bar, and Foo's required // location is Head, so too should Bar's location. // forge the effective require settings for this resource // (1) If a require exists for the resource, combine with it. Last settings in gets preference for its specified values. // (2) If no require already exists, form a new settings object based on the given one but with its own type/name. settings = allResources.Contains(resource) ? ((RequireSettings)allResources[resource]).Combine(settings) : new RequireSettings(_options) { Type = resource.Type, Name = resource.Name }.Combine(settings); if (resource.Dependencies != null) { // share search instance var tempSettings = new RequireSettings(); for (var i = 0; i < resource.Dependencies.Count; i++) { var d = resource.Dependencies[i]; var idx = d.IndexOf(':'); var name = d; string version = null; if (idx != -1) { name = d.Substring(0, idx); version = d.Substring(idx + 1); } tempSettings.Type = resource.Type; tempSettings.Name = name; tempSettings.Version = version; var dependency = FindResource(tempSettings); if (dependency == null) { continue; } ExpandDependencies(dependency, settings, allResources); } } allResources[resource] = settings; }
private ResourceDefinition FindMatchingResource( IEnumerable <KeyValuePair <string, IList <ResourceDefinition> > > stream, RequireSettings settings, string type, string name) { Version lower = null; Version upper = null; if (!String.IsNullOrEmpty(settings.Version)) { // Specific version, filter lower = GetLowerBoundVersion(settings.Version); upper = GetUpperBoundVersion(settings.Version); } ResourceDefinition resource = null; foreach (var r in stream) { if (String.Equals(r.Key, name, StringComparison.OrdinalIgnoreCase)) { foreach (var resourceDefinition in r.Value) { var version = resourceDefinition.Version != null ? new Version(resourceDefinition.Version) : null; if (lower != null) { if (lower > version || version >= upper) { continue; } } // Use the highest version of all matches if (resource == null || (resourceDefinition.Version != null && new Version(resource.Version) < version)) { resource = resourceDefinition; } } } } return(resource); }
public void RenderStylesheet(IHtmlContentBuilder builder, RequireSettings settings) { var first = true; var styleSheets = this.GetRequiredResources("stylesheet"); foreach (var context in styleSheets) { if (!first) { builder.AppendHtml(Environment.NewLine); } first = false; builder.AppendHtml(context.GetHtmlContent(settings, "/")); } }
public RequireSettings Combine(RequireSettings other) { var settings = (new RequireSettings { Name = Name, Type = Type }).AtLocation(Location).AtLocation(other.Location) .WithBasePath(BasePath).WithBasePath(other.BasePath) .UseCdn(CdnMode).UseCdn(other.CdnMode) .UseDebugMode(DebugMode).UseDebugMode(other.DebugMode) .UseCulture(Culture).UseCulture(other.Culture) .UseCondition(Condition).UseCondition(other.Condition) .UseVersion(Version).UseVersion(other.Version) .Define(InlineDefinition).Define(other.InlineDefinition); settings._attributes = MergeAttributes(other); return(settings); }
private Dictionary <string, string> MergeAttributes(RequireSettings other) { // efficiently merge the two dictionaries, taking into account that one or both may not exist // and that attributes in 'other' should overridde attributes in this, even if the value is null. if (_attributes == null) { return(other._attributes == null ? null : new Dictionary <string, string>(other._attributes)); } if (other._attributes == null) { return(new Dictionary <string, string>(_attributes)); } var mergedAttributes = new Dictionary <string, string>(_attributes); foreach (var pair in other._attributes) { mergedAttributes[pair.Key] = pair.Value; } return(mergedAttributes); }
public void RenderLocalScript(RequireSettings settings, IHtmlContentBuilder builder) { var localScripts = this.GetRequiredResources("script"); var first = true; foreach (var context in localScripts.Where(r => r.Settings.Location == ResourceLocation.Unspecified)) { if (_localScripts.Add(context.Settings.Name) || context.Settings.Name == settings.Name) { if (!first) { builder.AppendHtml(Environment.NewLine); } first = false; builder.AppendHtml(context.GetHtmlContent(_pathBase)); } } }
public void RenderLocalScript(RequireSettings settings, IHtmlContentBuilder builder) { var localScripts = DoGetRequiredResources("script"); var first = true; foreach (var context in localScripts) { if (context.Settings.Location == ResourceLocation.Unspecified && (_localScripts.Add(context.Settings.Name) || context.Settings.Name == settings.Name)) { if (!first) { builder.AppendHtml(System.Environment.NewLine); } first = false; builder.AppendHtml(context.GetHtmlContent(_options.ContentBasePath)); } } }
public IHtmlContent GetHtmlContent(RequireSettings baseSettings, string appPath) { var combinedSettings = baseSettings == null ? Settings : baseSettings.Combine(Settings); var tagBuilder = Resource.GetTagBuilder(combinedSettings, appPath); if (String.IsNullOrEmpty(combinedSettings.Condition)) { return(tagBuilder); } var builder = new HtmlContentBuilder(); if (combinedSettings.Condition == NotIE) { builder.AppendHtml("<!--[if " + combinedSettings.Condition + "]>-->"); } else { builder.AppendHtml("<!--[if " + combinedSettings.Condition + "]>"); } builder.AppendHtml(tagBuilder); if (!string.IsNullOrEmpty(combinedSettings.Condition)) { if (combinedSettings.Condition == NotIE) { builder.AppendHtml("<!--<![endif]-->"); } else { builder.AppendHtml("<![endif]-->"); } } return(builder); }
public void AddExpandedResource(ResourceDefinition resource, RequireSettings settings) { _expanding.Pop(); if (settings.Position != ResourcePosition.ByDependency) { var existing = (RequireSettings)this[resource]; if (existing == null || existing.Position == ResourcePosition.ByDependency) { if (settings.Position == ResourcePosition.First) { FirstCount++; } if (settings.Position == ResourcePosition.Last) { LastCount++; } } } this[resource] = settings; }
protected virtual void ExpandDependencies(ResourceDefinition resource, RequireSettings settings, OrderedDictionary allResources) { if (resource == null) { return; } // Settings is given so they can cascade down into dependencies. For example, if Foo depends on Bar, and Foo's required // location is Head, so too should Bar's location. // forge the effective require settings for this resource // (1) If a require exists for the resource, combine with it. Last settings in gets preference for its specified values. // (2) If no require already exists, form a new settings object based on the given one but with its own type/name. settings = allResources.Contains(resource) ? ((RequireSettings)allResources[resource]).Combine(settings) : new RequireSettings(_options.Value) { Type = resource.Type, Name = resource.Name }.Combine(settings); if (resource.Dependencies != null) { var dependencies = from d in resource.Dependencies let segments = d.Split(':') let name = segments[0] let version = segments.Length > 1 ? segments[1] : null select FindResource(new RequireSettings { Type = resource.Type, Name = name, Version = version }); foreach (var dependency in dependencies) { if (dependency == null) { continue; } ExpandDependencies(dependency, settings, allResources); } } allResources[resource] = settings; }
protected virtual void ExpandDependencies( ResourceDefinition resource, RequireSettings settings, ResourceDictionary allResources) { if (resource == null) { return; } allResources.AddExpandingResource(resource, settings); // Use any additional dependencies from the settings without mutating the resource that is held in a singleton collection. List <string> dependencies = null; if (resource.Dependencies != null) { dependencies = new List <string>(resource.Dependencies); if (settings.Dependencies != null) { dependencies.AddRange(settings.Dependencies); } } else if (settings.Dependencies != null) { dependencies = new List <string>(settings.Dependencies); } // Settings is given so they can cascade down into dependencies. For example, if Foo depends on Bar, and Foo's required // location is Head, so too should Bar's location, similarly, if Foo is First positioned, Bar dependency should be too. // // forge the effective require settings for this resource // (1) If a require exists for the resource, combine with it. Last settings in gets preference for its specified values. // (2) If no require already exists, form a new settings object based on the given one but with its own type/name. var dependencySettings = (((RequireSettings)allResources[resource]) ?.NewAndCombine(settings) ?? new RequireSettings(_options) { Name = resource.Name, Type = resource.Type, Position = resource.Position } .Combine(settings)) .CombinePosition(settings) ; if (dependencies != null) { // share search instance var tempSettings = new RequireSettings(); for (var i = 0; i < dependencies.Count; i++) { var d = dependencies[i]; var idx = d.IndexOf(':'); var name = d; string version = null; if (idx != -1) { name = d.Substring(0, idx); version = d[(idx + 1)..];
public TagBuilder GetTagBuilder(RequireSettings settings, string applicationPath) { string url; // Url priority: if (settings.DebugMode) { url = settings.CdnMode ? Coalesce(UrlCdnDebug, UrlDebug, UrlCdn, Url) : Coalesce(UrlDebug, Url, UrlCdnDebug, UrlCdn); } else { url = settings.CdnMode ? Coalesce(UrlCdn, Url, UrlCdnDebug, UrlDebug) : Coalesce(Url, UrlDebug, UrlCdn, UrlCdnDebug); } if (String.IsNullOrEmpty(url)) { url = null; } if (!String.IsNullOrEmpty(settings.Culture)) { string nearestCulture = FindNearestCulture(settings.Culture); if (!String.IsNullOrEmpty(nearestCulture)) { url = Path.ChangeExtension(url, nearestCulture + Path.GetExtension(url)); } } if (url.StartsWith("~/", StringComparison.Ordinal)) { if (!String.IsNullOrEmpty(_basePath)) { url = _basePath + url.Substring(1); } else { url = applicationPath + url.Substring(1); } } var tagBuilder = new TagBuilder(TagName) { TagRenderMode = TagRenderMode }; if (!String.IsNullOrEmpty(CdnIntegrity) && url != null && url == UrlCdn) { tagBuilder.Attributes["integrity"] = CdnIntegrity; tagBuilder.Attributes["crossorigin"] = "anonymous"; } else if (!String.IsNullOrEmpty(CdnDebugIntegrity) && url != null && url == UrlCdnDebug) { tagBuilder.Attributes["integrity"] = CdnDebugIntegrity; tagBuilder.Attributes["crossorigin"] = "anonymous"; } if (_resourceAttributes.ContainsKey(Type)) { tagBuilder.MergeAttributes(_resourceAttributes[Type]); } if (Attributes != null) { tagBuilder.MergeAttributes(Attributes); } if (settings.HasAttributes) { tagBuilder.MergeAttributes(settings.Attributes); } if (!String.IsNullOrEmpty(FilePathAttributeName)) { if (!String.IsNullOrEmpty(url)) { tagBuilder.MergeAttribute(FilePathAttributeName, url, true); } } return tagBuilder; }
private ResourceDefinition FindResource(RequireSettings settings, bool resolveInlineDefinitions) { // find the resource with the given type and name // that has at least the given version number. If multiple, // return the resource with the greatest version number. // If not found and an inlineDefinition is given, define the resource on the fly // using the action. var name = settings.Name ?? ""; var type = settings.Type; ResourceDefinition resource; var resources = (from p in ResourceManifests from r in p.GetResources(type) where name.Equals(r.Key, StringComparison.OrdinalIgnoreCase) select r.Value).SelectMany(x => x); if (!String.IsNullOrEmpty(settings.Version)) { // Specific version, filter var upper = GetUpperBoundVersion(settings.Version); var lower = GetLowerBoundVersion(settings.Version); resources = from r in resources let version = r.Version != null ? new Version(r.Version) : null where lower <= version && version < upper select r; } // Use the highest version of all matches resource = (from r in resources let version = r.Version != null ? new Version(r.Version) : null orderby version descending select r).FirstOrDefault(); if (resource == null && _dynamicManifest != null) { resources = (from r in _dynamicManifest.GetResources(type) where name.Equals(r.Key, StringComparison.OrdinalIgnoreCase) select r.Value).SelectMany(x => x); if (!String.IsNullOrEmpty(settings.Version)) { // Specific version, filter var upper = GetUpperBoundVersion(settings.Version); var lower = GetLowerBoundVersion(settings.Version); resources = from r in resources let version = r.Version != null ? new Version(r.Version) : null where lower <= version && version < upper select r; } // Use the highest version of all matches resource = (from r in resources let version = r.Version != null ? new Version(r.Version) : null orderby version descending select r).FirstOrDefault(); } if (resolveInlineDefinitions && resource == null) { // Does not seem to exist, but it's possible it is being // defined by a Define() from a RequireSettings somewhere. if (ResolveInlineDefinitions(settings.Type)) { // if any were defined, now try to find it resource = FindResource(settings, false); } } return(resource); }
public ResourceDefinition FindResource(RequireSettings settings) { return(FindResource(settings, true)); }
public TagBuilder GetTagBuilder(RequireSettings settings, string applicationPath, IFileVersionProvider fileVersionProvider) { string url; // Url priority: if (settings.DebugMode) { url = settings.CdnMode ? Coalesce(UrlCdnDebug, UrlDebug, UrlCdn, Url) : Coalesce(UrlDebug, Url, UrlCdnDebug, UrlCdn); } else { url = settings.CdnMode ? Coalesce(UrlCdn, Url, UrlCdnDebug, UrlDebug) : Coalesce(Url, UrlDebug, UrlCdn, UrlCdnDebug); } if (String.IsNullOrEmpty(url)) { url = null; } if (!String.IsNullOrEmpty(settings.Culture)) { string nearestCulture = FindNearestCulture(settings.Culture); if (!String.IsNullOrEmpty(nearestCulture)) { url = Path.ChangeExtension(url, nearestCulture + Path.GetExtension(url)); } } if (url.StartsWith("~/", StringComparison.Ordinal)) { if (!String.IsNullOrEmpty(_basePath)) { url = _basePath + url.Substring(1); } else { url = applicationPath + url.Substring(1); } } // If settings has value, it can override resource definition, otherwise use resource definition if (url != null && ((settings.AppendVersion.HasValue && settings.AppendVersion == true) || (!settings.AppendVersion.HasValue && AppendVersion == true))) { url = fileVersionProvider.AddFileVersionToPath(applicationPath, url); } // Don't prefix cdn if the path is absolute, or is in debug mode. if (!settings.DebugMode && !String.IsNullOrEmpty(settings.CdnBaseUrl) && !Uri.TryCreate(url, UriKind.Absolute, out var uri)) { url = settings.CdnBaseUrl + url; } var tagBuilder = new TagBuilder(TagName) { TagRenderMode = TagRenderMode }; if (!String.IsNullOrEmpty(CdnIntegrity) && url != null && url == UrlCdn) { tagBuilder.Attributes["integrity"] = CdnIntegrity; tagBuilder.Attributes["crossorigin"] = "anonymous"; } else if (!String.IsNullOrEmpty(CdnDebugIntegrity) && url != null && url == UrlCdnDebug) { tagBuilder.Attributes["integrity"] = CdnDebugIntegrity; tagBuilder.Attributes["crossorigin"] = "anonymous"; } if (_resourceAttributes.ContainsKey(Type)) { tagBuilder.MergeAttributes(_resourceAttributes[Type]); } if (Attributes != null) { tagBuilder.MergeAttributes(Attributes); } if (settings.HasAttributes) { tagBuilder.MergeAttributes(settings.Attributes); } if (!String.IsNullOrEmpty(FilePathAttributeName)) { if (!String.IsNullOrEmpty(url)) { tagBuilder.MergeAttribute(FilePathAttributeName, url, true); } } return(tagBuilder); }
public TagBuilder GetTagBuilder(RequireSettings settings, string applicationPath, IFileVersionProvider fileVersionProvider) { string url, filePathAttributeName = null; // Url priority: if (settings.DebugMode) { url = settings.CdnMode ? Coalesce(UrlCdnDebug, UrlDebug, UrlCdn, Url) : Coalesce(UrlDebug, Url, UrlCdnDebug, UrlCdn); } else { url = settings.CdnMode ? Coalesce(UrlCdn, Url, UrlCdnDebug, UrlDebug) : Coalesce(Url, UrlDebug, UrlCdn, UrlCdnDebug); } if (String.IsNullOrEmpty(url)) { url = null; } if (!String.IsNullOrEmpty(settings.Culture)) { string nearestCulture = FindNearestCulture(settings.Culture); if (!String.IsNullOrEmpty(nearestCulture)) { url = Path.ChangeExtension(url, nearestCulture + Path.GetExtension(url)); } } if (url != null && url.StartsWith("~/", StringComparison.Ordinal)) { if (!String.IsNullOrEmpty(_basePath)) { url = _basePath + url.Substring(1); } else { url = applicationPath + url.Substring(1); } } // If settings has value, it can override resource definition, otherwise use resource definition if (url != null && ((settings.AppendVersion.HasValue && settings.AppendVersion == true) || (!settings.AppendVersion.HasValue && AppendVersion == true))) { url = fileVersionProvider.AddFileVersionToPath(applicationPath, url); } // Don't prefix cdn if the path is absolute, or is in debug mode. if (!settings.DebugMode && !String.IsNullOrEmpty(settings.CdnBaseUrl) && !Uri.TryCreate(url, UriKind.Absolute, out var uri)) { url = settings.CdnBaseUrl + url; } TagBuilder tagBuilder; switch (Type) { case "script": tagBuilder = new TagBuilder("script"); filePathAttributeName = "src"; break; case "stylesheet": if (url == null && InnerContent != null) { // Inline style declaration tagBuilder = new TagBuilder("style") { Attributes = { { "type", "text/css" } } }; } else { // Stylesheet resource tagBuilder = new TagBuilder("link") { TagRenderMode = TagRenderMode.SelfClosing, Attributes = { { "type", "text/css" }, { "rel", "stylesheet" } } }; filePathAttributeName = "href"; } break; case "link": tagBuilder = new TagBuilder("link") { TagRenderMode = TagRenderMode.SelfClosing }; filePathAttributeName = "href"; break; default: tagBuilder = new TagBuilder("meta") { TagRenderMode = TagRenderMode.SelfClosing }; break; } if (!String.IsNullOrEmpty(CdnIntegrity) && url != null && url == UrlCdn) { tagBuilder.Attributes["integrity"] = CdnIntegrity; tagBuilder.Attributes["crossorigin"] = "anonymous"; } else if (!String.IsNullOrEmpty(CdnDebugIntegrity) && url != null && url == UrlCdnDebug) { tagBuilder.Attributes["integrity"] = CdnDebugIntegrity; tagBuilder.Attributes["crossorigin"] = "anonymous"; } if (Attributes != null) { tagBuilder.MergeAttributes(Attributes); } if (settings.HasAttributes) { tagBuilder.MergeAttributes(settings.Attributes); } if (!String.IsNullOrEmpty(url) && filePathAttributeName != null) { tagBuilder.MergeAttribute(filePathAttributeName, url, true); } else if (!String.IsNullOrEmpty(InnerContent)) { tagBuilder.InnerHtml.AppendHtml(InnerContent); } return(tagBuilder); }