2026-09-20 08:31:23 +02:00
|
|
|
using SixLabors.ImageSharp;
|
|
|
|
|
using SixLabors.ImageSharp.Processing;
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
using System.Text.RegularExpressions;
|
2026-09-20 08:31:23 +02:00
|
|
|
|
|
|
|
|
namespace wp2ghost
|
|
|
|
|
{
|
|
|
|
|
// =============================================================================
|
|
|
|
|
// ImageManager — Bilder herunterladen, cachen, lokal verwalten
|
|
|
|
|
// =============================================================================
|
|
|
|
|
static class ImageManager
|
|
|
|
|
{
|
|
|
|
|
private static readonly HttpClient httpClient = new();
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
// Schlüssel: Bild-Schlüssel (siehe GetImageKey) — alle WordPress-Varianten eines Bildes teilen sich einen Eintrag
|
|
|
|
|
private static Dictionary<string, (string SourceUrl, string RelativePath, string LocalPath)> Cache = new();
|
2026-09-20 08:31:23 +02:00
|
|
|
private static List<(string RelativePath, string LocalPath)> FilesToZip = new();
|
|
|
|
|
private static string LocalImageDir = "";
|
|
|
|
|
private static string CachePath = "";
|
2026-10-14 19:12:29 +02:00
|
|
|
// Angehängte, aber im Beitrag nicht verwendete Bilder — bewusst außerhalb von images/
|
|
|
|
|
private const string UnusedImageDirName = "images_unbenutzt";
|
|
|
|
|
private static string UnusedImageDir = "";
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
private static readonly Regex SizeSuffixRegex = new(@"-\d+x\d+(?=\.\w+$)", RegexOptions.Compiled);
|
|
|
|
|
private static readonly Regex ScaledSuffixRegex = new(@"-scaled(?=\.\w+$)", RegexOptions.Compiled);
|
|
|
|
|
|
2026-09-20 08:31:23 +02:00
|
|
|
public static IReadOnlyList<(string RelativePath, string LocalPath)> CachedFiles => FilesToZip;
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Schlüssel, unter dem alle Varianten desselben WordPress-Bildes zusammenfallen:
|
|
|
|
|
/// Pfad ohne Host, Query (?w=1024), Größen-Suffix (-1024x683) und -scaled.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static string GetImageKey(string url)
|
|
|
|
|
{
|
|
|
|
|
string path;
|
|
|
|
|
try { path = new Uri(url).AbsolutePath; }
|
|
|
|
|
catch { path = url.Split('?', '#')[0]; }
|
|
|
|
|
path = SizeSuffixRegex.Replace(path, "");
|
|
|
|
|
path = ScaledSuffixRegex.Replace(path, "");
|
|
|
|
|
return path.ToLowerInvariant();
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-20 08:31:23 +02:00
|
|
|
public static bool TryGetRelativePath(string url, out string relativePath)
|
|
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
if (TryGetCached(GetImageKey(url), out var cached))
|
2026-09-20 08:31:23 +02:00
|
|
|
{
|
|
|
|
|
relativePath = cached.RelativePath;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
relativePath = "";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-09-22 08:08:51 +02:00
|
|
|
|
2026-10-14 19:12:29 +02:00
|
|
|
private const string GhostImagePrefix = "__GHOST_URL__/content/images/";
|
|
|
|
|
private static readonly Dictionary<string, (int Width, int Height)?> SizeCache = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Echte Maße eines lokal vorhandenen Bildes anhand seiner Ghost-URL
|
|
|
|
|
/// (__GHOST_URL__/content/images/...). null, wenn die URL kein lokales Bild ist.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static (int Width, int Height)? TryGetImageSize(string ghostUrl)
|
|
|
|
|
{
|
|
|
|
|
if (!ghostUrl.StartsWith(GhostImagePrefix)) return null;
|
|
|
|
|
string relativePath = ghostUrl.Substring(GhostImagePrefix.Length);
|
|
|
|
|
if (SizeCache.TryGetValue(relativePath, out var known)) return known;
|
|
|
|
|
|
|
|
|
|
(int Width, int Height)? size = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var info = Image.Identify(Path.Combine(LocalImageDir, relativePath));
|
|
|
|
|
if (info != null) size = (info.Width, info.Height);
|
|
|
|
|
}
|
|
|
|
|
catch { }
|
|
|
|
|
SizeCache[relativePath] = size;
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
private static bool TryGetCached(string key, out (string RelativePath, string LocalPath) file)
|
|
|
|
|
{
|
|
|
|
|
if (Cache.TryGetValue(key, out var cached))
|
2026-09-22 08:08:51 +02:00
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
if (File.Exists(cached.LocalPath))
|
2026-09-22 08:08:51 +02:00
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
file = (cached.RelativePath, cached.LocalPath);
|
|
|
|
|
RegisterForZip(file);
|
2026-09-22 08:08:51 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
Cache.Remove(key);
|
2026-09-22 08:08:51 +02:00
|
|
|
}
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
file = default;
|
2026-09-20 08:31:23 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
private static void RegisterForZip((string RelativePath, string LocalPath) file)
|
|
|
|
|
{
|
|
|
|
|
if (!FilesToZip.Any(f => f.RelativePath == file.RelativePath))
|
|
|
|
|
FilesToZip.Add(file);
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-20 08:31:23 +02:00
|
|
|
public static void Init(string baseDir)
|
|
|
|
|
{
|
|
|
|
|
LocalImageDir = Path.Combine(baseDir, "images");
|
2026-10-14 19:12:29 +02:00
|
|
|
UnusedImageDir = Path.Combine(baseDir, UnusedImageDirName);
|
2026-09-20 08:31:23 +02:00
|
|
|
CachePath = Path.Combine(baseDir, "imagecache.txt");
|
|
|
|
|
|
|
|
|
|
if (!Directory.Exists(LocalImageDir))
|
|
|
|
|
Directory.CreateDirectory(LocalImageDir);
|
|
|
|
|
|
|
|
|
|
LoadCache();
|
|
|
|
|
}
|
|
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
public static string ImageContainerPath => LocalImageDir;
|
2026-09-20 08:31:23 +02:00
|
|
|
|
|
|
|
|
public static void SaveCache()
|
|
|
|
|
{
|
|
|
|
|
var lines = new List<string>();
|
|
|
|
|
foreach (var kvp in Cache)
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
lines.Add($"{kvp.Value.SourceUrl}|{kvp.Value.RelativePath}|{kvp.Value.LocalPath}|{kvp.Key}");
|
2026-09-20 08:31:23 +02:00
|
|
|
File.WriteAllLines(CachePath, lines);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ClearAll()
|
|
|
|
|
{
|
|
|
|
|
if (Directory.Exists(LocalImageDir))
|
|
|
|
|
{
|
|
|
|
|
Directory.Delete(LocalImageDir, true);
|
|
|
|
|
Directory.CreateDirectory(LocalImageDir);
|
|
|
|
|
}
|
2026-10-14 19:12:29 +02:00
|
|
|
if (Directory.Exists(UnusedImageDir))
|
|
|
|
|
Directory.Delete(UnusedImageDir, true);
|
2026-09-20 08:31:23 +02:00
|
|
|
Cache.Clear();
|
|
|
|
|
FilesToZip.Clear();
|
|
|
|
|
SaveCache();
|
|
|
|
|
Console.WriteLine("Bilder wurden lokal gelöscht.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ShowInfo()
|
|
|
|
|
{
|
|
|
|
|
if (Cache.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("\nLokal gespeicherte Bilder:");
|
|
|
|
|
foreach (var kvp in Cache.Take(20))
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
Console.WriteLine($" {kvp.Value.SourceUrl} -> images/{kvp.Value.RelativePath}");
|
2026-09-20 08:31:23 +02:00
|
|
|
if (Cache.Count > 20)
|
|
|
|
|
Console.WriteLine($" ... und {Cache.Count - 20} weitere");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool IsMainImage(string url)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(url)) return false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri(url);
|
|
|
|
|
string fileName = Path.GetFileName(uri.LocalPath);
|
|
|
|
|
// WordPress-Sizes: -300x200, -scaled, -1024x768 etc.
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
if (SizeSuffixRegex.IsMatch(fileName))
|
2026-09-20 08:31:23 +02:00
|
|
|
return false;
|
|
|
|
|
if (fileName.Contains("-scaled"))
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch { return false; }
|
|
|
|
|
}
|
|
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
/// <summary>
|
|
|
|
|
/// Lädt EIN Bild für eine Gruppe von URL-Varianten desselben WordPress-Bildes
|
|
|
|
|
/// (Original, -scaled, -1024x683, ?w=...). Es wird die beste verfügbare Variante geladen.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static async Task<(string RelativePath, string LocalPath)?> DownloadBestAsync(IEnumerable<string> variants, DateTime? postDate)
|
2026-09-20 08:31:23 +02:00
|
|
|
{
|
2026-10-14 19:12:29 +02:00
|
|
|
var urls = CleanUrls(variants);
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
if (urls.Count == 0) return null;
|
|
|
|
|
|
|
|
|
|
string key = GetImageKey(urls[0]);
|
|
|
|
|
if (TryGetCached(key, out var cachedFile))
|
|
|
|
|
return cachedFile;
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
string lastError = "";
|
2026-10-14 19:12:29 +02:00
|
|
|
foreach (string candidate in GetDownloadCandidates(urls))
|
2026-09-20 19:35:16 +02:00
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
try
|
2026-09-20 19:35:16 +02:00
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
byte[] imageBytes = await httpClient.GetByteArrayAsync(candidate);
|
2026-09-20 19:35:16 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
var now = DateTime.Now;
|
|
|
|
|
string datePath = $"{now:yyyy}/{now:MM}";
|
|
|
|
|
string localDir = Path.Combine(LocalImageDir, datePath);
|
|
|
|
|
if (!Directory.Exists(localDir))
|
|
|
|
|
Directory.CreateDirectory(localDir);
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
// Eindeutigen Dateinamen bestimmen (nie eine vorhandene Datei wiederverwenden)
|
|
|
|
|
var pDate = postDate ?? now;
|
|
|
|
|
string ext = Path.GetExtension(new Uri(candidate).AbsolutePath);
|
|
|
|
|
int counter = 1 + new DirectoryInfo(localDir).GetFiles().Length;
|
|
|
|
|
string relativePath, localPath;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
relativePath = $"{datePath}/{pDate:yyyyMMdd}_{counter++}{ext}";
|
|
|
|
|
localPath = Path.Combine(LocalImageDir, relativePath);
|
|
|
|
|
} while (File.Exists(localPath));
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
await File.WriteAllBytesAsync(localPath, imageBytes);
|
|
|
|
|
Console.WriteLine($" [Bild] Heruntergeladen: {Path.GetFileName(new Uri(candidate).AbsolutePath)} → {relativePath}");
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
ResizeImage(localPath);
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
var fileResult = (relativePath, localPath);
|
|
|
|
|
Cache[key] = (candidate, relativePath, localPath);
|
|
|
|
|
RegisterForZip(fileResult);
|
|
|
|
|
return fileResult;
|
2026-09-20 08:31:23 +02:00
|
|
|
}
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
catch (Exception ex)
|
2026-09-20 08:31:23 +02:00
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
lastError = ex.Message;
|
2026-09-20 08:31:23 +02:00
|
|
|
}
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
}
|
2026-09-20 08:31:23 +02:00
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
Console.WriteLine($" [Bild-Fehler] Konnte {urls[0]} nicht laden: {lastError}");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2026-09-20 08:31:23 +02:00
|
|
|
|
2026-10-14 19:12:29 +02:00
|
|
|
// Query/Fragment entfernen: ?w=1024 & Co. liefern höchstens eine verkleinerte Fassung
|
|
|
|
|
private static List<string> CleanUrls(IEnumerable<string> variants) => variants
|
|
|
|
|
.Where(u => !string.IsNullOrEmpty(u))
|
|
|
|
|
.Select(u => u.Split('?', '#')[0])
|
|
|
|
|
.Where(u => Uri.IsWellFormedUriString(u, UriKind.Absolute))
|
|
|
|
|
.Distinct()
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
// Reihenfolge: Original -> -scaled -> erratenes Original -> Größenvarianten (größte zuerst)
|
|
|
|
|
private static IEnumerable<string> GetDownloadCandidates(List<string> urls)
|
|
|
|
|
{
|
|
|
|
|
var candidates = new List<string>();
|
|
|
|
|
candidates.AddRange(urls.Where(IsMainImage));
|
|
|
|
|
candidates.AddRange(urls.Where(u => ScaledSuffixRegex.IsMatch(u) && !SizeSuffixRegex.IsMatch(u)));
|
|
|
|
|
candidates.Add(ScaledSuffixRegex.Replace(SizeSuffixRegex.Replace(urls[0], ""), ""));
|
|
|
|
|
candidates.AddRange(urls.Where(u => SizeSuffixRegex.IsMatch(u)).OrderByDescending(GetVariantArea));
|
|
|
|
|
return candidates.Distinct();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Lädt ein am Beitrag angehängtes, aber im Beitrag nicht verwendetes Bild in den
|
|
|
|
|
/// Extra-Ordner (images_unbenutzt/<WP-ID>/). Diese Bilder werden weder nach Ghost
|
|
|
|
|
/// hochgeladen noch in die ZIP gepackt.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static async Task<bool> DownloadUnusedAsync(IEnumerable<string> variants, int wpId)
|
|
|
|
|
{
|
|
|
|
|
var urls = CleanUrls(variants);
|
|
|
|
|
if (urls.Count == 0) return false;
|
|
|
|
|
|
|
|
|
|
string dir = Path.Combine(UnusedImageDir, wpId.ToString());
|
|
|
|
|
string lastError = "";
|
|
|
|
|
foreach (string candidate in GetDownloadCandidates(urls))
|
|
|
|
|
{
|
|
|
|
|
string localPath = Path.Combine(dir, Path.GetFileName(new Uri(candidate).LocalPath));
|
|
|
|
|
if (File.Exists(localPath)) return true;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
byte[] imageBytes = await httpClient.GetByteArrayAsync(candidate);
|
|
|
|
|
Directory.CreateDirectory(dir);
|
|
|
|
|
await File.WriteAllBytesAsync(localPath, imageBytes);
|
|
|
|
|
Console.WriteLine($" [Bild] Nicht im Beitrag verwendet → {UnusedImageDirName}/{wpId}/{Path.GetFileName(localPath)}");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
lastError = ex.Message;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Console.WriteLine($" [Bild-Fehler] Konnte {urls[0]} nicht laden: {lastError}");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
private static long GetVariantArea(string url)
|
|
|
|
|
{
|
|
|
|
|
var m = Regex.Match(url, @"-(\d+)x(\d+)(?=\.\w+$)");
|
|
|
|
|
return m.Success ? long.Parse(m.Groups[1].Value) * long.Parse(m.Groups[2].Value) : 0;
|
2026-09-20 08:31:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ResizeImage(string localPath)
|
|
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
const int maxSize = 2048;
|
2026-09-20 08:31:23 +02:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using var image = Image.Load(localPath);
|
|
|
|
|
int width = image.Width;
|
|
|
|
|
int height = image.Height;
|
|
|
|
|
|
|
|
|
|
int longEdge = Math.Max(width, height);
|
|
|
|
|
if (longEdge <= maxSize) return;
|
|
|
|
|
|
|
|
|
|
int newWidth, newHeight;
|
|
|
|
|
if (width >= height)
|
|
|
|
|
{
|
|
|
|
|
newWidth = maxSize;
|
|
|
|
|
newHeight = (int)Math.Round(height * ((double)maxSize / width));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
newHeight = maxSize;
|
|
|
|
|
newWidth = (int)Math.Round(width * ((double)maxSize / height));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image.Mutate(x => x.Resize(newWidth, newHeight));
|
|
|
|
|
image.Save(localPath);
|
|
|
|
|
Console.WriteLine($" [Bild] Angepasst: {width}x{height} → {newWidth}x{newHeight}");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($" [Bild-Warnung] Resize fehlgeschlagen für {Path.GetFileName(localPath)}: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void LoadCache()
|
|
|
|
|
{
|
|
|
|
|
if (!File.Exists(CachePath)) return;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var lines = File.ReadAllLines(CachePath);
|
|
|
|
|
foreach (var line in lines)
|
|
|
|
|
{
|
|
|
|
|
var parts = line.Split('|');
|
2026-09-22 08:08:51 +02:00
|
|
|
if (parts.Length >= 3)
|
|
|
|
|
{
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
// Schlüssel immer aus der URL ableiten (ältere Cache-Dateien enthalten nur den Dateinamen)
|
|
|
|
|
Cache[GetImageKey(parts[0])] = (parts[0], parts[1], parts[2]);
|
2026-09-22 08:08:51 +02:00
|
|
|
}
|
2026-09-20 08:31:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"Fehler beim Laden des Bild-Caches: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Importer: Kategorien als Tags, Keywords als Meta, Bilder vollständig nach Ghost
Importer
- Kategorien werden als Ghost-Tags angelegt; bei mehreren wird die primäre
abgefragt, die übrigen folgen als sekundäre Tags
- Schlagwörter werden ohne Nachfrage als <meta name="keywords"> in den
Code-Injection-Header geschrieben (Ghost kennt kein meta_keywords-Feld)
- Tag-Suche lädt alle Seiten, HTML-kodierte Namen werden dekodiert
Bilder
- Varianten eines WordPress-Bildes (Original, -scaled, -WxH, ?w=) werden
zusammengefasst, einmal geladen und im HTML alle umgeschrieben
- src bei Einzelbildern setzen, srcset/sizes entfernen
- Cache-Schlüssel ist der Pfad statt nur der Dateiname; Dateinamen eindeutig
- ZIP-Export enthält Cache-Bilder und feature_image
- Warnung bei Bild-URLs, die weiter auf WordPress zeigen
- Maximale Bildgröße 2048 px
Plugin / GhostImageManager
- Plugin liefert primäre Kategorie
- Kategorie- und Keyword-Felder samt Filter im Image Manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:26:18 +02:00
|
|
|
}
|