diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/InfoPanels/NugetInfoPanel.xaml b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/InfoPanels/NugetInfoPanel.xaml
new file mode 100644
index 0000000..ce96051
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/InfoPanels/NugetInfoPanel.xaml
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/InfoPanels/NugetInfoPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/InfoPanels/NugetInfoPanel.xaml.cs
new file mode 100644
index 0000000..1c16c56
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/InfoPanels/NugetInfoPanel.xaml.cs
@@ -0,0 +1,138 @@
+// Copyright © 2017-2026 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 QuickLook.Common.ExtensionMethods;
+using QuickLook.Common.Helpers;
+using QuickLook.Common.Plugin;
+using QuickLook.Plugin.AppViewer.PackageParsers.Nuget;
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Navigation;
+
+namespace QuickLook.Plugin.AppViewer.InfoPanels;
+
+public partial class NugetInfoPanel : UserControl, IAppInfoPanel
+{
+ private readonly ContextObject _context;
+
+ public NugetInfoPanel(ContextObject context)
+ {
+ _context = context;
+
+ DataContext = this;
+ InitializeComponent();
+
+ string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config");
+ packageIdTitle.Text = TranslationHelper.Get("NUGET_PACKAGE_ID", translationFile);
+ versionTitle.Text = TranslationHelper.Get("APP_VERSION", translationFile);
+ authorsTitle.Text = TranslationHelper.Get("NUGET_AUTHORS", translationFile);
+ licenseTitle.Text = TranslationHelper.Get("NUGET_LICENSE", translationFile);
+ projectUrlTitle.Text = TranslationHelper.Get("NUGET_PROJECT_URL", translationFile);
+ repoUrlTitle.Text = TranslationHelper.Get("NUGET_REPO_URL", translationFile);
+ frameworksTitle.Text = TranslationHelper.Get("NUGET_FRAMEWORKS", translationFile);
+ totalSizeTitle.Text = TranslationHelper.Get("TOTAL_SIZE", translationFile);
+ modDateTitle.Text = TranslationHelper.Get("LAST_MODIFIED", translationFile);
+ dependenciesGroupBox.Header = TranslationHelper.Get("NUGET_DEPENDENCIES", translationFile);
+ }
+
+ public void DisplayInfo(string path)
+ {
+ var name = Path.GetFileName(path);
+ filename.Text = string.IsNullOrEmpty(name) ? path : name;
+
+ _ = Task.Run(() =>
+ {
+ if (!File.Exists(path)) return;
+
+ var size = new FileInfo(path).Length;
+ NugetInfo nugetInfo = NugetParser.Parse(path);
+ var last = File.GetLastWriteTime(path);
+
+ Dispatcher.Invoke(() =>
+ {
+ packageId.Text = nugetInfo.PackageId ?? string.Empty;
+ version.Text = nugetInfo.Version ?? string.Empty;
+ authors.Text = nugetInfo.Authors ?? string.Empty;
+
+ // License
+ licenseBlock.Text = nugetInfo.License ?? string.Empty;
+
+ // Project URL
+ if (!string.IsNullOrWhiteSpace(nugetInfo.ProjectUrl) &&
+ Uri.TryCreate(nugetInfo.ProjectUrl, UriKind.Absolute, out var projectUri))
+ {
+ projectUrlText.Text = nugetInfo.ProjectUrl;
+ projectUrlLink.NavigateUri = projectUri;
+ projectUrlTitle.Visibility = Visibility.Visible;
+ projectUrlBlock.Visibility = Visibility.Visible;
+ }
+
+ // Source Repository URL
+ if (!string.IsNullOrWhiteSpace(nugetInfo.RepositoryUrl) &&
+ Uri.TryCreate(nugetInfo.RepositoryUrl, UriKind.Absolute, out var repoUri))
+ {
+ repoUrlText.Text = nugetInfo.RepositoryUrl;
+ repoUrlLink.NavigateUri = repoUri;
+ repoUrlTitle.Visibility = Visibility.Visible;
+ repoUrlBlock.Visibility = Visibility.Visible;
+ }
+
+ // Target Frameworks
+ frameworks.Text = nugetInfo.TargetFrameworks?.Length > 0
+ ? string.Join(", ", nugetInfo.TargetFrameworks)
+ : string.Empty;
+
+ totalSize.Text = size.ToPrettySize(2);
+ modDate.Text = last.ToString(CultureInfo.CurrentCulture);
+
+ // Dependencies
+ if (nugetInfo.Dependencies?.Length > 0)
+ {
+ dependencies.ItemsSource = nugetInfo.Dependencies;
+ }
+
+ // Icon — use embedded icon if available, otherwise keep default nuget.png
+ if (nugetInfo.Icon != null)
+ {
+ using var icon = nugetInfo.Icon;
+ image.Source = icon.ToBitmapSource();
+ }
+
+ _context.IsBusy = false;
+ });
+ });
+ }
+
+ private void OnHyperlinkNavigate(object sender, RequestNavigateEventArgs e)
+ {
+ try
+ {
+ Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
+ }
+ catch
+ {
+ // Ignore if the browser cannot be launched
+ }
+ e.Handled = true;
+ }
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/PackageParsers/Nuget/NugetInfo.cs b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/PackageParsers/Nuget/NugetInfo.cs
new file mode 100644
index 0000000..70daa0f
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/PackageParsers/Nuget/NugetInfo.cs
@@ -0,0 +1,43 @@
+// Copyright © 2017-2026 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.Drawing;
+
+namespace QuickLook.Plugin.AppViewer.PackageParsers.Nuget;
+
+public class NugetInfo
+{
+ public string PackageId { get; set; }
+
+ public string Version { get; set; }
+
+ public string Authors { get; set; }
+
+ public string Description { get; set; }
+
+ public string ProjectUrl { get; set; }
+
+ public string RepositoryUrl { get; set; }
+
+ public string License { get; set; }
+
+ public Bitmap Icon { get; set; }
+
+ public string[] TargetFrameworks { get; set; } = [];
+
+ public string[] Dependencies { get; set; } = [];
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/PackageParsers/Nuget/NugetParser.cs b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/PackageParsers/Nuget/NugetParser.cs
new file mode 100644
index 0000000..d22787b
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/PackageParsers/Nuget/NugetParser.cs
@@ -0,0 +1,169 @@
+// Copyright © 2017-2026 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 ICSharpCode.SharpZipLib.Zip;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Xml.Linq;
+
+namespace QuickLook.Plugin.AppViewer.PackageParsers.Nuget;
+
+public static class NugetParser
+{
+ public static NugetInfo Parse(string path)
+ {
+ NugetInfo info = new();
+
+ try
+ {
+ using var zip = new ZipFile(path);
+
+ // Find .nuspec entry (only one should exist at the root or in a subdirectory)
+ ZipEntry nuspecEntry = null;
+ foreach (ZipEntry entry in zip)
+ {
+ if (!entry.IsDirectory && entry.Name.EndsWith(".nuspec", StringComparison.OrdinalIgnoreCase))
+ {
+ nuspecEntry = entry;
+ break;
+ }
+ }
+
+ if (nuspecEntry == null) return info;
+
+ // Parse nuspec XML
+ XDocument doc;
+ using (var stream = zip.GetInputStream(nuspecEntry))
+ {
+ doc = XDocument.Load(stream);
+ }
+
+ // Handle XML namespace (nuspec uses versioned namespace)
+ XNamespace ns = doc.Root?.GetDefaultNamespace() ?? XNamespace.None;
+ var metadata = doc.Root?.Element(ns + "metadata");
+ if (metadata == null) return info;
+
+ info.PackageId = metadata.Element(ns + "id")?.Value?.Trim();
+ info.Version = metadata.Element(ns + "version")?.Value?.Trim();
+ info.Authors = metadata.Element(ns + "authors")?.Value?.Trim();
+ info.Description = metadata.Element(ns + "description")?.Value?.Trim();
+ info.ProjectUrl = metadata.Element(ns + "projectUrl")?.Value?.Trim();
+
+ // Repository URL
+ var repoEl = metadata.Element(ns + "repository");
+ if (repoEl != null)
+ {
+ info.RepositoryUrl = repoEl.Attribute("url")?.Value?.Trim();
+ }
+
+ // License: prefer element, fall back to
+ var licenseEl = metadata.Element(ns + "license");
+ if (licenseEl != null)
+ {
+ info.License = licenseEl.Value?.Trim();
+ }
+ else
+ {
+ info.License = metadata.Element(ns + "licenseUrl")?.Value?.Trim();
+ }
+
+ // Icon — look up the embedded icon file in the zip
+ var iconPath = metadata.Element(ns + "icon")?.Value?.Trim();
+ if (!string.IsNullOrEmpty(iconPath))
+ {
+ // Normalize path separators for comparison
+ string normalizedIconPath = iconPath.Replace('\\', '/');
+ foreach (ZipEntry entry in zip)
+ {
+ if (!entry.IsDirectory &&
+ string.Equals(entry.Name.Replace('\\', '/'), normalizedIconPath, StringComparison.OrdinalIgnoreCase))
+ {
+ using var iconStream = zip.GetInputStream(entry);
+ using var ms = new MemoryStream();
+ iconStream.CopyTo(ms);
+ ms.Position = 0;
+ // Clone the bitmap so it doesn't depend on the stream
+ using var tmpBitmap = new Bitmap(ms);
+ info.Icon = new Bitmap(tmpBitmap);
+ break;
+ }
+ }
+ }
+
+ // Target Frameworks and Dependencies
+ var depsEl = metadata.Element(ns + "dependencies");
+ if (depsEl != null)
+ {
+ var groups = depsEl.Elements(ns + "group").ToList();
+
+ if (groups.Count > 0)
+ {
+ // Collect distinct target frameworks
+ info.TargetFrameworks = groups
+ .Select(g => g.Attribute("targetFramework")?.Value?.Trim())
+ .Where(s => !string.IsNullOrEmpty(s))
+ .Distinct()
+ .ToArray();
+
+ // Format all dependencies grouped by framework
+ var depLines = new List();
+ foreach (var group in groups)
+ {
+ string fw = group.Attribute("targetFramework")?.Value?.Trim();
+ var deps = group.Elements(ns + "dependency").ToList();
+ if (deps.Count == 0) continue;
+
+ if (!string.IsNullOrEmpty(fw))
+ depLines.Add($"[{fw}]");
+
+ foreach (var dep in deps)
+ {
+ string id = dep.Attribute("id")?.Value?.Trim() ?? string.Empty;
+ string ver = dep.Attribute("version")?.Value?.Trim() ?? string.Empty;
+ string exclude = dep.Attribute("exclude")?.Value?.Trim();
+ string line = string.IsNullOrEmpty(ver) ? id : $"{id} ({ver})";
+ depLines.Add($" {line}");
+ }
+ }
+ info.Dependencies = depLines.ToArray();
+ }
+ else
+ {
+ // No groups — direct top-level dependencies
+ info.Dependencies = depsEl.Elements(ns + "dependency")
+ .Select(d =>
+ {
+ string id = d.Attribute("id")?.Value?.Trim() ?? string.Empty;
+ string ver = d.Attribute("version")?.Value?.Trim() ?? string.Empty;
+ return string.IsNullOrEmpty(ver) ? id : $"{id} ({ver})";
+ })
+ .Where(s => !string.IsNullOrWhiteSpace(s))
+ .ToArray();
+ }
+ }
+ }
+ catch
+ {
+ // Return whatever partial info was collected
+ }
+
+ return info;
+ }
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs
index d607f09..487d605 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs
@@ -57,6 +57,10 @@ public sealed class Plugin : IViewer
// Others
".wgt", ".wgtu", // UniApp Widget
+
+ // NuGet
+ ".nupkg", // NuGet Package
+ ".snupkg", // NuGet Symbol Package
];
private IAppInfoPanel _ip;
@@ -87,6 +91,7 @@ public sealed class Plugin : IViewer
".appimage" => new Size { Width = 600, Height = 300 },
".rpm" => new Size { Width = 600, Height = 260 },
".wgt" or ".wgtu" => new Size { Width = 600, Height = 345 },
+ ".nupkg" or ".snupkg" => new Size { Width = 660, Height = 580 },
_ => throw new NotSupportedException("Extension is not supported."),
};
context.Title = string.Empty;
@@ -112,6 +117,7 @@ public sealed class Plugin : IViewer
".appimage" => new AppImageInfoPanel(context),
".rpm" => new RpmInfoPanel(context),
".wgt" or ".wgtu" => new WgtInfoPanel(context),
+ ".nupkg" or ".snupkg" => new NugetInfoPanel(context),
_ => throw new NotSupportedException("Extension is not supported."),
};
diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config
index 2ab732b..f3eb31c 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config
+++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config
@@ -33,6 +33,13 @@
النوع
طرفية
المورد
+ معرّف الحزمة
+ المؤلفون
+ موقع المشروع
+ مستودع المصدر
+ الترخيص
+ أطر العمل المستهدفة
+ التبعيات
Termékverzió
@@ -66,6 +73,13 @@
Típus
Terminál
Szállító
+ Csomag azonosítója
+ Szerzők
+ Projekt webhelye
+ Forrástár
+ Licenc
+ Cél keretrendszerek
+ Függőségek
Verzia produktu
@@ -99,6 +113,13 @@
Typ
Terminál
Dodávateľ
+ ID balíka
+ Autori
+ Webová stránka projektu
+ Zdrojové úložisko
+ Licencia
+ Cieľové rámce
+ Závislosti
Versi produk
@@ -132,6 +153,13 @@
Jenis
Terminal
Vendor
+ ID Paket
+ Penulis
+ Situs Proyek
+ Repositori Sumber
+ Lisensi
+ Target Framework
+ Dependensi
Product Version
@@ -165,6 +193,13 @@
Type
Terminal
Vendor
+ Package ID
+ Authors
+ Project Website
+ Source Repository
+ License
+ Target Frameworks
+ Dependencies
제품 버전
@@ -198,6 +233,13 @@
유형
터미널
공급업체
+ 패키지 ID
+ 작성자
+ 프로젝트 웹사이트
+ 소스 저장소
+ 라이선스
+ 대상 프레임워크
+ 종속성
Versão do produto
@@ -231,6 +273,13 @@
Tipo
Terminal
Fornecedor
+ ID do pacote
+ Autores
+ Website do projeto
+ Repositório de origem
+ Licença
+ Frameworks de destino
+ Dependências
产品版本
@@ -264,6 +313,13 @@
类型
终端
供应商
+ 包 ID
+ 作者
+ 项目网站
+ 源代码仓库
+ 许可证
+ 目标框架
+ 依赖项
產品版本
@@ -297,6 +353,13 @@
類型
終端機
供應商
+ 套件 ID
+ 作者
+ 專案網站
+ 原始碼存放庫
+ 授權條款
+ 目標架構
+ 相依性
製品バージョン
@@ -330,6 +393,13 @@
種類
ターミナル
ベンダー
+ パッケージ ID
+ 作者
+ プロジェクトのウェブサイト
+ ソースリポジトリ
+ ライセンス
+ 対応フレームワーク
+ 依存関係
Produktversion
@@ -363,6 +433,13 @@
Typ
Terminal
Anbieter
+ Paket-ID
+ Autoren
+ Projekt-Website
+ Quell-Repository
+ Lizenz
+ Ziel-Frameworks
+ Abhängigkeiten
Produktversion
@@ -396,6 +473,13 @@
Typ
Terminal
Leverantör
+ Paket-ID
+ Upphovsmän
+ Projektets webbplats
+ Källkodsförvar
+ Licens
+ Målramverk
+ Beroenden
Versiune produs
@@ -429,5 +513,12 @@
Tip
Terminal
Furnizor
+ ID pachet
+ Autori
+ Site-ul proiectului
+ Depozit sursă
+ Licență
+ Framework-uri țintă
+ Dependențe