mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
Improve offline support
* Add a command line option for supplying local web files * Consolodate references into a single file * Resolves #1486
This commit is contained in:
parent
06010534f1
commit
fd0f5fd014
@ -1,25 +0,0 @@
|
||||
namespace AssetRipper.GUI.Web;
|
||||
|
||||
internal static class Bootstrap
|
||||
{
|
||||
internal static void WriteStyleSheetReference(TextWriter writer)
|
||||
{
|
||||
new Link(writer)
|
||||
{
|
||||
Rel = "stylesheet",
|
||||
Href = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
|
||||
Integrity = "sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN",
|
||||
Crossorigin = "anonymous"
|
||||
}.Close();
|
||||
}
|
||||
|
||||
internal static void WriteScriptReference(TextWriter writer)
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js",
|
||||
Integrity = "sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL",
|
||||
Crossorigin = "anonymous"
|
||||
}.Close();
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ public abstract class DefaultPage : HtmlPage
|
||||
new Meta(writer).WithCharset("utf-8").Close();
|
||||
new Meta(writer).WithName("viewport").WithContent("width=device-width, initial-scale=1.0").Close();
|
||||
new Title(writer).Close(GetTitle());
|
||||
Bootstrap.WriteStyleSheetReference(writer);
|
||||
OnlineDependencies.Bootstrap.WriteStyleSheetReference(writer);
|
||||
new Link(writer).WithRel("stylesheet").WithHref("/css/site.css").Close();
|
||||
}
|
||||
using (new Body(writer).WithCustomAttribute("data-bs-theme", "dark").End())
|
||||
@ -202,8 +202,8 @@ public abstract class DefaultPage : HtmlPage
|
||||
|
||||
protected virtual void WriteScriptReferences(TextWriter writer)
|
||||
{
|
||||
writer.Write("""<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>""");
|
||||
Bootstrap.WriteScriptReference(writer);
|
||||
OnlineDependencies.Popper.WriteScriptReference(writer);
|
||||
OnlineDependencies.Bootstrap.WriteScriptReference(writer);
|
||||
new Script(writer).WithSrc("/js/site.js").Close();
|
||||
}
|
||||
}
|
||||
|
||||
141
Source/AssetRipper.GUI.Web/OnlineDependencies.cs
Normal file
141
Source/AssetRipper.GUI.Web/OnlineDependencies.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using AssetRipper.Import;
|
||||
|
||||
namespace AssetRipper.GUI.Web;
|
||||
|
||||
/// <summary>
|
||||
/// Contains references to online dependencies.
|
||||
/// </summary>
|
||||
internal static class OnlineDependencies
|
||||
{
|
||||
// Dependencies are ordered alphabetically in this class.
|
||||
|
||||
/// <summary>
|
||||
/// <see href="https://www.babylonjs.com/"/>
|
||||
/// </summary>
|
||||
internal static class Babylon
|
||||
{
|
||||
internal static void WriteScriptReference(TextWriter writer)
|
||||
{
|
||||
if (!TryWriteCachedScriptReference(writer, "/js/babylon.js"))
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://cdn.babylonjs.com/babylon.js"
|
||||
}.Close();
|
||||
}
|
||||
if (!TryWriteCachedScriptReference(writer, "/js/babylonjs.loaders.min.js"))
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"
|
||||
}.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see href="https://getbootstrap.com/"/>
|
||||
/// </summary>
|
||||
internal static class Bootstrap
|
||||
{
|
||||
internal static void WriteStyleSheetReference(TextWriter writer)
|
||||
{
|
||||
if (!TryWriteCachedStyleSheetReference(writer, "/css/bootstrap.min.css"))
|
||||
{
|
||||
new Link(writer)
|
||||
{
|
||||
Rel = "stylesheet",
|
||||
Href = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
|
||||
Integrity = "sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN",
|
||||
Crossorigin = "anonymous"
|
||||
}.Close();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteScriptReference(TextWriter writer)
|
||||
{
|
||||
if (!TryWriteCachedScriptReference(writer, "/js/bootstrap.bundle.min.js"))
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js",
|
||||
Integrity = "sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL",
|
||||
Crossorigin = "anonymous"
|
||||
}.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see href="https://jquery.com/"/>
|
||||
/// </summary>
|
||||
internal static class Popper
|
||||
{
|
||||
internal static void WriteScriptReference(TextWriter writer)
|
||||
{
|
||||
if (!TryWriteCachedScriptReference(writer, "/js/popper.min.js"))
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js",
|
||||
Integrity = "sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r",
|
||||
Crossorigin = "anonymous"
|
||||
}.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see href="https://vuejs.org/"/>
|
||||
/// </summary>
|
||||
internal static class Vue
|
||||
{
|
||||
internal static void WriteScriptReference(TextWriter writer)
|
||||
{
|
||||
if (!TryWriteCachedScriptReference(writer, "/js/vue.global.prod.js") && !TryWriteCachedScriptReference(writer, "/js/vue.global.js"))
|
||||
{
|
||||
if (AssetRipperRuntimeInformation.Build.Debug)
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://unpkg.com/vue@3/dist/vue.global.js"
|
||||
}.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = "https://unpkg.com/vue@3/dist/vue.global.prod.js"
|
||||
}.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryWriteCachedStyleSheetReference(TextWriter writer, string path)
|
||||
{
|
||||
if (StaticContentLoader.Cache.ContainsKey(path))
|
||||
{
|
||||
new Link(writer)
|
||||
{
|
||||
Rel = "stylesheet",
|
||||
Href = path
|
||||
}.Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryWriteCachedScriptReference(TextWriter writer, string path)
|
||||
{
|
||||
if (StaticContentLoader.Cache.ContainsKey(path))
|
||||
{
|
||||
new Script(writer)
|
||||
{
|
||||
Src = path
|
||||
}.Close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -36,8 +36,7 @@ public sealed class ViewPage : DefaultPage
|
||||
protected override void WriteScriptReferences(TextWriter writer)
|
||||
{
|
||||
base.WriteScriptReferences(writer);
|
||||
new Script(writer).WithSrc("https://cdn.babylonjs.com/babylon.js").Close();
|
||||
new Script(writer).WithSrc("https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js").Close();
|
||||
OnlineDependencies.Babylon.WriteScriptReference(writer);
|
||||
new Script(writer).WithSrc("/js/mesh_preview.js").Close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace AssetRipper.GUI.Web;
|
||||
public static partial class StaticContentLoader
|
||||
{
|
||||
private const string Prefix = "AssetRipper.GUI.Web.StaticContent.";
|
||||
private static readonly ConcurrentDictionary<string, byte[]> Cache = new();
|
||||
public static ConcurrentDictionary<string, byte[]> Cache { get; } = new();
|
||||
|
||||
public static async ValueTask<byte[]> Load(string path)
|
||||
{
|
||||
|
||||
@ -1,19 +1,10 @@
|
||||
using AssetRipper.Import;
|
||||
|
||||
namespace AssetRipper.GUI.Web;
|
||||
namespace AssetRipper.GUI.Web;
|
||||
|
||||
public abstract class VuePage : DefaultPage
|
||||
{
|
||||
protected override void WriteScriptReferences(TextWriter writer)
|
||||
{
|
||||
base.WriteScriptReferences(writer);
|
||||
if (AssetRipperRuntimeInformation.Build.Debug)
|
||||
{
|
||||
writer.Write("""<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>""");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write("""<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>""");
|
||||
}
|
||||
OnlineDependencies.Vue.WriteScriptReference(writer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,16 +47,40 @@ public static class WebApplicationLauncher
|
||||
getDefaultValue: () => Defaults.LaunchBrowser);
|
||||
rootCommand.AddOption(launchBrowserOption);
|
||||
|
||||
Option<string[]> localWebFilesOption = new Option<string[]>(
|
||||
name: "--local-web-file",
|
||||
description: "Files provided with this option will replace online sources.",
|
||||
getDefaultValue: () => []);
|
||||
rootCommand.AddOption(localWebFilesOption);
|
||||
|
||||
bool shouldRun = false;
|
||||
int port = Defaults.Port;
|
||||
bool launchBrowser = Defaults.LaunchBrowser;
|
||||
|
||||
rootCommand.SetHandler((int portParsed, bool launchBrowserParsed) =>
|
||||
rootCommand.SetHandler((int portParsed, bool launchBrowserParsed, string[] localWebFilesParsed) =>
|
||||
{
|
||||
shouldRun = true;
|
||||
port = portParsed;
|
||||
launchBrowser = launchBrowserParsed;
|
||||
}, portOption, launchBrowserOption);
|
||||
foreach (string localWebFile in localWebFilesParsed)
|
||||
{
|
||||
if (File.Exists(localWebFile))
|
||||
{
|
||||
string fileName = Path.GetFileName(localWebFile);
|
||||
string webPrefix = Path.GetExtension(fileName) switch
|
||||
{
|
||||
".css" => "/css/",
|
||||
".js" => "/js/",
|
||||
_ => "/"
|
||||
};
|
||||
StaticContentLoader.Cache.TryAdd(webPrefix + fileName, File.ReadAllBytes(localWebFile));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"File '{localWebFile}' does not exist.");
|
||||
}
|
||||
}
|
||||
}, portOption, launchBrowserOption, localWebFilesOption);
|
||||
|
||||
rootCommand.Invoke(args);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user