@namespace Oqtane.UI @using System.Net @inject IJSRuntime JSRuntime @inject NavigationManager NavigationManager @inject SiteState SiteState @DynamicComponent @code { [CascadingParameter] PageState PageState { get; set; } RenderFragment DynamicComponent { get; set; } protected override void OnParametersSet() { // handle page redirection if (!string.IsNullOrEmpty(PageState.Page.Url)) { NavigationManager.NavigateTo(PageState.Page.Url); return; } // force authenticated user to provide email address (email may be missing if using external login) if (PageState.User != null && PageState.User.IsAuthenticated && string.IsNullOrEmpty(PageState.User.Email) && PageState.Route.PagePath != "profile") { NavigationManager.NavigateTo(Utilities.NavigateUrl(PageState.Alias.Path, "profile", "returnurl=" + WebUtility.UrlEncode(PageState.Route.PathAndQuery))); return; } // set page title if (!string.IsNullOrEmpty(PageState.Page.Title)) { SiteState.Properties.PageTitle = PageState.Page.Title; } else { SiteState.Properties.PageTitle = PageState.Page.Name + " - " + PageState.Site.Name; } // set page head content var headcontent = ""; // favicon if (PageState.Site.FaviconFileId != null) { headcontent += $"\n"; } else { headcontent += $"\n"; } // head content if (!string.IsNullOrEmpty(PageState.Site.HeadContent)) { headcontent = AddHeadContent(headcontent, PageState.Site.HeadContent); } if (!string.IsNullOrEmpty(PageState.Page.HeadContent)) { headcontent = AddHeadContent(headcontent, PageState.Page.HeadContent); } SiteState.Properties.HeadContent = headcontent; DynamicComponent = builder => { builder.OpenComponent(0, Type.GetType(PageState.Page.ThemeType)); builder.CloseComponent(); }; } private string AddHeadContent(string headcontent, string content) { if (!string.IsNullOrEmpty(content)) { var elements = content.Split('<', StringSplitOptions.RemoveEmptyEntries); foreach (var element in elements) { if (PageState.RenderMode == RenderModes.Static || (!element.ToLower().StartsWith("script") && !element.ToLower().StartsWith("/script"))) { if (!headcontent.Contains("<" + element) || element.StartsWith("/")) { headcontent += "<" + element; } } } headcontent += "\n"; } return headcontent; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) { // site content if (!string.IsNullOrEmpty(PageState.Site.HeadContent) && PageState.Site.HeadContent.Contains(" item.ResourceType == ResourceType.Stylesheet)) { var interop = new Interop(JSRuntime); string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff"); var links = new List(); 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; 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 }); } if (links.Any()) { await interop.IncludeLinks(links.ToArray()); } await interop.RemoveElementsById("app-stylesheet-page-", "", "app-stylesheet-page-" + batch + "-00"); await interop.RemoveElementsById("app-stylesheet-module-", "", "app-stylesheet-module-" + batch + "-00"); } } private async Task InjectScripts(string content, ResourceLocation location) { // inject scripts into page dynamically var interop = new Interop(JSRuntime); var scripts = new List(); var count = 0; var index = content.IndexOf("= 0) { var script = content.Substring(index, content.IndexOf("", index) + 9 - index); // get script attributes var attributes = script.Substring(0, script.IndexOf(">")).Replace("\"", "").Split(" "); string id = ""; string src = ""; string integrity = ""; string crossorigin = ""; string type = ""; var dataAttributes = new Dictionary(); foreach (var attribute in attributes) { if (attribute.Contains("=")) { var value = attribute.Split("="); switch (value[0]) { case "id": id = value[1]; break; case "src": src = value[1]; break; case "integrity": integrity = value[1]; break; case "crossorigin": crossorigin = value[1]; break; case "type": type = value[1]; break; default: if(!string.IsNullOrWhiteSpace(value[0]) && value[0].StartsWith("data-")) { dataAttributes.Add(value[0], value[1]); } break; } } } // inject script if (!string.IsNullOrEmpty(src)) { src = (src.Contains("://")) ? src : PageState.Alias.BaseUrl + src; scripts.Add(new { href = src, type = type, bundle = "", integrity = integrity, crossorigin = crossorigin, location = location.ToString().ToLower(), dataAttributes = dataAttributes }); } else { if (id == "") { count += 1; id = $"page{PageState.Page.PageId}-script{count}"; } var pos = script.IndexOf(">") + 1; await interop.IncludeScript(id, "", "", "", type, script.Substring(pos, script.IndexOf("") - pos), location.ToString().ToLower(), dataAttributes); } index = content.IndexOf(" resources, Alias alias) { var stylesheets = ""; if (resources != null) { string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff"); int count = 0; foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Stylesheet)) { if (resource.Url.StartsWith("~")) { resource.Url = resource.Url.Replace("~", "/Themes/" + Utilities.GetTypeName(resource.Namespace) + "/").Replace("//", "/"); } if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl)) { resource.Url = alias.BaseUrl + resource.Url; } if (!stylesheets.Contains(resource.Url, StringComparison.OrdinalIgnoreCase)) { count++; string id = "id=\"app-stylesheet-" + ResourceLevel.Page.ToString().ToLower() + "-" + batch + "-" + count.ToString("00") + "\" "; stylesheets += "" + Environment.NewLine; } } } return stylesheets; } private string ManageScripts(List resources, Alias alias) { var scripts = ""; if (resources != null) { foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Script && item.Location == ResourceLocation.Head)) { var script = CreateScript(resource, alias); if (!scripts.Contains(script, StringComparison.OrdinalIgnoreCase)) { scripts += script + Environment.NewLine; } } } return scripts; } private string CreateScript(Resource resource, Alias alias) { if (!string.IsNullOrEmpty(resource.Url)) { var url = (resource.Url.Contains("://")) ? resource.Url : alias.BaseUrl + resource.Url; return ""; } else { // inline script return ""; } } }