From 16da0dffaf63932e578ff707d32b3899519a1193 Mon Sep 17 00:00:00 2001
From: Aryan Mane <146648718+ARYAN-9099@users.noreply.github.com>
Date: Thu, 30 Jul 2026 23:43:59 +0530
Subject: [PATCH 1/3] Edit image URL for existing books in library #2792
---
plugin/js/Library.js | 26 ++++++++++++++++++++++++++
plugin/popup.html | 3 +++
2 files changed, 29 insertions(+)
diff --git a/plugin/js/Library.js b/plugin/js/Library.js
index 7e477883..4bbbce00 100644
--- a/plugin/js/Library.js
+++ b/plugin/js/Library.js
@@ -565,6 +565,7 @@ class Library { // eslint-disable-line no-unused-vars
let LibTemplateMetadataSubject = document.getElementById("LibTemplateMetadataSubject").innerHTML;
let LibTemplateMetadataDescription = document.getElementById("LibTemplateMetadataDescription").innerHTML;
let LibTemplateMetadataPublisher = document.getElementById("LibTemplateMetadataPublisher").innerHTML;
+ let LibTemplateMetadataCoverImageUrl = document.getElementById("LibTemplateMetadataCoverImageUrl").innerHTML;
let LibRenderResult = document.getElementById("LibRenderMetadata" + objbtn.dataset.libepubid);
let LibMetadata = await Library.LibGetMetadata(objbtn.dataset.libepubid);
let LibRenderString = "";
@@ -604,6 +605,10 @@ class Library { // eslint-disable-line no-unused-vars
LibRenderString += "
"+LibTemplateMetadataPublisher+" | ";
LibRenderString += " | ";
LibRenderString += "";
+ LibRenderString += "";
+ LibRenderString += "| "+LibTemplateMetadataCoverImageUrl+" | ";
+ LibRenderString += " | ";
+ LibRenderString += "
";
LibRenderString += "";
LibRenderString += "";
LibRenderString += "";
@@ -631,7 +636,28 @@ class Library { // eslint-disable-line no-unused-vars
let LibSubjectInput = document.getElementById("LibSubjectInput"+obj.dataset.libepubid).value;
let LibDescriptionInput = document.getElementById("LibDescriptionInput"+obj.dataset.libepubid).value;
let LibPublisherInput = document.getElementById("LibPublisherInput"+obj.dataset.libepubid).value;
+ let LibCoverImageUrlInput = document.getElementById("LibCoverImageUrlInput"+obj.dataset.libepubid).value;
Library.LibShowLoadingText();
+
+ // Update cover image in storage if a new URL was provided
+ if (LibCoverImageUrlInput.trim() !== "") {
+ try {
+ let response = await fetch(LibCoverImageUrlInput);
+ let blob = await response.blob();
+ let reader = new FileReader();
+ let coverDataUrl = await new Promise((resolve, reject) => {
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = reject;
+ reader.readAsDataURL(blob);
+ });
+ chrome.storage.local.set({
+ ["LibCover" + obj.dataset.libepubid]: coverDataUrl
+ });
+ } catch {
+ // If fetching the image fails, continue with the metadata save
+ }
+ }
+
let LibDateCreated = new EpubPacker().getDateForMetaData();
try {
let EpubReader = await new zip.Data64URIReader(await Library.LibGetFromStorage("LibEpub"+obj.dataset.libepubid));
diff --git a/plugin/popup.html b/plugin/popup.html
index 5a73dfb9..846625c8 100644
--- a/plugin/popup.html
+++ b/plugin/popup.html
@@ -244,6 +244,9 @@ Instructions
| __MSG_label_Metadata_publisher__ |
+
+ | __MSG_label_Cover_Image_URL__ |
+
From 5d9f181204a2e2367e4291c3067c8b191629a035 Mon Sep 17 00:00:00 2001
From: Aryan Mane <146648718+ARYAN-9099@users.noreply.github.com>
Date: Fri, 31 Jul 2026 01:55:35 +0530
Subject: [PATCH 2/3] fix: change image in the ebook
---
plugin/js/Library.js | 73 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git a/plugin/js/Library.js b/plugin/js/Library.js
index 4bbbce00..cfed9622 100644
--- a/plugin/js/Library.js
+++ b/plugin/js/Library.js
@@ -639,22 +639,27 @@ class Library { // eslint-disable-line no-unused-vars
let LibCoverImageUrlInput = document.getElementById("LibCoverImageUrlInput"+obj.dataset.libepubid).value;
Library.LibShowLoadingText();
+ let newCoverBlob = null;
+ let newCoverMimeType = null;
+
// Update cover image in storage if a new URL was provided
if (LibCoverImageUrlInput.trim() !== "") {
try {
let response = await fetch(LibCoverImageUrlInput);
- let blob = await response.blob();
+ newCoverBlob = await response.blob();
+ newCoverMimeType = newCoverBlob.type;
let reader = new FileReader();
let coverDataUrl = await new Promise((resolve, reject) => {
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
- reader.readAsDataURL(blob);
+ reader.readAsDataURL(newCoverBlob);
});
chrome.storage.local.set({
["LibCover" + obj.dataset.libepubid]: coverDataUrl
});
} catch {
// If fetching the image fails, continue with the metadata save
+ newCoverBlob = null;
}
}
@@ -665,12 +670,74 @@ class Library { // eslint-disable-line no-unused-vars
let EpubContent = await EpubZipRead.getEntries();
EpubContent = EpubContent.filter(a => a.directory == false);
let opfFile = await EpubContent.filter(a => a.filename == "OEBPS/content.opf")[0].getData(new zip.TextWriter());
+
+ // Handle new cover embedding in EPUB
+ let oldCoverimgPath = null;
+ let newCoverimgPath = null;
+ let coverXhtmlFile = EpubContent.filter(a => a.filename == "OEBPS/Text/Cover.xhtml");
+ if (newCoverBlob != null && coverXhtmlFile.length > 0) {
+ try {
+ let Coverxml = await coverXhtmlFile[0].getData(new zip.TextWriter());
+ let match = Coverxml.match(/"..\/Images\/000.+?"/);
+ if (match) {
+ oldCoverimgPath = "OEBPS" + match[0].replace(/"../, "").replace("\"", "");
+
+ let extension = "jpg";
+ if (newCoverMimeType && newCoverMimeType.includes("png")) {
+ extension = "png";
+ } else if (newCoverMimeType && newCoverMimeType.includes("gif")) {
+ extension = "gif";
+ } else if (newCoverMimeType && newCoverMimeType.includes("webp")) {
+ extension = "webp";
+ }
+
+ let baseName = oldCoverimgPath.substring(0, oldCoverimgPath.lastIndexOf("."));
+ newCoverimgPath = baseName + "." + extension;
+
+ let oldHref = oldCoverimgPath.replace("OEBPS/", "");
+ let newHref = newCoverimgPath.replace("OEBPS/", "");
+
+ // Update OPF
+ let itemRegexStr = "- ]+href=\"" + oldHref.replace(/\./g, "\\.") + "\"[^>]*>";
+ let itemRegex = new RegExp(itemRegexStr, "g");
+ let itemMatch = opfFile.match(itemRegex);
+ if (itemMatch) {
+ let oldItem = itemMatch[0];
+ let newItem = oldItem.replace(oldHref, newHref);
+ if (newCoverMimeType) {
+ newItem = newItem.replace(/media-type="[^"]+"/, "media-type=\"" + newCoverMimeType + "\"");
+ }
+ opfFile = opfFile.replace(oldItem, newItem);
+ }
+
+ // Update Cover.xhtml
+ let oldSrc = oldHref.replace("Images/", "../Images/");
+ let newSrc = newHref.replace("Images/", "../Images/");
+ coverXhtmlFile[0].newXmlData = Coverxml.replace(oldSrc, newSrc);
+ }
+ } catch (e) {
+ // Ignore if cover modification fails
+ oldCoverimgPath = null;
+ newCoverimgPath = null;
+ }
+ }
let EpubWriter = new zip.BlobWriter("application/epub+zip");
let EpubZipWrite = new zip.ZipWriter(EpubWriter,{useWebWorkers: false,compressionMethod: 8});
//Copy Epub in NewEpub
for (let element of EpubContent.filter(a => a.filename != "OEBPS/content.opf")) {
- EpubZipWrite.add(element.filename, new zip.BlobReader(await element.getData(new zip.BlobWriter())));
+ if (oldCoverimgPath != null && element.filename === oldCoverimgPath) {
+ continue; // Skip old image
+ }
+ if (newCoverBlob != null && element.filename === "OEBPS/Text/Cover.xhtml" && coverXhtmlFile[0].newXmlData) {
+ EpubZipWrite.add(element.filename, new zip.TextReader(coverXhtmlFile[0].newXmlData));
+ } else {
+ EpubZipWrite.add(element.filename, new zip.BlobReader(await element.getData(new zip.BlobWriter())));
+ }
+ }
+
+ if (newCoverBlob != null && newCoverimgPath != null) {
+ EpubZipWrite.add(newCoverimgPath, new zip.BlobReader(newCoverBlob));
}
let regex1 = opfFile.match(new RegExp(".+?", "gs"));
From 6aa51376c82086a51e0911736b2d4698b4201fc4 Mon Sep 17 00:00:00 2001
From: Aryan Mane <146648718+ARYAN-9099@users.noreply.github.com>
Date: Sun, 2 Aug 2026 11:20:11 +0530
Subject: [PATCH 3/3] fix: update cover image handling in EPUB files
---
plugin/js/Library.js | 116 +++++++++++++++++++++++++++----------------
1 file changed, 72 insertions(+), 44 deletions(-)
diff --git a/plugin/js/Library.js b/plugin/js/Library.js
index cfed9622..1c02077c 100644
--- a/plugin/js/Library.js
+++ b/plugin/js/Library.js
@@ -675,50 +675,75 @@ class Library { // eslint-disable-line no-unused-vars
let oldCoverimgPath = null;
let newCoverimgPath = null;
let coverXhtmlFile = EpubContent.filter(a => a.filename == "OEBPS/Text/Cover.xhtml");
- if (newCoverBlob != null && coverXhtmlFile.length > 0) {
- try {
- let Coverxml = await coverXhtmlFile[0].getData(new zip.TextWriter());
- let match = Coverxml.match(/"..\/Images\/000.+?"/);
- if (match) {
- oldCoverimgPath = "OEBPS" + match[0].replace(/"../, "").replace("\"", "");
-
- let extension = "jpg";
- if (newCoverMimeType && newCoverMimeType.includes("png")) {
- extension = "png";
- } else if (newCoverMimeType && newCoverMimeType.includes("gif")) {
- extension = "gif";
- } else if (newCoverMimeType && newCoverMimeType.includes("webp")) {
- extension = "webp";
- }
-
- let baseName = oldCoverimgPath.substring(0, oldCoverimgPath.lastIndexOf("."));
- newCoverimgPath = baseName + "." + extension;
+
+ if (newCoverBlob != null) {
+ let extension = "jpg";
+ if (newCoverMimeType && newCoverMimeType.includes("png")) {
+ extension = "png";
+ } else if (newCoverMimeType && newCoverMimeType.includes("gif")) {
+ extension = "gif";
+ } else if (newCoverMimeType && newCoverMimeType.includes("webp")) {
+ extension = "webp";
+ }
- let oldHref = oldCoverimgPath.replace("OEBPS/", "");
- let newHref = newCoverimgPath.replace("OEBPS/", "");
-
- // Update OPF
- let itemRegexStr = "
- ]+href=\"" + oldHref.replace(/\./g, "\\.") + "\"[^>]*>";
- let itemRegex = new RegExp(itemRegexStr, "g");
- let itemMatch = opfFile.match(itemRegex);
- if (itemMatch) {
- let oldItem = itemMatch[0];
- let newItem = oldItem.replace(oldHref, newHref);
- if (newCoverMimeType) {
- newItem = newItem.replace(/media-type="[^"]+"/, "media-type=\"" + newCoverMimeType + "\"");
+ if (coverXhtmlFile.length > 0) {
+ try {
+ let Coverxml = await coverXhtmlFile[0].getData(new zip.TextWriter());
+ let match = Coverxml.match(/"..\/Images\/000.+?"/);
+ if (match) {
+ oldCoverimgPath = "OEBPS" + match[0].replace(/"../, "").replace("\"", "");
+ let baseName = oldCoverimgPath.substring(0, oldCoverimgPath.lastIndexOf("."));
+ newCoverimgPath = baseName + "." + extension;
+
+ let oldHref = oldCoverimgPath.replace("OEBPS/", "");
+ let newHref = newCoverimgPath.replace("OEBPS/", "");
+
+ // Update OPF
+ let itemRegexStr = "
- ]+href=\"" + oldHref.replace(/\./g, "\\.") + "\"[^>]*>";
+ let itemRegex = new RegExp(itemRegexStr, "g");
+ let itemMatch = opfFile.match(itemRegex);
+ if (itemMatch) {
+ let oldItem = itemMatch[0];
+ let newItem = oldItem.replace(oldHref, newHref);
+ if (newCoverMimeType) {
+ newItem = newItem.replace(/media-type="[^"]+"/, "media-type=\"" + newCoverMimeType + "\"");
+ }
+ opfFile = opfFile.replace(oldItem, newItem);
}
- opfFile = opfFile.replace(oldItem, newItem);
+
+ // Update Cover.xhtml
+ let oldSrc = oldHref.replace("Images/", "../Images/");
+ let newSrc = newHref.replace("Images/", "../Images/");
+ coverXhtmlFile[0].newXmlData = Coverxml.replace(oldSrc, newSrc);
}
-
- // Update Cover.xhtml
- let oldSrc = oldHref.replace("Images/", "../Images/");
- let newSrc = newHref.replace("Images/", "../Images/");
- coverXhtmlFile[0].newXmlData = Coverxml.replace(oldSrc, newSrc);
+ } catch (e) {
+ // Ignore if cover modification fails
+ oldCoverimgPath = null;
+ newCoverimgPath = null;
}
- } catch (e) {
- // Ignore if cover modification fails
- oldCoverimgPath = null;
- newCoverimgPath = null;
+ } else {
+ // EPUB had no cover previously, inject one
+ newCoverimgPath = "OEBPS/Images/0000_cover." + extension;
+
+ let newManifestItems = `\n
\n \n`;
+ opfFile = opfFile.replace("", "" + newManifestItems);
+
+ opfFile = opfFile.replace(/]*>/, "$&\n\n");
+
+ if (opfFile.includes("")) {
+ opfFile = opfFile.replace("", "\n\n");
+ } else {
+ opfFile = opfFile.replace("", "\n\n\n");
+ }
+
+ opfFile = opfFile.replace(/]*>/, "$&\n\n");
+
+ let newCoverxml = `\n\n\n\n Cover\n\n\n \n

\n
\n\n`;
+
+ coverXhtmlFile = [{
+ filename: "OEBPS/Text/Cover.xhtml",
+ newXmlData: newCoverxml
+ }];
}
}
@@ -729,16 +754,19 @@ class Library { // eslint-disable-line no-unused-vars
if (oldCoverimgPath != null && element.filename === oldCoverimgPath) {
continue; // Skip old image
}
- if (newCoverBlob != null && element.filename === "OEBPS/Text/Cover.xhtml" && coverXhtmlFile[0].newXmlData) {
- EpubZipWrite.add(element.filename, new zip.TextReader(coverXhtmlFile[0].newXmlData));
- } else {
- EpubZipWrite.add(element.filename, new zip.BlobReader(await element.getData(new zip.BlobWriter())));
+ if (newCoverBlob != null && element.filename === "OEBPS/Text/Cover.xhtml") {
+ // Original cover existed, skip adding it here (we add the modified one below)
+ continue;
}
+ EpubZipWrite.add(element.filename, new zip.BlobReader(await element.getData(new zip.BlobWriter())));
}
if (newCoverBlob != null && newCoverimgPath != null) {
EpubZipWrite.add(newCoverimgPath, new zip.BlobReader(newCoverBlob));
}
+ if (newCoverBlob != null && coverXhtmlFile.length > 0 && coverXhtmlFile[0].newXmlData) {
+ EpubZipWrite.add(coverXhtmlFile[0].filename, new zip.TextReader(coverXhtmlFile[0].newXmlData));
+ }
let regex1 = opfFile.match(new RegExp(".+?", "gs"));
if ( regex1 == null) {