<%* const EXCLUDE = ["title", "cssclasses", "aliases", "position", "member"];
module.exports = async (params) => {
const { app } = params;
const file = app.workspace.getActiveFile();
if (!file) { new Notice("No active file."); return; }
// Step 1: Strip the button block
let content = await app.vault.read(file);
content = content.replace(/\n?```button[\s\S]*?```\n?/g, "");
await app.vault.modify(file, content);
await new Promise(r => setTimeout(r, 150));
const cache = app.metadataCache.getFileCache(file);
const fm = cache?.frontmatter;
if (!fm) { new Notice("No frontmatter found."); return; }
// Step 2: Generate reference code if missing
if (!fm["reference code"]) {
const refCode = Math.floor(Math.random() * 9000000000000000) + 1000000000000000;
await app.fileManager.processFrontMatter(file, (fmObj) => {
fmObj["reference code"] = refCode;
});
await new Promise(r => setTimeout(r, 300));
}
// Step 3: Re-read updated frontmatter
const updatedFm = app.metadataCache.getFileCache(file)?.frontmatter;
if (!updatedFm) { new Notice("Could not read updated frontmatter."); return; }
const folder = file.parent?.name || "";
const title = file.basename;
const refCode = updatedFm["reference code"] || "";
// Step 4: Build table rows (excluding reference code from display)
const EXCLUDE_FROM_TABLE = [...EXCLUDE, "reference code"];
const rows = Object.entries(updatedFm)
.filter(([key]) => !EXCLUDE_FROM_TABLE.includes(key.toLowerCase()))
.map(([key, value]) => {
if (value === null || value === undefined || value === "") return null;
let display;
if (key.toLowerCase() === "source" && String(value).startsWith("http")) {
display = `[Article Link](${value})`;
} else if (Array.isArray(value)) {
display = value.join(", ");
} else {
display = String(value);
}
return `| ${key} | ${display} |`;
})
.filter(Boolean);
// Step 5: Build email button
const emailButton = `<div style="text-align:center;"><a href="mailto:
[email protected]?subject=Revision:%20${encodeURIComponent(folder)}%2F${encodeURIComponent(title)}%20-%20${refCode}" style="border:1px solid #555; padding:4px 12px; border-radius:4px; color:#a89ee8; text-decoration:none; font-size:0.9em; background-color:#2a2a2a;">📩 Submit a Revision/Addition</a></div>`;
// Step 6: Read file and locate frontmatter end
content = await app.vault.read(file);
const firstDash = content.indexOf("---");
const secondDash = content.indexOf("---", firstDash + 3);
const fmEnd = secondDash + 3;
const beforeFm = content.slice(0, fmEnd);
let afterFm = content.slice(fmEnd);
// Strip existing table, buttons, and stray rows
afterFm = afterFm.replace(/^(\s*\|[^\n]*\n)+/m, "");
afterFm = afterFm.replace(/<div[^>]*>[\s\S]*?<a href="mailto:[^"]*"[\s\S]*?<\/a>[\s\S]*?<\/div>\n*/g, "");
afterFm = afterFm.replace(/<a href="mailto:[^"]*"[^>]*>.*?<\/a>\n*/gs, "");
afterFm = afterFm.replace(/^\s*\|\s*reference code\s*\|[^\n]*\n?/gim, "");
afterFm = afterFm.replace(/^\s*\|\s*member\s*\|[^\n]*\n?/gim, "");
const bodyContent = afterFm.trimStart();
// Step 7: Reassemble
if (rows.length === 0) {
const newContent = beforeFm + "\n\n" + emailButton + "\n\n" + bodyContent;
await app.vault.modify(file, newContent);
} else {
const newTable = `| | |\n| --- | --- |\n${rows.join("\n")}`;
const newContent = beforeFm + "\n\n" + newTable + "\n<br>\n" + emailButton + "\n\n" + bodyContent;
await app.vault.modify(file, newContent);
}
new Notice("Done.");
};
_%>