|
@@ -1,147 +1,151 @@
|
|
import fs from "node:fs";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import path from "node:path";
|
|
-import { dirExists, isFileSync, isDir, waittime } from "#utils";
|
|
|
|
|
|
+import {dirExists, isFileSync, isDir, waittime} from "#utils";
|
|
import {
|
|
import {
|
|
- getFileBymd5,
|
|
|
|
- searchFileByPath,
|
|
|
|
- files_insert_link_epub,
|
|
|
|
- files_insert,
|
|
|
|
- book_mate_insert,
|
|
|
|
|
|
+ getFileBymd5,
|
|
|
|
+ searchFileByPath,
|
|
|
|
+ searchFileByName,
|
|
|
|
+ files_insert_link_epub,
|
|
|
|
+ files_insert,
|
|
|
|
+ book_mate_insert,
|
|
} from "#db";
|
|
} from "#db";
|
|
-import { calculateMD5 } from "./image.js";
|
|
|
|
|
|
+import {calculateMD5} from "./image.js";
|
|
|
|
|
|
const imageExtensions = [".png", ".jpg", ".jpeg", ".svg"];
|
|
const imageExtensions = [".png", ".jpg", ".jpeg", ".svg"];
|
|
|
|
|
|
async function processFiles(elmData, file_md5) {
|
|
async function processFiles(elmData, file_md5) {
|
|
- const rows = elmData.toString().split(/\n/);
|
|
|
|
- const promises = rows.map(async (rowtext) => {
|
|
|
|
- if (
|
|
|
|
- rowtext.includes("Images") &&
|
|
|
|
- imageExtensions.some((ext) => rowtext.includes(ext))
|
|
|
|
- ) {
|
|
|
|
- const match = rowtext.match(/.*(..\/Images\/(.*\.(jpg|png|jpeg|svg))).*/);
|
|
|
|
- if (match) {
|
|
|
|
- const [, imgPath, imageSrc] = match;
|
|
|
|
- const imgRow = await searchFileByPath(imageSrc);
|
|
|
|
- if (imgRow) {
|
|
|
|
- return (
|
|
|
|
- rowtext.replace(imgPath, `/api/v1/epub/img/${imgRow.file_id}`) +
|
|
|
|
- "\n"
|
|
|
|
- );
|
|
|
|
|
|
+ const rows = elmData.toString().split(/\n/);
|
|
|
|
+ const promises = rows.map(async (rowtext) => {
|
|
|
|
+ if (
|
|
|
|
+ rowtext.includes("<img ") &&
|
|
|
|
+ imageExtensions.some((ext) => rowtext.includes(ext))
|
|
|
|
+ ) {
|
|
|
|
+ // const match = rowtext.match(/.*(..\/Images\/(.*\.(jpg|png|jpeg|svg))).*/);
|
|
|
|
+ const match = rowtext.match(/src=("|')(.*\/(.*\.[a-zA-Z]+))("|')/)
|
|
|
|
+ if (match) {
|
|
|
|
+ const [, , imgPath, imageSrc] = match;
|
|
|
|
+ const imgRow = await searchFileByPath(imageSrc);
|
|
|
|
+ if (imgRow) {
|
|
|
|
+ return (
|
|
|
|
+ rowtext.replace(imgPath, `/api/v1/epub/img/${imgRow.file_id}`) +
|
|
|
|
+ "\n"
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (rowtext.includes(".css")) {
|
|
|
|
+ const match = rowtext.match(/.*="(.*\/?(.*\.css))/);
|
|
|
|
+ const [elmPath, elmName] = `${rowtext}`.match(/.*\/(.*\.css)/);
|
|
|
|
+ if (match) {
|
|
|
|
+ const [, cssPath, cssSrc] = match;
|
|
|
|
+ // const imgRow = await searchFileByPath(elmName, file_md5);
|
|
|
|
+ const imgNameRow = await searchFileByName(elmName, file_md5);
|
|
|
|
+ if (imgNameRow) {
|
|
|
|
+ return (
|
|
|
|
+ rowtext.replace(cssPath, `/api/v1/epub/css/${imgNameRow.file_id}`) +
|
|
|
|
+ "\n"
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (rowtext.includes(".ttf")) {
|
|
|
|
+ // 使用正则表达式匹配路径和文件名
|
|
|
|
+ const match = rowtext.match(/.*\((.*\/?(.*ttf))\)./);
|
|
|
|
+ if (match) {
|
|
|
|
+ const [, cssPath, cssSrc] = match;
|
|
|
|
+ try {
|
|
|
|
+ // 搜索数据库中是否存在该字体文件
|
|
|
|
+ const imgRow = await searchFileByPath(cssSrc, file_md5);
|
|
|
|
+ if (imgRow) {
|
|
|
|
+ // 如果找到,替换路径为 API 端点
|
|
|
|
+ console.log(57, rowtext);
|
|
|
|
+ console.log(58, cssPath, cssSrc);
|
|
|
|
+ console.log(59, `/api/v1/epub/css/${imgRow.file_id}`);
|
|
|
|
+
|
|
|
|
+ return (
|
|
|
|
+ rowtext.replace(cssPath, `/api/v1/epub/css/${imgRow.file_id}`) +
|
|
|
|
+ "\n"
|
|
|
|
+ );
|
|
|
|
+ } else {
|
|
|
|
+ console.warn(`Font file not found for path: ${cssSrc}`);
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error("Error searching for font file:", error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- } else if (rowtext.includes(".css")) {
|
|
|
|
- const match = rowtext.match(/.*="(.*\/?(.*\.css))/);
|
|
|
|
- if (match) {
|
|
|
|
- const [, cssPath, cssSrc] = match;
|
|
|
|
- const imgRow = await searchFileByPath(cssSrc, file_md5);
|
|
|
|
- if (imgRow) {
|
|
|
|
- return (
|
|
|
|
- rowtext.replace(cssPath, `/api/v1/epub/css/${imgRow.file_id}`) +
|
|
|
|
- "\n"
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else if (rowtext.includes(".ttf")) {
|
|
|
|
- // 使用正则表达式匹配路径和文件名
|
|
|
|
- const match = rowtext.match(/.*\((.*\/?(.*ttf))\)./);
|
|
|
|
- if (match) {
|
|
|
|
- const [, cssPath, cssSrc] = match;
|
|
|
|
- try {
|
|
|
|
- // 搜索数据库中是否存在该字体文件
|
|
|
|
- const imgRow = await searchFileByPath(cssSrc, file_md5);
|
|
|
|
- if (imgRow) {
|
|
|
|
- // 如果找到,替换路径为 API 端点
|
|
|
|
- console.log(57, rowtext);
|
|
|
|
- console.log(58, cssPath, cssSrc);
|
|
|
|
- console.log(59, `/api/v1/epub/css/${imgRow.file_id}`);
|
|
|
|
-
|
|
|
|
- return (
|
|
|
|
- rowtext.replace(cssPath, `/api/v1/epub/css/${imgRow.file_id}`) +
|
|
|
|
- "\n"
|
|
|
|
- );
|
|
|
|
- } else {
|
|
|
|
- console.warn(`Font file not found for path: ${cssSrc}`);
|
|
|
|
- }
|
|
|
|
- } catch (error) {
|
|
|
|
- console.error("Error searching for font file:", error);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return rowtext + "\n";
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- const results = await Promise.all(promises);
|
|
|
|
- return results.join("");
|
|
|
|
|
|
+
|
|
|
|
+ return rowtext + "\n";
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const results = await Promise.all(promises);
|
|
|
|
+ return results.join("");
|
|
}
|
|
}
|
|
|
|
|
|
export async function htmlParser(epub, zipEpubExtract, file_md5, author_id) {
|
|
export async function htmlParser(epub, zipEpubExtract, file_md5, author_id) {
|
|
- const needSetImage = epub.zip.names.filter(
|
|
|
|
- (elm) => elm.endsWith(".html") || elm.endsWith(".css")
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- const needSetFont = epub.zip.names.filter((elm) => elm.endsWith(".ttf"));
|
|
|
|
- const basePath = path.join("./base_files", file_md5, "Text");
|
|
|
|
- const styleBasePath = path.join("./base_files", file_md5, "style");
|
|
|
|
- dirExists(basePath);
|
|
|
|
- dirExists(styleBasePath);
|
|
|
|
-
|
|
|
|
- await Promise.all(
|
|
|
|
- needSetImage.map(async (elm) => {
|
|
|
|
- const filePath = path.join(zipEpubExtract, elm);
|
|
|
|
- const elmData = fs.readFileSync(filePath);
|
|
|
|
- const htmlStr = await processFiles(elmData, file_md5);
|
|
|
|
-
|
|
|
|
- if (htmlStr) {
|
|
|
|
- fs.writeFileSync(filePath, htmlStr);
|
|
|
|
-
|
|
|
|
- const htmlMd5 = await calculateMD5(filePath);
|
|
|
|
- const isCss = elm.endsWith(".css");
|
|
|
|
- const newFilePath = path.join(
|
|
|
|
- isCss ? styleBasePath : basePath,
|
|
|
|
- `${htmlMd5}.${isCss ? "css" : "html"}`
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- const params = {
|
|
|
|
- file_id: htmlMd5,
|
|
|
|
- md5: htmlMd5,
|
|
|
|
- mimetype: isCss ? "text/css" : "text/html",
|
|
|
|
- size: Buffer.byteLength(htmlStr),
|
|
|
|
- name: `${htmlMd5}.${isCss ? "css" : "html"}`,
|
|
|
|
- path: newFilePath,
|
|
|
|
- source_id: elm,
|
|
|
|
- };
|
|
|
|
- await files_insert(params);
|
|
|
|
- await Promise.all([
|
|
|
|
- files_insert_link_epub({
|
|
|
|
- file_id: htmlMd5,
|
|
|
|
- book_id: file_md5,
|
|
|
|
- author_id,
|
|
|
|
- }),
|
|
|
|
- fs.promises.writeFile(newFilePath, htmlStr),
|
|
|
|
- ]);
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- );
|
|
|
|
|
|
+ const needSetImage = epub.zip.names.filter(
|
|
|
|
+ (elm) => elm.endsWith(".html") || elm.endsWith(".css")
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ const needSetFont = epub.zip.names.filter((elm) => elm.endsWith(".ttf"));
|
|
|
|
+ const basePath = path.join("./base_files", file_md5, "Text");
|
|
|
|
+ const styleBasePath = path.join("./base_files", file_md5, "style");
|
|
|
|
+ dirExists(basePath);
|
|
|
|
+ dirExists(styleBasePath);
|
|
|
|
+
|
|
|
|
+ await Promise.all(
|
|
|
|
+ needSetImage.map(async (elm) => {
|
|
|
|
+ const filePath = path.join(zipEpubExtract, elm);
|
|
|
|
+ const elmData = fs.readFileSync(filePath);
|
|
|
|
+ const htmlStr = await processFiles(elmData, file_md5);
|
|
|
|
+
|
|
|
|
+ if (htmlStr) {
|
|
|
|
+ fs.writeFileSync(filePath, htmlStr);
|
|
|
|
+
|
|
|
|
+ const htmlMd5 = await calculateMD5(filePath);
|
|
|
|
+ const isCss = elm.endsWith(".css");
|
|
|
|
+ const newFilePath = path.join(
|
|
|
|
+ isCss ? styleBasePath : basePath,
|
|
|
|
+ `${htmlMd5}.${isCss ? "css" : "html"}`
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ const params = {
|
|
|
|
+ file_id: htmlMd5,
|
|
|
|
+ md5: htmlMd5,
|
|
|
|
+ mimetype: isCss ? "text/css" : "text/html",
|
|
|
|
+ size: Buffer.byteLength(htmlStr),
|
|
|
|
+ name: `${htmlMd5}.${isCss ? "css" : "html"}`,
|
|
|
|
+ path: newFilePath,
|
|
|
|
+ source_id: elm,
|
|
|
|
+ };
|
|
|
|
+ await files_insert(params);
|
|
|
|
+ await Promise.all([
|
|
|
|
+ files_insert_link_epub({
|
|
|
|
+ file_id: htmlMd5,
|
|
|
|
+ book_id: file_md5,
|
|
|
|
+ author_id,
|
|
|
|
+ }),
|
|
|
|
+ fs.promises.writeFile(newFilePath, htmlStr),
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
// saveMateInfo
|
|
// saveMateInfo
|
|
export async function saveMateInfo(epub, zipEpubExtract, file_md5, author_id) {
|
|
export async function saveMateInfo(epub, zipEpubExtract, file_md5, author_id) {
|
|
- // book_mate_insert
|
|
|
|
- const params = {
|
|
|
|
- book_name: epub.metadata.title,
|
|
|
|
- book_id: file_md5,
|
|
|
|
- book_md5: file_md5,
|
|
|
|
- // language: "",
|
|
|
|
- // date: "",
|
|
|
|
- // creatorFileAs: "",
|
|
|
|
- // UUID: "",
|
|
|
|
- // ISBN: "",
|
|
|
|
- author_id: author_id,
|
|
|
|
- // category_id: "",
|
|
|
|
- // Introduction: "",
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- const res = await book_mate_insert(params);
|
|
|
|
|
|
+ // book_mate_insert
|
|
|
|
+ const params = {
|
|
|
|
+ book_name: epub.metadata.title,
|
|
|
|
+ book_id: file_md5,
|
|
|
|
+ book_md5: file_md5,
|
|
|
|
+ // language: "",
|
|
|
|
+ // date: "",
|
|
|
|
+ // creatorFileAs: "",
|
|
|
|
+ // UUID: "",
|
|
|
|
+ // ISBN: "",
|
|
|
|
+ author_id: author_id,
|
|
|
|
+ // category_id: "",
|
|
|
|
+ // Introduction: "",
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const res = await book_mate_insert(params);
|
|
}
|
|
}
|