using System.Text; namespace XFESystem.Browser; /// Explicit packaged application resources. This interface never reads host paths on behalf of a URL. public interface IBrowserResourceSource { bool TryGet(Uri address, out WebResponse response); } public sealed class PackagedBrowserResources : IBrowserResourceSource { public const string Origin = "http://xfesystem.local"; public const string MonacoCoreRoot = Origin + "/Browser/Monaco/0.52.2/Core/"; public const string MonacoPageAddress = Origin + "/Browser/Monaco/Index.html"; public const string WebsiteCodeRoot = Origin + "/Browser/WebsiteCode/"; private sealed record CachedResource(string ContentType, string Body); // Only this finite assembly manifest is cached. The completed dictionary // is never mutated, and script execution still uses a fresh page/runtime. private static readonly IReadOnlyDictionary resources = LoadEmbeddedResources(); /// Reserve large immutable script strings while the early boot /// heap still has contiguous space, before browsers allocate transient DOM/JS state. public static int PrewarmTextResources() => resources.Count; private static IReadOnlyDictionary LoadEmbeddedResources() { var loaded = new Dictionary(StringComparer.Ordinal); foreach (string name in typeof(PackagedBrowserResources).Assembly.GetManifestResourceNames()) { var normalized = name.Replace('\\', '/'); string? path = normalized.StartsWith("MonacoCore/", StringComparison.Ordinal) ? "/Browser/Monaco/0.52.2/Core/" + normalized[11..] : normalized.StartsWith("WebsiteCode/", StringComparison.Ordinal) ? "/Browser/WebsiteCode/" + normalized[12..] : null; if (path is null) continue; string extension = Path.GetExtension(path).ToLowerInvariant(); if (extension is not (".js" or ".css" or ".json")) continue; using var stream = typeof(PackagedBrowserResources).Assembly.GetManifestResourceStream(name)!; using var reader = new StreamReader(stream, Encoding.UTF8, true); loaded.Add(path, new(extension == ".css" ? "text/css" : extension == ".json" ? "application/json" : "application/javascript", reader.ReadToEnd())); } return new System.Collections.ObjectModel.ReadOnlyDictionary(loaded); } public bool TryGet(Uri address, out WebResponse response) { response = null!; if (address.GetLeftPart(UriPartial.Authority) != Origin) return false; if (address.AbsolutePath == "/Browser/Monaco/Index.html") { response = new(address, 200, "text/html", MonacoPage); return true; } if (XFESystem.Documents.WebsiteAssets.TryReadWebText(address.AbsolutePath, out var website, out var mime)) { response = new(address, 200, mime, website); return true; } if (!resources.TryGetValue(address.AbsolutePath, out var cached)) return false; response = new(address, 200, cached.ContentType, cached.Body); return true; } public const string MonacoPage = """ XFESystem Monaco
Loading official Monaco Editor 0.52.2...
"""; }