Merge pull request #2914 from sbwalker/dev

integrate old logic for managing stylesheets using JS Interop
This commit is contained in:
Shaun Walker 2023-06-20 08:52:18 -04:00 committed by GitHub
commit d9f3db5bf3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 141 additions and 19 deletions

View File

@ -90,6 +90,21 @@ namespace Oqtane.UI
} }
} }
public Task IncludeLinks(object[] links)
{
try
{
_jsRuntime.InvokeVoidAsync(
"Oqtane.Interop.includeLinks",
(object)links);
return Task.CompletedTask;
}
catch
{
return Task.CompletedTask;
}
}
// external scripts need to specify src, inline scripts need to specify id and content // external scripts need to specify src, inline scripts need to specify id and content
public Task IncludeScript(string id, string src, string integrity, string crossorigin, string content, string location) public Task IncludeScript(string id, string src, string integrity, string crossorigin, string content, string location)
{ {
@ -125,6 +140,21 @@ namespace Oqtane.UI
} }
} }
public Task RemoveElementsById(string prefix, string first, string last)
{
try
{
_jsRuntime.InvokeVoidAsync(
"Oqtane.Interop.removeElementsById",
prefix, first, last);
return Task.CompletedTask;
}
catch
{
return Task.CompletedTask;
}
}
public ValueTask<string> GetElementByName(string name) public ValueTask<string> GetElementByName(string name)
{ {
try try

View File

@ -522,7 +522,7 @@
} }
// ensure resource does not exist already // ensure resource does not exist already
if (pageresources.Find(item => item.Url == resource.Url) == null) if (!pageresources.Any(item => item.Url.ToLower() == resource.Url.ToLower()))
{ {
resource.Level = level; resource.Level = level;
pageresources.Add(resource); pageresources.Add(resource);

View File

@ -31,6 +31,7 @@
// set page head content // set page head content
var headcontent = ""; var headcontent = "";
// favicon // favicon
var favicon = "favicon.ico"; var favicon = "favicon.ico";
var favicontype = "x-icon"; var favicontype = "x-icon";
@ -40,12 +41,14 @@
favicontype = favicon.Substring(favicon.LastIndexOf(".") + 1); favicontype = favicon.Substring(favicon.LastIndexOf(".") + 1);
} }
headcontent += $"<link id=\"app-favicon\" rel=\"shortcut icon\" type=\"image/{favicontype}\" href=\"{favicon}\" />\n"; headcontent += $"<link id=\"app-favicon\" rel=\"shortcut icon\" type=\"image/{favicontype}\" href=\"{favicon}\" />\n";
// stylesheets // stylesheets
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet)) //foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
{ //{
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url; // var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
headcontent += "<link rel=\"stylesheet\" href=\"" + url + "\"" + (!string.IsNullOrEmpty(resource.Integrity) ? " integrity=\"" + resource.Integrity + "\"" : "") + (!string.IsNullOrEmpty(resource.CrossOrigin) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") + " type=\"text/css\"/>" + "\n"; // headcontent += "<link rel=\"stylesheet\" href=\"" + url + "\"" + (!string.IsNullOrEmpty(resource.Integrity) ? " integrity=\"" + resource.Integrity + "\"" : "") + (!string.IsNullOrEmpty(resource.CrossOrigin) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") + " type=\"text/css\"/>" + "\n";
} //}
// head content // head content
AddHeadContent(headcontent, PageState.Site.HeadContent); AddHeadContent(headcontent, PageState.Site.HeadContent);
if (!string.IsNullOrEmpty(PageState.Site.HeadContent)) if (!string.IsNullOrEmpty(PageState.Site.HeadContent))
@ -100,27 +103,49 @@
} }
} }
if (PageState.Page.Resources != null && PageState.Page.Resources.Exists(item => item.ResourceType == ResourceType.Script)) if (PageState.Page.Resources != null)
{ {
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
var scripts = new List<object>();
var inline = 0; if (PageState.Page.Resources.Exists(item => item.ResourceType == ResourceType.Stylesheet))
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level != ResourceLevel.Site))
{ {
if (!string.IsNullOrEmpty(resource.Url)) string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
var links = new List<object>();
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
{ {
var prefix = "app-stylesheet-" + resource.Level.ToString().ToLower();
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url; var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module, location = resource.Location.ToString().ToLower() }); links.Add(new { id = prefix + "-" + batch + "-" + (links.Count + 1).ToString("00"), rel = "stylesheet", href = url, type = "text/css", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", insertbefore = prefix });
} }
else if (links.Any())
{ {
inline += 1; await interop.IncludeLinks(links.ToArray());
await interop.IncludeScript(GetType().Namespace.ToLower() + inline.ToString(), "", "", "", resource.Content, resource.Location.ToString().ToLower());
} }
await interop.RemoveElementsById("app-stylesheet-page-", "", "app-stylesheet-page-" + batch + "-00");
await interop.RemoveElementsById("app-stylesheet-module-", "", "app-stylesheet-module-" + batch + "-00");
} }
if (scripts.Any())
if (PageState.Page.Resources.Exists(item => item.ResourceType == ResourceType.Script))
{ {
await interop.IncludeScripts(scripts.ToArray()); var scripts = new List<object>();
var inline = 0;
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level != ResourceLevel.Site))
{
if (!string.IsNullOrEmpty(resource.Url))
{
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module, location = resource.Location.ToString().ToLower() });
}
else
{
inline += 1;
await interop.IncludeScript(GetType().Namespace.ToLower() + inline.ToString(), "", "", "", resource.Content, resource.Location.ToString().ToLower());
}
}
if (scripts.Any())
{
await interop.IncludeScripts(scripts.ToArray());
}
} }
} }
} }

View File

@ -15,6 +15,8 @@
{ {
<link id="app-manifest" rel="manifest" /> <link id="app-manifest" rel="manifest" />
} }
<style id="app-stylesheet-page"></style>
<style id="app-stylesheet-module"></style>
<component type="typeof(Oqtane.Head)" render-mode="@((RenderMode)Enum.Parse(typeof(RenderMode), Model.RenderMode, true))" /> <component type="typeof(Oqtane.Head)" render-mode="@((RenderMode)Enum.Parse(typeof(RenderMode), Model.RenderMode, true))" />
@Html.Raw(Model.HeadResources) @Html.Raw(Model.HeadResources)
</head> </head>

View File

@ -19,6 +19,8 @@ using Microsoft.Extensions.Primitives;
using Oqtane.Enums; using Oqtane.Enums;
using Oqtane.Security; using Oqtane.Security;
using Oqtane.Extensions; using Oqtane.Extensions;
using Oqtane.Themes;
using System.Collections.Generic;
namespace Oqtane.Pages namespace Oqtane.Pages
{ {
@ -163,7 +165,29 @@ namespace Oqtane.Pages
} }
} }
// inject scripts // stylesheets
var resources = new List<Resource>();
if (string.IsNullOrEmpty(page.ThemeType))
{
page.ThemeType = site.DefaultThemeType;
}
var theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == page.ThemeType));
if (theme != null)
{
resources.AddRange(theme.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet).ToList());
}
var type = Type.GetType(page.ThemeType);
if (type != null)
{
var obj = Activator.CreateInstance(type) as IThemeControl;
if (obj.Resources != null)
{
resources.AddRange(obj.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet).ToList());
}
}
ManageResources(resources, alias, theme.ThemeName);
// scripts
if (Runtime == "Server") if (Runtime == "Server")
{ {
ReconnectScript = CreateReconnectScript(); ReconnectScript = CreateReconnectScript();
@ -468,5 +492,31 @@ namespace Oqtane.Pages
CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture))); CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)));
} }
private void ManageResources(List<Resource> resources, Alias alias, string name)
{
if (resources != null)
{
int count = 0;
foreach (var resource in resources)
{
if (resource.Url.StartsWith("~"))
{
resource.Url = resource.Url.Replace("~", "/Themes/" + name + "/").Replace("//", "/");
}
if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl))
{
resource.Url = alias.BaseUrl + resource.Url;
}
if (!HeadResources.Contains(resource.Url, StringComparison.OrdinalIgnoreCase))
{
count++;
string id = "id=\"app-stylesheet-" + ResourceLevel.Page.ToString().ToLower() + "-" + DateTime.UtcNow.ToString("yyyyMMddHHmmssfff") + "-" + count.ToString("00") + "\" ";
HeadResources += "<link " + id + "rel=\"stylesheet\" href=\"" + resource.Url + "\"" + (!string.IsNullOrEmpty(resource.Integrity) ? " integrity=\"" + resource.Integrity + "\"" : "") + (!string.IsNullOrEmpty(resource.CrossOrigin) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") + " type=\"text/css\"/>" + Environment.NewLine;
}
}
}
}
} }
} }

View File

@ -99,7 +99,8 @@ namespace Oqtane.Repository
{ {
var site = GetSite(alias.SiteId); var site = GetSite(alias.SiteId);
_themeRepository.GetThemes(); // load themes and module definitions
site.Themes = _themeRepository.GetThemes().ToList();
var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId); var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId);
// site migrations // site migrations

View File

@ -108,6 +108,11 @@ Oqtane.Interop = {
} }
} }
}, },
includeLinks: function (links) {
for (let i = 0; i < links.length; i++) {
this.includeLink(links[i].id, links[i].rel, links[i].href, links[i].type, links[i].integrity, links[i].crossorigin, links[i].insertbefore);
}
},
includeScript: function (id, src, integrity, crossorigin, type, content, location) { includeScript: function (id, src, integrity, crossorigin, type, content, location) {
var script; var script;
if (src !== "") { if (src !== "") {
@ -234,6 +239,15 @@ Oqtane.Interop = {
} }
return getAbsoluteUrl(url); return getAbsoluteUrl(url);
}, },
removeElementsById: function (prefix, first, last) {
var elements = document.querySelectorAll('[id^=' + prefix + ']');
for (var i = elements.length - 1; i >= 0; i--) {
var element = elements[i];
if (element.id.startsWith(prefix) && (first === '' || element.id >= first) && (last === '' || element.id <= last)) {
element.parentNode.removeChild(element);
}
}
},
getElementByName: function (name) { getElementByName: function (name) {
var elements = document.getElementsByName(name); var elements = document.getElementsByName(name);
if (elements.length) { if (elements.length) {