From 071ecebe292676aa21243bb0edf73cb7bbdd49ae Mon Sep 17 00:00:00 2001 From: Willems Davy Date: Sat, 4 Sep 2021 12:50:59 +0200 Subject: [PATCH] Add Image Deduplicator option for #2 --- FileDeDuplicator.cs | 51 ++++++++++++++++++++++++++ HtmlExporterPlugin.cs | 22 +++++++---- HtmlExporterPlugin.csproj | 1 + HtmlExporterPluginSettingsView.xaml.cs | 2 +- ImageOptions.cs | 3 +- ImageOptionsView.xaml | 3 ++ ImageProcessRunner.cs | 39 ++++++++++++-------- Localization/LocSource.xaml | 1 + Localization/af_ZA.xaml | 1 + Localization/ar_SA.xaml | 1 + Localization/ca_ES.xaml | 1 + Localization/cs_CZ.xaml | 1 + Localization/da_DK.xaml | 1 + Localization/de_DE.xaml | 1 + Localization/el_GR.xaml | 1 + Localization/en_US.xaml | 1 + Localization/eo_UY.xaml | 1 + Localization/es_ES.xaml | 1 + Localization/et_EE.xaml | 1 + Localization/fa_IR.xaml | 1 + Localization/fi_FI.xaml | 1 + Localization/fr_FR.xaml | 1 + Localization/he_IL.xaml | 1 + Localization/hr_HR.xaml | 1 + Localization/hu_HU.xaml | 1 + Localization/id_ID.xaml | 1 + Localization/it_IT.xaml | 1 + Localization/ja_JP.xaml | 1 + Localization/ko_KR.xaml | 1 + Localization/lt_LT.xaml | 1 + Localization/nl_NL.xaml | 1 + Localization/no_NO.xaml | 1 + Localization/pl_PL.xaml | 1 + Localization/pt_BR.xaml | 1 + Localization/pt_PT.xaml | 1 + Localization/ro_RO.xaml | 1 + Localization/ru_RU.xaml | 1 + Localization/sk_SK.xaml | 1 + Localization/sr_SP.xaml | 1 + Localization/sv_SE.xaml | 1 + Localization/tr_TR.xaml | 1 + Localization/uk_UA.xaml | 1 + Localization/vi_VN.xaml | 1 + Localization/zh_CN.xaml | 1 + Localization/zh_TW.xaml | 1 + extension.yaml | 2 +- 46 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 FileDeDuplicator.cs diff --git a/FileDeDuplicator.cs b/FileDeDuplicator.cs new file mode 100644 index 0000000..9bf1884 --- /dev/null +++ b/FileDeDuplicator.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace HtmlExporterPlugin +{ + class FileDeDuplicator + { + private Dictionary DuplicateDictionary = new Dictionary(); + + private static string CalculateMD5(string filename) + { + using (var md5 = MD5.Create()) + { + using (var stream = new BufferedStream(File.OpenRead(filename), 1048576)) + { + var hash = md5.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } + + public void clear() + { + DuplicateDictionary.Clear(); + } + + public string GetUniqueFile(string fullfilename, string storedfilename, bool DoCheck) + { + if (!DoCheck || !File.Exists(fullfilename)) + { + return storedfilename; + } + + string md5 = CalculateMD5(fullfilename); + if (DuplicateDictionary.ContainsKey(md5)) + { + return DuplicateDictionary[md5]; + } + else + { + DuplicateDictionary[md5] = storedfilename; + return storedfilename; + } + } + } +} diff --git a/HtmlExporterPlugin.cs b/HtmlExporterPlugin.cs index 505725a..c9ba31e 100644 --- a/HtmlExporterPlugin.cs +++ b/HtmlExporterPlugin.cs @@ -13,6 +13,7 @@ using System.Threading; using System.Web; using System.Windows.Controls; +using System.Security.Cryptography; //using ZetaProducerHtmlCompressor.Internal; namespace HtmlExporterPlugin @@ -121,6 +122,7 @@ public void DoExportToHtml() Dictionary GameMediaHashtable = new Dictionary(); Dictionary GameMediaCopyDoneDict = new Dictionary(); Dictionary FirstGroupFieldFileNames = new Dictionary(); + FileDeDuplicator DeDuplicator = new FileDeDuplicator(); int pagecount = Settings.Pages.Count; int PageNr = 0; int Errors = 0; @@ -1134,6 +1136,7 @@ public void DoExportToHtml() gameicon = realgame.Platform.Icon.Replace("\\", "/"); } } + gameicon = DeDuplicator.GetUniqueFile(PlayniteApi.Database.GetFullFilePath(gameicon), gameicon, Settings.ConvertImageOptions.DetectDuplicates); } GameMediaHashtable[Constants.MediaIconText + realgame.Id.ToString()] = gameicon; } @@ -1169,6 +1172,8 @@ public void DoExportToHtml() coverimage = realgame.Platform.Cover.Replace("\\", "/"); } } + + coverimage = DeDuplicator.GetUniqueFile(PlayniteApi.Database.GetFullFilePath(coverimage), coverimage, Settings.ConvertImageOptions.DetectDuplicates); } GameMediaHashtable[Constants.MediaCoverText + realgame.Id.ToString()] = coverimage; } @@ -1190,17 +1195,20 @@ public void DoExportToHtml() { backgroundimage = filespathbackground; } - else - if ((filespathbackground != String.Empty) && File.Exists(PlayniteApi.Database.GetFullFilePath(filespathbackground))) - { - backgroundimage = realgame.BackgroundImage.Replace("\\", "/"); - } else { - if (!String.IsNullOrEmpty(realgame.Platform?.Background)) + if ((filespathbackground != String.Empty) && File.Exists(PlayniteApi.Database.GetFullFilePath(filespathbackground))) { - backgroundimage = realgame.Platform.Background.Replace("\\", "/"); + backgroundimage = realgame.BackgroundImage.Replace("\\", "/"); + } + else + { + if (!String.IsNullOrEmpty(realgame.Platform?.Background)) + { + backgroundimage = realgame.Platform.Background.Replace("\\", "/"); + } } + backgroundimage = DeDuplicator.GetUniqueFile(PlayniteApi.Database.GetFullFilePath(backgroundimage), backgroundimage, Settings.ConvertImageOptions.DetectDuplicates); } GameMediaHashtable[Constants.MediaBackgroundText + realgame.Id.ToString()] = backgroundimage; } diff --git a/HtmlExporterPlugin.csproj b/HtmlExporterPlugin.csproj index 9934058..1eb1722 100644 --- a/HtmlExporterPlugin.csproj +++ b/HtmlExporterPlugin.csproj @@ -55,6 +55,7 @@ + diff --git a/HtmlExporterPluginSettingsView.xaml.cs b/HtmlExporterPluginSettingsView.xaml.cs index c329c12..ae8188a 100644 --- a/HtmlExporterPluginSettingsView.xaml.cs +++ b/HtmlExporterPluginSettingsView.xaml.cs @@ -261,7 +261,7 @@ private void ButImageOptions_Click(object sender, RoutedEventArgs e) }); - window.Height = 450; + window.Height = 475; window.Width = 800; window.Title = Constants.ImageOptionsText; diff --git a/ImageOptions.cs b/ImageOptions.cs index b941680..205283b 100644 --- a/ImageOptions.cs +++ b/ImageOptions.cs @@ -32,6 +32,7 @@ public class ImageOptions public bool AlwaysProcess { get; set; } = false; + public bool DetectDuplicates { get; set; } = false; public string GetUniqueString(bool includeMaxTasks = false, bool includeAlwaysProcess = false) { @@ -39,7 +40,7 @@ public string GetUniqueString(bool includeMaxTasks = false, bool includeAlwaysPr ResizeCoverImage.ToString() + '_' + CoverImageWidth + '_' + CoverImageHeight + '_' + ResizeBackgroundImage.ToString() + '_' + BackgroundImageWidth + '_' + BackgroundImageHeight + '_' + ResizeIconImage.ToString() + '_' + IconImageWidth + '_' + IconImageHeight + '_' + - ForceConversion.ToString() + (includeMaxTasks ? '_' + MaxTasks.ToString() : String.Empty) + + ForceConversion.ToString() + '_' + DetectDuplicates.ToString() + (includeMaxTasks ? '_' + MaxTasks.ToString() : String.Empty) + (includeAlwaysProcess ? '_' + AlwaysProcess.ToString() : String.Empty); } diff --git a/ImageOptionsView.xaml b/ImageOptionsView.xaml index 8df4029..27f1f97 100644 --- a/ImageOptionsView.xaml +++ b/ImageOptionsView.xaml @@ -24,6 +24,9 @@ + + + diff --git a/ImageProcessRunner.cs b/ImageProcessRunner.cs index c91d2f3..0ca474c 100644 --- a/ImageProcessRunner.cs +++ b/ImageProcessRunner.cs @@ -45,7 +45,7 @@ public ImageProcessDef(ImageProcessDef Source) public int FailedConverts = 0; public List FailedFiles = new List(); - private readonly List ImagesProcessDefList = new List(); + private readonly Dictionary ImagesProcessDefDict = new Dictionary(); private CancellationTokenSource cancellationTokenSource = null; private static int StartProcessWait(string path, string arguments, string workDir, bool noWindow = false) @@ -77,22 +77,25 @@ private static int StartProcessWait(string path, string arguments, string workDi public void addImageProcess(bool copyonly, string source, string dest, string destconverted, string exepath, string arguments, string workDir, bool noWindow = false) { - ImageProcessDef ImageProcess = new ImageProcessDef(); - ImageProcess.path = exepath; - ImageProcess.arguments = arguments; - ImageProcess.workDir = workDir; - ImageProcess.noWindow = noWindow; - ImageProcess.copyonly = copyonly; - ImageProcess.source = source; - ImageProcess.dest = dest; - ImageProcess.destconverted = destconverted; - ImagesProcessDefList.Add(ImageProcess); + if (!ImagesProcessDefDict.ContainsKey(source)) + { + ImageProcessDef ImageProcess = new ImageProcessDef(); + ImageProcess.path = exepath; + ImageProcess.arguments = arguments; + ImageProcess.workDir = workDir; + ImageProcess.noWindow = noWindow; + ImageProcess.copyonly = copyonly; + ImageProcess.source = source; + ImageProcess.dest = dest; + ImageProcess.destconverted = destconverted; + ImagesProcessDefDict.Add(source, ImageProcess); + } } public void Clear() { - ImagesProcessDefList.Clear(); + ImagesProcessDefDict.Clear(); } public void Stop() @@ -105,14 +108,14 @@ public void Stop() public int Count() { - return ImagesProcessDefList.Count; + return ImagesProcessDefDict.Count; } public void Start(int maxConcurrency, DelCallback CallBack) { using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency)) { - if (ImagesProcessDefList.Count == 0) + if (ImagesProcessDefDict.Count == 0) { return; } @@ -121,9 +124,9 @@ public void Start(int maxConcurrency, DelCallback CallBack) FailedConverts = 0; SuccesFullConverts = 0; FailedFiles.Clear(); - int max = ImagesProcessDefList.Count(); + int max = ImagesProcessDefDict.Count(); List> tasks = new List>(); - foreach (ImageProcessDef ImageProcess in ImagesProcessDefList) + foreach (ImageProcessDef ImageProcess in ImagesProcessDefDict.Values) { concurrencySemaphore.Wait(); Task t = Task.Factory.StartNew((object o) => @@ -186,6 +189,10 @@ public void Start(int maxConcurrency, DelCallback CallBack) return File.Exists(ImageProcessDefTask.destconverted); } } + catch + { + return false; + } finally { _ = concurrencySemaphore.Release(); diff --git a/Localization/LocSource.xaml b/Localization/LocSource.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/LocSource.xaml +++ b/Localization/LocSource.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/af_ZA.xaml b/Localization/af_ZA.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/af_ZA.xaml +++ b/Localization/af_ZA.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/ar_SA.xaml b/Localization/ar_SA.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/ar_SA.xaml +++ b/Localization/ar_SA.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/ca_ES.xaml b/Localization/ca_ES.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/ca_ES.xaml +++ b/Localization/ca_ES.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/cs_CZ.xaml b/Localization/cs_CZ.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/cs_CZ.xaml +++ b/Localization/cs_CZ.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/da_DK.xaml b/Localization/da_DK.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/da_DK.xaml +++ b/Localization/da_DK.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/de_DE.xaml b/Localization/de_DE.xaml index a6b090c..4268d2e 100644 --- a/Localization/de_DE.xaml +++ b/Localization/de_DE.xaml @@ -189,6 +189,7 @@ Gesamte zu verarbeitende Bilder: Bilder immer verarbeiten, auch wenn sie nicht geändert wurden optimierungen + Doppelte Bilder erkennen diff --git a/Localization/el_GR.xaml b/Localization/el_GR.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/el_GR.xaml +++ b/Localization/el_GR.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/en_US.xaml b/Localization/en_US.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/en_US.xaml +++ b/Localization/en_US.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/eo_UY.xaml b/Localization/eo_UY.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/eo_UY.xaml +++ b/Localization/eo_UY.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/es_ES.xaml b/Localization/es_ES.xaml index da32cd4..8502283 100644 --- a/Localization/es_ES.xaml +++ b/Localization/es_ES.xaml @@ -189,6 +189,7 @@ Total de imágenes para procesar: Siempre procesar imágenes, incluso si no han cambiado optimizaciones + Detectar imágenes duplicadas diff --git a/Localization/et_EE.xaml b/Localization/et_EE.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/et_EE.xaml +++ b/Localization/et_EE.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/fa_IR.xaml b/Localization/fa_IR.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/fa_IR.xaml +++ b/Localization/fa_IR.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/fi_FI.xaml b/Localization/fi_FI.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/fi_FI.xaml +++ b/Localization/fi_FI.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/fr_FR.xaml b/Localization/fr_FR.xaml index eda2e3c..8a287ff 100644 --- a/Localization/fr_FR.xaml +++ b/Localization/fr_FR.xaml @@ -189,6 +189,7 @@ Total des images à traiter: Toujours traiter les images, même si elles n'ont pas changé optimizations + Détecter les doublons d'images diff --git a/Localization/he_IL.xaml b/Localization/he_IL.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/he_IL.xaml +++ b/Localization/he_IL.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/hr_HR.xaml b/Localization/hr_HR.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/hr_HR.xaml +++ b/Localization/hr_HR.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/hu_HU.xaml b/Localization/hu_HU.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/hu_HU.xaml +++ b/Localization/hu_HU.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/id_ID.xaml b/Localization/id_ID.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/id_ID.xaml +++ b/Localization/id_ID.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/it_IT.xaml b/Localization/it_IT.xaml index 2a560af..b7a5d93 100644 --- a/Localization/it_IT.xaml +++ b/Localization/it_IT.xaml @@ -189,6 +189,7 @@ Totale immagini da elaborare: Elaborare sempre le immagini, anche se non sono cambiate ottimizzazioni + Rileva Immagini Duplicate diff --git a/Localization/ja_JP.xaml b/Localization/ja_JP.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/ja_JP.xaml +++ b/Localization/ja_JP.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/ko_KR.xaml b/Localization/ko_KR.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/ko_KR.xaml +++ b/Localization/ko_KR.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/lt_LT.xaml b/Localization/lt_LT.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/lt_LT.xaml +++ b/Localization/lt_LT.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/nl_NL.xaml b/Localization/nl_NL.xaml index 8f35e55..1edcde7 100644 --- a/Localization/nl_NL.xaml +++ b/Localization/nl_NL.xaml @@ -189,6 +189,7 @@ Totaal aantal afbeeldingen te verwerken: Altijd afbeeldingen verwerken, zelfs wanneer deze niet gewijzigd zijn optimalisaties + Dubbele afbeeldingen detecteren diff --git a/Localization/no_NO.xaml b/Localization/no_NO.xaml index 1065726..84d18bd 100644 --- a/Localization/no_NO.xaml +++ b/Localization/no_NO.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/pl_PL.xaml b/Localization/pl_PL.xaml index bf33236..1f1395c 100644 --- a/Localization/pl_PL.xaml +++ b/Localization/pl_PL.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/pt_BR.xaml b/Localization/pt_BR.xaml index d034e96..33ab8d9 100644 --- a/Localization/pt_BR.xaml +++ b/Localization/pt_BR.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/pt_PT.xaml b/Localization/pt_PT.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/pt_PT.xaml +++ b/Localization/pt_PT.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/ro_RO.xaml b/Localization/ro_RO.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/ro_RO.xaml +++ b/Localization/ro_RO.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/ru_RU.xaml b/Localization/ru_RU.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/ru_RU.xaml +++ b/Localization/ru_RU.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/sk_SK.xaml b/Localization/sk_SK.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/sk_SK.xaml +++ b/Localization/sk_SK.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/sr_SP.xaml b/Localization/sr_SP.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/sr_SP.xaml +++ b/Localization/sr_SP.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/sv_SE.xaml b/Localization/sv_SE.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/sv_SE.xaml +++ b/Localization/sv_SE.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/tr_TR.xaml b/Localization/tr_TR.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/tr_TR.xaml +++ b/Localization/tr_TR.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/uk_UA.xaml b/Localization/uk_UA.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/uk_UA.xaml +++ b/Localization/uk_UA.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/vi_VN.xaml b/Localization/vi_VN.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/vi_VN.xaml +++ b/Localization/vi_VN.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/zh_CN.xaml b/Localization/zh_CN.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/zh_CN.xaml +++ b/Localization/zh_CN.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/Localization/zh_TW.xaml b/Localization/zh_TW.xaml index ba7ca0d..faa50fe 100644 --- a/Localization/zh_TW.xaml +++ b/Localization/zh_TW.xaml @@ -189,6 +189,7 @@ Total images to process: Always process images, even if they have not changed optimizations + Detect Duplicate Images diff --git a/extension.yaml b/extension.yaml index 54370e0..5bfd110 100644 --- a/extension.yaml +++ b/extension.yaml @@ -1,7 +1,7 @@ Id: HtmlExporterPlugin_14bd031a-a1ff-4754-a586-0b9c23a6f557 Name: HTML Exporter Author: Joyrider3774 -Version: 2.0 +Version: 2.1 Module: HtmlExporterPlugin.dll Type: GenericPlugin Icon: icon.png