diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs
index 9e05d8e..1bbefc8 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs
@@ -48,7 +48,7 @@ public class Plugin : IViewer
".pbm", ".pcx", ".pef", ".pgm", ".png", ".pnm", ".ppm", ".psb", ".psd", ".ptx", ".pxn",
".qoi",
".r3d", ".raf", ".raw", ".rw2", ".rwl", ".rwz",
- ".sr2", ".srf", ".srw", ".svg", ".svgz",
+ ".sr2", ".srf", ".srw", ".svg", ".svga", ".svgz",
".tga", ".tif", ".tiff",
".wdp", ".webp", ".wmf",
".x3f", ".xcf", ".xbm", ".xpm",
@@ -114,7 +114,8 @@ public class Plugin : IViewer
public void Prepare(string path, ContextObject context)
{
- if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
+ if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)
+ || path.EndsWith(".svga", StringComparison.OrdinalIgnoreCase))
{
if (SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer"))
{
@@ -145,7 +146,8 @@ public class Plugin : IViewer
public void View(string path, ContextObject context)
{
- if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
+ if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)
+ || path.EndsWith(".svga", StringComparison.OrdinalIgnoreCase))
{
if (SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer"))
{
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj
index 9d7f868..1f347fb 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj
@@ -91,7 +91,7 @@
-
+
QuickLook.Plugin.ImageViewer.Resources.%(RecursiveDir)%(Filename)%(Extension)
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.html b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.html
new file mode 100644
index 0000000..22349b2
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ SVGA Preview
+
+
+
+
+
+
+
+
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.js b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.js
new file mode 100644
index 0000000..8e6bcfa
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.js
@@ -0,0 +1,39 @@
+/**
+ * SvgaViewer: Provides SVGA animation preview with the following features.
+ *
+ * Requirements:
+ * - Requires the following HTML structure:
+ *
+ * - SVGA file path is obtained via chrome.webview.hostObjects.external.GetPath()
+ *
+ * Features:
+ * - Loads and plays SVGA animation files
+ * - Uses SVGA.js library for parsing and playback
+ * - Automatically starts playback after loading
+ * - Handles asynchronous loading and mounting of SVGA files
+*/
+class SvgaViewer {
+ constructor() {
+ }
+
+ /**
+ * Play SVGA file.
+ * @async
+ */
+ async play() {
+ const path = await chrome.webview.hostObjects.external.GetPath();
+ const parser = new SVGA.Parser();
+
+ // Because the path is a local file, we need to convert it to a URL format
+ parser.load('https://' + path).then(svga => {
+ const player = new SVGA.Player(document.getElementById('canvas'));
+ player.mount(svga).then(() => {
+ player.start();
+ });
+ });
+ }
+}
+
+// Create the SVGA viewer and play
+new SvgaViewer().play();
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgImagePanel.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgImagePanel.cs
index aece289..3a79700 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgImagePanel.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgImagePanel.cs
@@ -99,7 +99,7 @@ public class SvgImagePanel : WebpagePanel
ObjectForScripting ??= new ScriptHandler(path);
- _homePage = _resources["/svg2html.html"];
+ _homePage = _resources[path.EndsWith(".svga", StringComparison.OrdinalIgnoreCase) ? "/svga2html.html" : "/svg2html.html"];
NavigateToUri(new Uri("file://quicklook/"));
}
@@ -145,6 +145,21 @@ public class SvgImagePanel : WebpagePanel
}
}
}
+ else if (requestedUri.Scheme == "https")
+ {
+ var localPath = $"{requestedUri.Authority}:{requestedUri.AbsolutePath}".Replace('/', '\\');
+
+ if (localPath.StartsWith(_fallbackPath, StringComparison.OrdinalIgnoreCase))
+ {
+ if (File.Exists(localPath))
+ {
+ var fileStream = File.OpenRead(localPath);
+ var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
+ fileStream, 200, "OK", MimeTypes.GetContentType() + "\r\nAccess-Control-Allow-Origin: *");
+ args.Response = response;
+ }
+ }
+ }
}
catch (Exception e)
{
@@ -197,6 +212,16 @@ public sealed class ScriptHandler(string path)
{
public string Path { get; } = path;
+ public async Task GetPath()
+ {
+ return await Task.FromResult(new Uri(Path).AbsolutePath);
+ }
+
+ public async Task GetUri()
+ {
+ return await Task.FromResult(new Uri(Path).AbsoluteUri);
+ }
+
public async Task GetSvgContent()
{
if (File.Exists(Path))
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs
index 8e11179..20060e8 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs
@@ -23,38 +23,42 @@ public class SvgMetaProvider(string path)
{
return _size;
}
- try
+
+ if (_path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
{
- var svgContent = File.ReadAllText(_path);
- var svg = XElement.Parse(svgContent);
- XNamespace ns = svg.Name.Namespace;
-
- string widthAttr = svg.Attribute("width")?.Value;
- string heightAttr = svg.Attribute("height")?.Value;
-
- float? width = TryParseSvgLength(widthAttr);
- float? height = TryParseSvgLength(heightAttr);
-
- if (width.HasValue && height.HasValue)
+ try
{
- _size = new Size { Width = width.Value, Height = height.Value };
- }
+ var svgContent = File.ReadAllText(_path);
+ var svg = XElement.Parse(svgContent);
+ XNamespace ns = svg.Name.Namespace;
- string viewBoxAttr = svg.Attribute("viewBox")?.Value;
- if (!string.IsNullOrEmpty(viewBoxAttr))
- {
- var parts = viewBoxAttr.Split([' ', ','], StringSplitOptions.RemoveEmptyEntries);
- if (parts.Length == 4 &&
- float.TryParse(parts[2], out float vbWidth) &&
- float.TryParse(parts[3], out float vbHeight))
+ string widthAttr = svg.Attribute("width")?.Value;
+ string heightAttr = svg.Attribute("height")?.Value;
+
+ float? width = TryParseSvgLength(widthAttr);
+ float? height = TryParseSvgLength(heightAttr);
+
+ if (width.HasValue && height.HasValue)
{
- _size = new Size { Width = vbWidth, Height = vbHeight };
+ _size = new Size { Width = width.Value, Height = height.Value };
+ }
+
+ string viewBoxAttr = svg.Attribute("viewBox")?.Value;
+ if (!string.IsNullOrEmpty(viewBoxAttr))
+ {
+ var parts = viewBoxAttr.Split([' ', ','], StringSplitOptions.RemoveEmptyEntries);
+ if (parts.Length == 4 &&
+ float.TryParse(parts[2], out float vbWidth) &&
+ float.TryParse(parts[3], out float vbHeight))
+ {
+ _size = new Size { Width = vbWidth, Height = vbHeight };
+ }
}
}
- }
- catch (Exception e)
- {
- Debug.WriteLine(e);
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ }
}
return _size;