/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ 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 __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); var __export = (target, all) => { __markAsModule(target); for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __reExport = (target, module2, desc) => { if (module2 && typeof module2 === "object" || typeof module2 === "function") { for (let key of __getOwnPropNames(module2)) if (!__hasOwnProp.call(target, key) && key !== "default") __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); } return target; }; var __toModule = (module2) => { return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); }; var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // main.ts __export(exports, { default: () => PDFAnnotationPlugin }); var import_obsidian = __toModule(require("obsidian")); // extractHighlight.ts var SUPPORTED_ANNOTS = ["Text", "Highlight", "Underline"]; function searchQuad(minx, maxx, miny, maxy, items) { const mycontent = items.reduce(function(txt, x) { if (x.width == 0) return txt; if (!(miny <= x.transform[5] && x.transform[5] <= maxy)) return txt; if (x.transform[4] + x.width < minx) return txt; if (x.transform[4] > maxx) return txt; const start = x.transform[4] >= minx ? 0 : Math.floor(x.str.length * (minx - x.transform[4]) / x.width); if (x.transform[4] + x.width <= maxx) { return txt + x.str.substr(start); } else { const lenc = Math.floor(x.str.length * (maxx - x.transform[4]) / x.width) - start; return txt + x.str.substr(start, lenc); } }, ""); return mycontent.trim(); } function extractHighlight(annot, items) { const highlight = annot.quadPoints.reduce((txt, quad) => { const minx = quad.reduce((prev, curr) => Math.min(prev, curr.x), quad[0].x); const maxx = quad.reduce((prev, curr) => Math.max(prev, curr.x), quad[0].x); const miny = quad.reduce((prev, curr) => Math.min(prev, curr.y), quad[0].y); const maxy = quad.reduce((prev, curr) => Math.max(prev, curr.y), quad[0].y); const res = searchQuad(minx, maxx, miny, maxy, items); if (txt.substring(txt.length - 1) != "-") { return txt + " " + res; } else if (txt.substring(txt.length - 2).toLowerCase() == txt.substring(txt.length - 2) && res.substring(0, 1).toLowerCase() == res.substring(0, 1)) { return txt.substring(0, txt.length - 1) + res; } else { return txt + res; } }, ""); return highlight; } function loadPage(page, pagenum, file, containingFolder, total) { return __async(this, null, function* () { let annotations = yield page.getAnnotations(); annotations = annotations.filter(function(anno) { return SUPPORTED_ANNOTS.indexOf(anno.subtype) >= 0; }); const content = yield page.getTextContent({ normalizeWhitespace: true }); content.items.sort(function(a1, a2) { if (a1.transform[5] > a2.transform[5]) return -1; if (a1.transform[5] < a2.transform[5]) return 1; if (a1.transform[4] > a2.transform[4]) return 1; if (a1.transform[4] < a2.transform[4]) return -1; return 0; }); annotations.map(function(anno) { return __async(this, null, function* () { if (anno.subtype == "Highlight" || anno.subtype == "Underline") { anno.highlightedText = extractHighlight(anno, content.items); } anno.folder = containingFolder; anno.file = file; anno.filepath = file.path; anno.pageNumber = pagenum; anno.author = anno.titleObj.str; anno.body = anno.contentsObj.str; total.push(anno); }); }); }); } function loadPDFFile(file, pdfjsLib, containingFolder, total) { return __async(this, null, function* () { const content = yield this.app.vault.readBinary(file); const pdf = yield pdfjsLib.getDocument(content).promise; for (let i = 1; i <= pdf.numPages; i++) { const page = yield pdf.getPage(i); yield loadPage(page, i, file, containingFolder, total); } }); } // main.ts function template(strings, ...keys) { return function(...values) { const dict = values[values.length - 1] || {}; const result = [strings[0]]; keys.forEach(function(key, i) { const value = Number.isInteger(key) ? values[key] : dict[key]; result.push(value, strings[i + 1]); }); return result.join(""); }; } var highlighted = template`> ${"highlightedText"} ${"body"} * *highlighted by ${"author"} at page ${"pageNumber"} on [[${"filepath"}]]* `; var note = template`${"body"} * *noted by ${"author"} at page ${"pageNumber"} on [[${"filepath"}]]* `; var PDFAnnotationPlugin = class extends import_obsidian.Plugin { sort(grandtotal) { const settings = this.settings; if (settings.sortByTopic) { grandtotal.forEach((anno) => { const lines = anno.body.split(/\r\n|\n\r|\n|\r/); anno.topic = lines[0]; anno.body = lines.slice(1).join("\r\n"); }); } grandtotal.sort(function(a1, a2) { if (settings.sortByTopic) { if (a1.topic > a2.topic) return 1; if (a1.topic < a2.topic) return -1; } if (settings.useFolderNames) { if (a1.folder > a2.folder) return 1; if (a1.folder < a2.folder) return -1; } if (a1.file.name > a2.file.name) return 1; if (a1.file.name < a2.file.name) return -1; if (a1.pageNumber > a2.pageNumber) return 1; if (a1.pageNumber < a2.pageNumber) return -1; if (a1.rect[1] > a2.rect[1]) return -1; if (a1.rect[1] < a2.rect[1]) return 1; return 0; }); } format(grandtotal) { let text = ""; let topic = ""; let currentFolder = ""; grandtotal.forEach((a) => { if (this.settings.sortByTopic) { if (topic != a.topic) { topic = a.topic; currentFolder = ""; text += `# ${topic} `; } } if (this.settings.useFolderNames) { if (currentFolder != a.folder) { currentFolder = a.folder; text += `## ${currentFolder} `; } } else { if (currentFolder != a.file.name) { currentFolder = a.file.name; text += `## ${currentFolder} `; } } if (a.subtype == "Text") { text += note(a); } else { text += highlighted(a); } }); if (grandtotal.length == 0) return "*No Annotations*"; else return text; } loadSinglePDFFile(file) { return __async(this, null, function* () { const pdfjsLib = yield (0, import_obsidian.loadPdfJs)(); const containingFolder = file.parent.name; const grandtotal = []; console.log("loading from file ", file); yield loadPDFFile(file, pdfjsLib, containingFolder, grandtotal); this.sort(grandtotal); const finalMarkdown = this.format(grandtotal); let filePath = file.name.replace(".pdf", ".md"); filePath = "Annotations for " + filePath; yield this.saveHighlightsToFile(filePath, finalMarkdown); yield this.app.workspace.openLinkText(filePath, "", true); }); } onload() { return __async(this, null, function* () { this.loadSettings(); this.addSettingTab(new PDFAnnotationPluginSettingTab(this.app, this)); this.addCommand({ id: "extract-annotations-single", name: "Extract PDF Annotations on single file", checkCallback: (checking) => { const file = this.app.workspace.getActiveFile(); if (file != null && file.extension === "pdf") { if (!checking) { this.loadSinglePDFFile(file); } return true; } else { return false; } } }); this.addCommand({ id: "extract-annotations", name: "Extract PDF Annotations", editorCallback: (editor, view) => __async(this, null, function* () { const file = this.app.workspace.getActiveFile(); if (file == null) return; const folder = file.parent; const grandtotal = []; const pdfjsLib = yield (0, import_obsidian.loadPdfJs)(); editor.replaceSelection("Extracting PDF Comments from " + folder.name + "\n"); const promises = []; import_obsidian.Vault.recurseChildren(folder, (file2) => __async(this, null, function* () { if (file2 instanceof import_obsidian.TFile) { if (file2.extension === "pdf") { promises.push(loadPDFFile(file2, pdfjsLib, file2.parent.name, grandtotal)); } } })); yield Promise.all(promises); this.sort(grandtotal); editor.replaceSelection(this.format(grandtotal)); }) }); }); } loadSettings() { this.settings = new PDFAnnotationPluginSetting(); (() => __async(this, null, function* () { const loadedSettings = yield this.loadData(); if (loadedSettings) { this.settings.useFolderNames = loadedSettings.useFolderNames; this.settings.sortByTopic = loadedSettings.sortByTopic; } }))(); } onunload() { } saveHighlightsToFile(filePath, mdString) { return __async(this, null, function* () { const fileExists = yield this.app.vault.adapter.exists(filePath); if (fileExists) { yield this.appendHighlightsToFile(filePath, mdString); } else { yield this.app.vault.create(filePath, mdString); } }); } appendHighlightsToFile(filePath, note2) { return __async(this, null, function* () { let existingContent = yield this.app.vault.adapter.read(filePath); if (existingContent.length > 0) { existingContent = existingContent + "\r\r"; } yield this.app.vault.adapter.write(filePath, existingContent + note2); }); } }; var PDFAnnotationPluginSetting = class { constructor() { this.useFolderNames = true; this.sortByTopic = true; } }; var PDFAnnotationPluginSettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); new import_obsidian.Setting(containerEl).setName("Use Folder Name").setDesc("If enabled, uses the PDF's folder name (instead of the PDF-Filename) for sorting").addToggle((toggle) => toggle.setValue(this.plugin.settings.useFolderNames).onChange((value) => { this.plugin.settings.useFolderNames = value; this.plugin.saveData(this.plugin.settings); })); new import_obsidian.Setting(containerEl).setName("Sort by Topic").setDesc("If enabled, uses the notes first line as Topic for primary sorting").addToggle((toggle) => toggle.setValue(this.plugin.settings.sortByTopic).onChange((value) => { this.plugin.settings.sortByTopic = value; this.plugin.saveData(this.plugin.settings); })); } };