Project Files
dist / embedLocalImages.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.embedLocalImagesInMarkdown = embedLocalImagesInMarkdown;
const promises_1 = require("fs/promises");
const path_1 = __importDefault(require("path"));
function guessImageMimeTypeByExt(filePath) {
const ext = path_1.default.extname(filePath).toLowerCase();
switch (ext) {
case ".png":
return "image/png";
case ".jpg":
case ".jpeg":
return "image/jpeg";
case ".webp":
return "image/webp";
case ".gif":
return "image/gif";
case ".svg":
return "image/svg+xml";
case ".bmp":
return "image/bmp";
case ".tif":
case ".tiff":
return "image/tiff";
default:
return null;
}
}
function isEmbeddableUrl(url) {
const u = url.trim();
if (!u)
return false;
if (/^(data:|https?:|file:)/i.test(u))
return false;
if (/^embedded:/i.test(u))
return false;
return true;
}
function isPathWithinDir(candidatePath, baseDir) {
const base = path_1.default.resolve(baseDir);
const cand = path_1.default.resolve(candidatePath);
if (cand === base)
return true;
const baseWithSep = base.endsWith(path_1.default.sep) ? base : base + path_1.default.sep;
return cand.startsWith(baseWithSep);
}
async function fileToDataUrl(filePath) {
const mime = guessImageMimeTypeByExt(filePath);
if (!mime)
return null;
try {
const s = await (0, promises_1.stat)(filePath);
if (!s.isFile())
return null;
}
catch {
return null;
}
try {
const buf = await (0, promises_1.readFile)(filePath);
const b64 = buf.toString("base64");
return `data:${mime};base64,${b64}`;
}
catch {
return null;
}
}
async function embedLocalImagesInMarkdown(markdown, workingDirectory) {
const md = String(markdown ?? "");
const wd = String(workingDirectory ?? "").trim();
if (!md || !wd)
return md;
const re = /!\[([^\]]*)\]\(\s*(?:<([^>]+)>|([^\)\s]+))(?:\s+"([^"]*)")?\s*\)/g;
const cacheByResolvedPath = new Map();
let out = "";
let lastIndex = 0;
for (;;) {
const m = re.exec(md);
if (!m)
break;
const matchStart = m.index;
const matchText = m[0];
const alt = m[1] ?? "";
const url = (m[2] ?? m[3] ?? "").trim();
const title = typeof m[4] === "string" && m[4].length > 0 ? m[4] : null;
out += md.slice(lastIndex, matchStart);
lastIndex = matchStart + matchText.length;
if (!isEmbeddableUrl(url)) {
out += matchText;
continue;
}
const absolutePath = path_1.default.isAbsolute(url) ? url : path_1.default.resolve(wd, url);
if (!isPathWithinDir(absolutePath, wd)) {
out += matchText;
continue;
}
let dataUrl = cacheByResolvedPath.get(absolutePath);
if (!dataUrl) {
const computed = await fileToDataUrl(absolutePath);
if (!computed) {
out += matchText;
continue;
}
dataUrl = computed;
cacheByResolvedPath.set(absolutePath, dataUrl);
}
const titlePart = title != null ? ` "${title.replace(/"/g, "\\\"")}"` : "";
out += ``;
}
out += md.slice(lastIndex);
return out;
}