diff --git a/QuickLook.Plugin/QuickLook.Plugin.FontViewer/WebfontPanel.cs b/QuickLook.Plugin/QuickLook.Plugin.FontViewer/WebfontPanel.cs
index a44c539..96b0014 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.FontViewer/WebfontPanel.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.FontViewer/WebfontPanel.cs
@@ -124,55 +124,47 @@ public class WebfontPanel : WebpagePanel
return html;
}
- protected override void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
+ protected override void WebView_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs args)
{
- if (e.IsSuccess)
+ Debug.WriteLine($"[{args.Request.Method}] {args.Request.Uri}");
+
+ try
{
- _webView.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All);
+ var requestedUri = new Uri(args.Request.Uri);
- _webView.CoreWebView2.WebResourceRequested += (sender, args) =>
+ if (requestedUri.Scheme == "file")
{
- Debug.WriteLine($"[{args.Request.Method}] {args.Request.Uri}");
-
- try
+ if (requestedUri.AbsolutePath == "/")
{
- var requestedUri = new Uri(args.Request.Uri);
+ var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
+ new MemoryStream(_homePage), 200, "OK", MimeTypes.GetContentType(".html"));
+ args.Response = response;
+ }
+ else if (ContainsKey(requestedUri.AbsolutePath))
+ {
+ var stream = ReadStream(requestedUri.AbsolutePath);
+ var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
+ stream, 200, "OK", MimeTypes.GetContentType(Path.GetExtension(requestedUri.AbsolutePath)));
+ args.Response = response;
+ }
+ else
+ {
+ var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
- if (requestedUri.Scheme == "file")
+ if (File.Exists(localPath))
{
- if (requestedUri.AbsolutePath == "/")
- {
- var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
- new MemoryStream(_homePage), 200, "OK", MimeTypes.GetContentType(".html"));
- args.Response = response;
- }
- else if (ContainsKey(requestedUri.AbsolutePath))
- {
- var stream = ReadStream(requestedUri.AbsolutePath);
- var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
- stream, 200, "OK", MimeTypes.GetContentType(Path.GetExtension(requestedUri.AbsolutePath)));
- args.Response = response;
- }
- else
- {
- var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
-
- if (File.Exists(localPath))
- {
- var fileStream = File.OpenRead(localPath);
- var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
- fileStream, 200, "OK", MimeTypes.GetContentType());
- args.Response = response;
- }
- }
+ var fileStream = File.OpenRead(localPath);
+ var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
+ fileStream, 200, "OK", MimeTypes.GetContentType());
+ args.Response = response;
}
}
- catch (Exception e)
- {
- // We don't need to feel burdened by any exceptions
- Debug.WriteLine(e);
- }
- };
+ }
+ }
+ catch (Exception e)
+ {
+ // We don't need to feel burdened by any exceptions
+ Debug.WriteLine(e);
}
}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.HtmlViewer/WebpagePanel.cs b/QuickLook.Plugin/QuickLook.Plugin.HtmlViewer/WebpagePanel.cs
index f037269..0e87d6f 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.HtmlViewer/WebpagePanel.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.HtmlViewer/WebpagePanel.cs
@@ -176,51 +176,52 @@ public class WebpagePanel : UserControl
if (e.IsSuccess)
{
_webView.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All);
+ _webView.CoreWebView2.WebResourceRequested += WebView_WebResourceRequested;
+ }
+ }
- _webView.CoreWebView2.WebResourceRequested += (sender, args) =>
+ protected virtual void WebView_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs args)
+ {
+ if (string.IsNullOrWhiteSpace(_fallbackPath) || !Directory.Exists(_fallbackPath))
+ {
+ return;
+ }
+
+ try
+ {
+ var requestedUri = new Uri(args.Request.Uri);
+
+ // Check if the request is for a local file
+ if (requestedUri.Scheme == "file" && !File.Exists(requestedUri.LocalPath))
{
- if (string.IsNullOrWhiteSpace(_fallbackPath) || !Directory.Exists(_fallbackPath))
- {
- return;
- }
+ // Try loading from fallback directory
+ var fileName = Path.GetFileName(requestedUri.LocalPath);
+ var fileDirectoryName = Path.GetDirectoryName(requestedUri.LocalPath);
- try
+ // Convert the primary path to fallback path
+ if (fileDirectoryName.StartsWith(_primaryPath))
{
- var requestedUri = new Uri(args.Request.Uri);
+ var fallbackFilePath = Path.Combine(
+ _fallbackPath.Trim('/', '\\'), // Make it combinable
+ fileDirectoryName.Substring(_primaryPath.Length).Trim('/', '\\'), // Make it combinable
+ fileName
+ );
- // Check if the request is for a local file
- if (requestedUri.Scheme == "file" && !File.Exists(requestedUri.LocalPath))
+ if (File.Exists(fallbackFilePath))
{
- // Try loading from fallback directory
- var fileName = Path.GetFileName(requestedUri.LocalPath);
- var fileDirectoryName = Path.GetDirectoryName(requestedUri.LocalPath);
-
- // Convert the primary path to fallback path
- if (fileDirectoryName.StartsWith(_primaryPath))
- {
- var fallbackFilePath = Path.Combine(
- _fallbackPath.Trim('/', '\\'), // Make it combinable
- fileDirectoryName.Substring(_primaryPath.Length).Trim('/', '\\'), // Make it combinable
- fileName
- );
-
- if (File.Exists(fallbackFilePath))
- {
- // Serve the file from the fallback directory
- var fileStream = File.OpenRead(fallbackFilePath);
- var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
- fileStream, 200, "OK", "Content-Type: application/octet-stream");
- args.Response = response;
- }
- }
+ // Serve the file from the fallback directory
+ var fileStream = File.OpenRead(fallbackFilePath);
+ var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
+ fileStream, 200, "OK", "Content-Type: application/octet-stream");
+ args.Response = response;
}
}
- catch (Exception e)
- {
- // We don't need to feel burdened by any exceptions
- Debug.WriteLine(e);
- }
- };
+ }
+ }
+ catch (Exception e)
+ {
+ // We don't need to feel burdened by any exceptions
+ Debug.WriteLine(e);
}
}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs
index 5320d8a..1329369 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Plugin.cs
@@ -18,6 +18,7 @@
using QuickLook.Common.Helpers;
using QuickLook.Common.Plugin;
using QuickLook.Plugin.ImageViewer.AnimatedImage.Providers;
+using QuickLook.Plugin.ImageViewer.Webview;
using System;
using System.Collections.Generic;
using System.IO;
@@ -48,7 +49,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", ".svga", ".svgz",
+ ".sr2", ".srf", ".srw", ".svg", ".svgz",
".tga", ".tif", ".tiff",
".wdp", ".webp", ".wmf",
".x3f", ".xcf", ".xbm", ".xpm",
@@ -57,8 +58,8 @@ public class Plugin : IViewer
private ImagePanel _ip;
private MetaProvider _meta;
- private SvgImagePanel _ipSvg;
- private SvgMetaProvider _metaSvg;
+ private IWebImagePanel _ipWeb;
+ private IWebMetaProvider _metaWeb;
public int Priority => 0;
@@ -100,44 +101,20 @@ public class Plugin : IViewer
typeof(ImageMagickProvider)));
}
- private bool IsWellKnownImageExtension(string path)
- {
- return WellKnownImageExtensions.Contains(Path.GetExtension(path.ToLower()));
- }
-
public bool CanHandle(string path)
{
+ if (WebHandler.TryCanHandle(path))
+ return true;
+
// Disabled due mishandling text file types e.g., "*.config".
// Only check extension for well known image and animated image types.
- return !Directory.Exists(path) && IsWellKnownImageExtension(path);
+ return !Directory.Exists(path) && WellKnownImageExtensions.Contains(Path.GetExtension(path).ToLower());
}
public void Prepare(string path, ContextObject context)
{
- if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
- {
- if (SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer"))
- {
- _metaSvg = new SvgMetaProvider(path);
- var sizeSvg = _metaSvg.GetSize();
-
- if (!sizeSvg.IsEmpty)
- context.SetPreferredSizeFit(sizeSvg, 0.8d);
- else
- context.PreferredSize = new Size(800, 600);
-
- context.Theme = (Themes)SettingHelper.Get("LastTheme", 1, "QuickLook.Plugin.ImageViewer");
- return;
- }
- }
- else if (path.EndsWith(".svga", StringComparison.OrdinalIgnoreCase))
- {
- _metaSvg = new SvgMetaProvider(path);
-
- context.PreferredSize = new Size(800, 600);
- context.Theme = (Themes)SettingHelper.Get("LastTheme", 1, "QuickLook.Plugin.ImageViewer");
+ if (WebHandler.TryPrepare(path, context, out _metaWeb))
return;
- }
_meta = new MetaProvider(path);
@@ -153,25 +130,8 @@ public class Plugin : IViewer
public void View(string path, ContextObject context)
{
- if (path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase)
- || path.EndsWith(".svga", StringComparison.OrdinalIgnoreCase))
- {
- if (SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer"))
- {
- _ipSvg = new SvgImagePanel();
- _ipSvg.PreviewSvg(path);
-
- var sizeSvg = _metaSvg.GetSize();
-
- context.ViewerContent = _ipSvg;
- context.Title = sizeSvg.IsEmpty
- ? $"{Path.GetFileName(path)}"
- : $"{sizeSvg.Width}×{sizeSvg.Height}: {Path.GetFileName(path)}";
-
- context.IsBusy = false;
- return;
- }
- }
+ if (WebHandler.TryView(path, context, _metaWeb, out _ipWeb))
+ return;
_ip = new ImagePanel(context, _meta);
var size = _meta.GetSize();
@@ -197,7 +157,7 @@ public class Plugin : IViewer
_ip?.Dispose();
_ip = null;
- _ipSvg?.Dispose();
- _ipSvg = null;
+ _ipWeb?.Dispose();
+ _ipWeb = null;
}
}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj
index 1f347fb..7ddf26d 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/QuickLook.Plugin.ImageViewer.csproj
@@ -55,6 +55,7 @@
+
all
@@ -91,7 +92,7 @@
-
+
QuickLook.Plugin.ImageViewer.Resources.%(RecursiveDir)%(Filename)%(Extension)
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/lottie2html.html b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/lottie2html.html
new file mode 100644
index 0000000..ca104c4
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/lottie2html.html
@@ -0,0 +1,25 @@
+
+
+
+
+ LottieFiles Preview
+
+
+
+
+
+
+
+
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/lottie2html.js b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/lottie2html.js
new file mode 100644
index 0000000..497f239
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/lottie2html.js
@@ -0,0 +1,37 @@
+/**
+ * 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 LottieViewer {
+ constructor() {
+ }
+
+ /**
+ * Play Lottie files.
+ * @async
+ */
+ async play() {
+ const path = await chrome.webview.hostObjects.external.GetPath();
+ lottie.loadAnimation({
+ container: document.getElementById('bm'),
+ renderer: 'svg',
+ loop: true,
+ autoplay: true,
+ path: 'https://' + path,
+ });
+ }
+}
+
+// Create the Lottie viewer and play
+new LottieViewer().play();
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.html b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svg2html.html
similarity index 100%
rename from QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.html
rename to QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svg2html.html
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svg2html.js
similarity index 100%
rename from QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js
rename to QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svg2html.js
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.html b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svga2html.html
similarity index 100%
rename from QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.html
rename to QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svga2html.html
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.js b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svga2html.js
similarity index 100%
rename from QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svga2html.js
rename to QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/Web/svga2html.js
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs
deleted file mode 100644
index 20060e8..0000000
--- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/SvgMetaProvider.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Windows;
-using System.Xml.Linq;
-
-namespace QuickLook.Plugin.ImageViewer;
-
-public class SvgMetaProvider(string path)
-{
- private readonly string _path = path;
- private Size _size = Size.Empty;
-
- public Size GetSize()
- {
- if (_size != Size.Empty)
- {
- return _size;
- }
-
- if (!File.Exists(_path))
- {
- return _size;
- }
-
- if (_path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
- {
- try
- {
- 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)
- {
- _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);
- }
- }
-
- return _size;
- }
-
- private static float? TryParseSvgLength(string input)
- {
- if (string.IsNullOrEmpty(input))
- return null;
-
- var match = Regex.Match(input.Trim(), @"^([\d.]+)(px|pt|mm|cm|in|em|ex|%)?$", RegexOptions.IgnoreCase);
- if (match.Success && float.TryParse(match.Groups[1].Value, out float value))
- {
- return value;
- }
- return null;
- }
-}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/IWebImagePanel.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/IWebImagePanel.cs
new file mode 100644
index 0000000..114f6f0
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/IWebImagePanel.cs
@@ -0,0 +1,25 @@
+// Copyright © 2017-2025 QL-Win Contributors
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System;
+
+namespace QuickLook.Plugin.ImageViewer.Webview;
+
+internal interface IWebImagePanel : IDisposable
+{
+ public void Preview(string path);
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/IWebMetaProvider.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/IWebMetaProvider.cs
new file mode 100644
index 0000000..bfb2dc7
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/IWebMetaProvider.cs
@@ -0,0 +1,25 @@
+// Copyright © 2017-2025 QL-Win Contributors
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Windows;
+
+namespace QuickLook.Plugin.ImageViewer.Webview;
+
+internal interface IWebMetaProvider
+{
+ public Size GetSize();
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/Lottie/LottieDetector.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/Lottie/LottieDetector.cs
new file mode 100644
index 0000000..6271b01
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/Lottie/LottieDetector.cs
@@ -0,0 +1,51 @@
+// Copyright © 2017-2025 QL-Win Contributors
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Collections.Generic;
+using System.IO;
+
+namespace QuickLook.Plugin.ImageViewer.Webview.Lottie;
+
+internal static class LottieDetector
+{
+ public static bool IsVaild(string path)
+ {
+ try
+ {
+ var jsonString = File.ReadAllText(path);
+
+ // No exception will be thrown here
+ var jsonLottie = LottieParser.Parse>(jsonString);
+
+ if (jsonLottie != null
+ && jsonLottie.ContainsKey("v")
+ && jsonLottie.ContainsKey("fr")
+ && jsonLottie.ContainsKey("ip")
+ && jsonLottie.ContainsKey("op")
+ && jsonLottie.ContainsKey("layers"))
+ {
+ return true;
+ }
+ }
+ catch
+ {
+ // If any exception occurs, assume it's not a valid Lottie file
+ }
+
+ return false;
+ }
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/Lottie/LottieExtractor.cs b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/Lottie/LottieExtractor.cs
new file mode 100644
index 0000000..eade22f
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Webview/Lottie/LottieExtractor.cs
@@ -0,0 +1,97 @@
+// Copyright © 2017-2025 QL-Win Contributors
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+
+namespace QuickLook.Plugin.ImageViewer.Webview.Lottie;
+
+internal static class LottieExtractor
+{
+ public static string GetJsonContent(string path)
+ {
+ using var fileStream = File.OpenRead(path);
+ using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
+
+ var manifestEntry = zipArchive.GetEntry("manifest.json");
+ List idEntries = [];
+
+ if (manifestEntry != null)
+ {
+ using var manifestStream = manifestEntry.Open();
+ using var manifestReader = new StreamReader(manifestStream, Encoding.UTF8);
+ string content = manifestReader.ReadToEnd();
+
+ if (!string.IsNullOrEmpty(content))
+ {
+ var manifestJson = LottieParser.Parse>(content);
+
+ if (manifestJson.ContainsKey("animations"))
+ {
+ object animations = manifestJson["animations"];
+
+ if (manifestJson["animations"] is IEnumerable