285 lines
11 KiB
JavaScript
285 lines
11 KiB
JavaScript
"use strict";
|
||
var __create = Object.create;
|
||
var __defProp = Object.defineProperty;
|
||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||
var __getProtoOf = Object.getPrototypeOf;
|
||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||
var __export = (target, all) => {
|
||
for (var name in all)
|
||
__defProp(target, name, { get: all[name], enumerable: true });
|
||
};
|
||
var __copyProps = (to, from, except, desc) => {
|
||
if (from && typeof from === "object" || typeof from === "function") {
|
||
for (let key of __getOwnPropNames(from))
|
||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||
}
|
||
return to;
|
||
};
|
||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||
// If the importer is in node compatibility mode or this is not an ESM
|
||
// file that has been converted to a CommonJS file using a Babel-
|
||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||
mod
|
||
));
|
||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||
var text_format_exports = {};
|
||
__export(text_format_exports, {
|
||
decodeHTMLEntities: () => decodeHTMLEntities,
|
||
escapeHtml: () => escapeHtml,
|
||
formatHtmlHeader: () => formatHtmlHeader,
|
||
formatTextHeader: () => formatTextHeader,
|
||
htmlToText: () => htmlToText,
|
||
textToHtml: () => textToHtml
|
||
});
|
||
module.exports = __toCommonJS(text_format_exports);
|
||
var import_html_entities = __toESM(require("./html-entities.cjs"), 1);
|
||
function decodeHTMLEntities(str) {
|
||
return str.replace(/&(#\d+|#x[a-f0-9]+|[a-z]+\d*);?/gi, (match, entity) => {
|
||
if (typeof import_html_entities.default[match] === "string") {
|
||
return import_html_entities.default[match];
|
||
}
|
||
if (entity.charAt(0) !== "#" || match.charAt(match.length - 1) !== ";") {
|
||
return match;
|
||
}
|
||
let codePoint;
|
||
if (entity.charAt(1) === "x") {
|
||
codePoint = parseInt(entity.substr(2), 16);
|
||
} else {
|
||
codePoint = parseInt(entity.substr(1), 10);
|
||
}
|
||
let output = "";
|
||
if (codePoint >= 55296 && codePoint <= 57343 || codePoint > 1114111) {
|
||
return "\uFFFD";
|
||
}
|
||
if (codePoint > 65535) {
|
||
codePoint -= 65536;
|
||
output += String.fromCharCode(codePoint >>> 10 & 1023 | 55296);
|
||
codePoint = 56320 | codePoint & 1023;
|
||
}
|
||
output += String.fromCharCode(codePoint);
|
||
return output;
|
||
});
|
||
}
|
||
function escapeHtml(str) {
|
||
return str.trim().replace(/[<>"'?&]/g, (c) => {
|
||
let hex = c.charCodeAt(0).toString(16);
|
||
if (hex.length < 2) {
|
||
hex = "0" + hex;
|
||
}
|
||
return "&#x" + hex.toUpperCase() + ";";
|
||
});
|
||
}
|
||
function textToHtml(str) {
|
||
let html = escapeHtml(str).replace(/\n/g, "<br />");
|
||
return "<div>" + html + "</div>";
|
||
}
|
||
function htmlToText(str) {
|
||
str = str.replace(/\r?\n/g, "").replace(/<\!\-\-.*?\-\->/gi, " ").replace(/<br\b[^>]*>/gi, "\n").replace(/<\/?(p|div|table|tr|td|th)\b[^>]*>/gi, "\n\n").replace(/<script\b[^>]*>.*?<\/script\b[^>]*>/gi, " ").replace(/^.*<body\b[^>]*>/i, "").replace(/^.*<\/head\b[^>]*>/i, "").replace(/^.*<\!doctype\b[^>]*>/i, "").replace(/<\/body\b[^>]*>.*$/i, "").replace(/<\/html\b[^>]*>.*$/i, "").replace(/<a\b[^>]*href\s*=\s*["']?([^\s"']+)[^>]*>/gi, " ($1) ").replace(/<\/?(span|em|i|strong|b|u|a)\b[^>]*>/gi, "").replace(/<li\b[^>]*>[\n\u0001\s]*/gi, "* ").replace(/<hr\b[^>]*>/g, "\n-------------\n").replace(/<[^>]*>/g, " ").replace(/\u0001/g, "\n").replace(/[ \t]+/g, " ").replace(/^\s+$/gm, "").replace(/\n\n+/g, "\n\n").replace(/^\n+/, "\n").replace(/\n+$/, "\n");
|
||
str = decodeHTMLEntities(str);
|
||
return str;
|
||
}
|
||
function formatTextAddress(address) {
|
||
return [].concat(address.name || []).concat(address.name ? `<${address.address}>` : address.address).join(" ");
|
||
}
|
||
function formatTextAddresses(addresses) {
|
||
let parts = [];
|
||
let processAddress = (address, partCounter) => {
|
||
if (partCounter) {
|
||
parts.push(", ");
|
||
}
|
||
if (address.group) {
|
||
let groupStart = `${address.name}:`;
|
||
let groupEnd = `;`;
|
||
parts.push(groupStart);
|
||
address.group.forEach(processAddress);
|
||
parts.push(groupEnd);
|
||
} else {
|
||
parts.push(formatTextAddress(address));
|
||
}
|
||
};
|
||
addresses.forEach(processAddress);
|
||
return parts.join("");
|
||
}
|
||
function formatHtmlAddress(address) {
|
||
return `<a href="mailto:${escapeHtml(address.address)}" class="postal-email-address">${escapeHtml(address.name || `<${address.address}>`)}</a>`;
|
||
}
|
||
function formatHtmlAddresses(addresses) {
|
||
let parts = [];
|
||
let processAddress = (address, partCounter) => {
|
||
if (partCounter) {
|
||
parts.push('<span class="postal-email-address-separator">, </span>');
|
||
}
|
||
if (address.group) {
|
||
let groupStart = `<span class="postal-email-address-group">${escapeHtml(address.name)}:</span>`;
|
||
let groupEnd = `<span class="postal-email-address-group">;</span>`;
|
||
parts.push(groupStart);
|
||
address.group.forEach(processAddress);
|
||
parts.push(groupEnd);
|
||
} else {
|
||
parts.push(formatHtmlAddress(address));
|
||
}
|
||
};
|
||
addresses.forEach(processAddress);
|
||
return parts.join(" ");
|
||
}
|
||
function foldLines(str, lineLength, afterSpace) {
|
||
str = (str || "").toString();
|
||
lineLength = lineLength || 76;
|
||
let pos = 0, len = str.length, result = "", line, match;
|
||
while (pos < len) {
|
||
line = str.substr(pos, lineLength);
|
||
if (line.length < lineLength) {
|
||
result += line;
|
||
break;
|
||
}
|
||
if (match = line.match(/^[^\n\r]*(\r?\n|\r)/)) {
|
||
line = match[0];
|
||
result += line;
|
||
pos += line.length;
|
||
continue;
|
||
} else if ((match = line.match(/(\s+)[^\s]*$/)) && match[0].length - (afterSpace ? (match[1] || "").length : 0) < line.length) {
|
||
line = line.substr(0, line.length - (match[0].length - (afterSpace ? (match[1] || "").length : 0)));
|
||
} else if (match = str.substr(pos + line.length).match(/^[^\s]+(\s*)/)) {
|
||
line = line + match[0].substr(0, match[0].length - (!afterSpace ? (match[1] || "").length : 0));
|
||
}
|
||
result += line;
|
||
pos += line.length;
|
||
if (pos < len) {
|
||
result += "\r\n";
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
function formatTextHeader(message) {
|
||
let rows = [];
|
||
if (message.from) {
|
||
rows.push({ key: "From", val: formatTextAddress(message.from) });
|
||
}
|
||
if (message.subject) {
|
||
rows.push({ key: "Subject", val: message.subject });
|
||
}
|
||
if (message.date) {
|
||
let dateOptions = {
|
||
year: "numeric",
|
||
month: "numeric",
|
||
day: "numeric",
|
||
hour: "numeric",
|
||
minute: "numeric",
|
||
second: "numeric",
|
||
hour12: false
|
||
};
|
||
let dateStr = typeof Intl === "undefined" ? message.date : new Intl.DateTimeFormat("default", dateOptions).format(new Date(message.date));
|
||
rows.push({ key: "Date", val: dateStr });
|
||
}
|
||
if (message.to && message.to.length) {
|
||
rows.push({ key: "To", val: formatTextAddresses(message.to) });
|
||
}
|
||
if (message.cc && message.cc.length) {
|
||
rows.push({ key: "Cc", val: formatTextAddresses(message.cc) });
|
||
}
|
||
if (message.bcc && message.bcc.length) {
|
||
rows.push({ key: "Bcc", val: formatTextAddresses(message.bcc) });
|
||
}
|
||
let maxKeyLength = rows.map((r) => r.key.length).reduce((acc, cur) => {
|
||
return cur > acc ? cur : acc;
|
||
}, 0);
|
||
rows = rows.flatMap((row) => {
|
||
let sepLen = maxKeyLength - row.key.length;
|
||
let prefix = `${row.key}: ${" ".repeat(sepLen)}`;
|
||
let emptyPrefix = `${" ".repeat(row.key.length + 1)} ${" ".repeat(sepLen)}`;
|
||
let foldedLines = foldLines(row.val, 80, true).split(/\r?\n/).map((line) => line.trim());
|
||
return foldedLines.map((line, i) => `${i ? emptyPrefix : prefix}${line}`);
|
||
});
|
||
let maxLineLength = rows.map((r) => r.length).reduce((acc, cur) => {
|
||
return cur > acc ? cur : acc;
|
||
}, 0);
|
||
let lineMarker = "-".repeat(maxLineLength);
|
||
let template = `
|
||
${lineMarker}
|
||
${rows.join("\n")}
|
||
${lineMarker}
|
||
`;
|
||
return template;
|
||
}
|
||
function formatHtmlHeader(message) {
|
||
let rows = [];
|
||
if (message.from) {
|
||
rows.push(
|
||
`<div class="postal-email-header-key">From</div><div class="postal-email-header-value">${formatHtmlAddress(message.from)}</div>`
|
||
);
|
||
}
|
||
if (message.subject) {
|
||
rows.push(
|
||
`<div class="postal-email-header-key">Subject</div><div class="postal-email-header-value postal-email-header-subject">${escapeHtml(
|
||
message.subject
|
||
)}</div>`
|
||
);
|
||
}
|
||
if (message.date) {
|
||
let dateOptions = {
|
||
year: "numeric",
|
||
month: "numeric",
|
||
day: "numeric",
|
||
hour: "numeric",
|
||
minute: "numeric",
|
||
second: "numeric",
|
||
hour12: false
|
||
};
|
||
let dateStr = typeof Intl === "undefined" ? message.date : new Intl.DateTimeFormat("default", dateOptions).format(new Date(message.date));
|
||
rows.push(
|
||
`<div class="postal-email-header-key">Date</div><div class="postal-email-header-value postal-email-header-date" data-date="${escapeHtml(
|
||
message.date
|
||
)}">${escapeHtml(dateStr)}</div>`
|
||
);
|
||
}
|
||
if (message.to && message.to.length) {
|
||
rows.push(
|
||
`<div class="postal-email-header-key">To</div><div class="postal-email-header-value">${formatHtmlAddresses(message.to)}</div>`
|
||
);
|
||
}
|
||
if (message.cc && message.cc.length) {
|
||
rows.push(
|
||
`<div class="postal-email-header-key">Cc</div><div class="postal-email-header-value">${formatHtmlAddresses(message.cc)}</div>`
|
||
);
|
||
}
|
||
if (message.bcc && message.bcc.length) {
|
||
rows.push(
|
||
`<div class="postal-email-header-key">Bcc</div><div class="postal-email-header-value">${formatHtmlAddresses(message.bcc)}</div>`
|
||
);
|
||
}
|
||
let template = `<div class="postal-email-header">${rows.length ? '<div class="postal-email-header-row">' : ""}${rows.join(
|
||
'</div>\n<div class="postal-email-header-row">'
|
||
)}${rows.length ? "</div>" : ""}</div>`;
|
||
return template;
|
||
}
|
||
// Annotate the CommonJS export names for ESM import in node:
|
||
0 && (module.exports = {
|
||
decodeHTMLEntities,
|
||
escapeHtml,
|
||
formatHtmlHeader,
|
||
formatTextHeader,
|
||
htmlToText,
|
||
textToHtml
|
||
});
|
||
|
||
// Make default export work naturally with require()
|
||
if (module.exports.default) {
|
||
var defaultExport = module.exports.default;
|
||
var namedExports = {};
|
||
for (var key in module.exports) {
|
||
if (key !== 'default' && key !== '__esModule') {
|
||
namedExports[key] = module.exports[key];
|
||
}
|
||
}
|
||
module.exports = defaultExport;
|
||
Object.assign(module.exports, namedExports);
|
||
// Preserve __esModule and .default for bundler/transpiler interop
|
||
Object.defineProperty(module.exports, '__esModule', { value: true });
|
||
module.exports.default = defaultExport;
|
||
}
|
||
|