chore: initial project commit

This commit is contained in:
Ignacio Ballesteros
2026-02-17 21:25:46 +01:00
commit 70f7fac23e
34 changed files with 6786 additions and 0 deletions

70
addon/bootstrap.js vendored Normal file
View File

@@ -0,0 +1,70 @@
/* eslint-disable no-undef */
var chromeHandle;
async function startup({ id, version, rootURI }, reason) {
await Zotero.initializationPromise;
try {
const aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(
Ci.amIAddonManagerStartup
);
const manifestURI = Services.io.newURI(rootURI + "manifest.json");
chromeHandle = aomStartup.registerChrome(manifestURI, [
["content", "orgexportannotations", rootURI + "content/"],
]);
Services.scriptloader.loadSubScript(rootURI + "content/scripts/index.js");
if (typeof Zotero.OrgExportAnnotations === "undefined") {
throw new Error("Zotero.OrgExportAnnotations not loaded from index.js");
}
await Zotero.OrgExportAnnotations.init({ id, version, rootURI });
await Zotero.OrgExportAnnotations.hooks.onStartup();
} catch (error) {
Zotero.logError("[OrgExportAnnotations] Startup failed: " + error);
throw error;
}
}
async function onMainWindowLoad({ window }) {
try {
await Zotero.OrgExportAnnotations?.hooks?.onMainWindowLoad(window);
} catch (error) {
Zotero.logError("[OrgExportAnnotations] onMainWindowLoad failed: " + error);
}
}
async function onMainWindowUnload({ window }) {
try {
await Zotero.OrgExportAnnotations?.hooks?.onMainWindowUnload(window);
} catch (error) {
Zotero.logError("[OrgExportAnnotations] onMainWindowUnload failed: " + error);
}
}
function shutdown({ id, version, rootURI }, reason) {
if (reason === APP_SHUTDOWN) {
return;
}
try {
Zotero.OrgExportAnnotations?.hooks?.onShutdown();
} catch (error) {
Zotero.logError("[OrgExportAnnotations] onShutdown failed: " + error);
}
try {
chromeHandle?.destruct();
} catch (error) {
Zotero.logError("[OrgExportAnnotations] Failed to destruct chrome handle: " + error);
}
chromeHandle = null;
delete Zotero.OrgExportAnnotations;
}
function install() {}
function uninstall() {}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="-7.65 -13.389 144.98 160"><path fill="#a04d32" stroke="#000" stroke-width="3" d="M133.399 46.067c-.205-3.15-2.842-4.366-5.993-2.125-7.22-1.297-14.305-.687-17.8-.981-7.662-1.073-14.041-5.128-14.041-5.128.932-1.239.486-3.917-5.498-4.101-1.646-.542-3.336-1.327-4.933-1.979.544-1.145-.133-2.836-.133-2.836 2.435-.672 2.808-3.842 1.848-5.709 3.106.084 2.612-4.718 2.183-6.381 2.435-.923 2.77-3.831 1.763-6.129 2.938-.671 3.022-4.114 2.77-6.548 3.023-.168 2.604-5.457 2.604-6.549 2.604-1.679 2.016-3.946 2.425-6.573 1.605-3.25-.577-4.173-2.116-.71-1.651 3.001-3.77 4.311-3.75 6.528.755 1.259-5.625 3.106-3.61 7.052-1.428 1.763-4.785 4.03-3.592 6.733-.606 1.326-4.888 4.433-3.041 7.371-4.03 2.687-3.79 3.335-2.938 5.793-1.147.736-2.318 1.862-2.995 3.094-1.32-1.568-2.603-4.429-2.584-8.294 0-3.275-6.1.318-6.1 6.784 0 .556-.056 1.061-.134 1.542-2.11.243-4.751.707-8.08 1.494-.106.073-.157.186-.182.316a8.704 8.704 0 01-.277-1.553c-.582-3.79-4.934-9.56-7.057-2.434-1.096 2.611-1.74 4.392-2.115 5.789v0s-.336.226-.957.61c-2.62 1.622-3.562 6.686-13.075 9.883-3.211 1.079-7.4 1.945-12.96 2.395-9.57.773-27.887 17.314-29.114 33.097-.283 3.964.31 13.737 3.596 22.31l.005.02c.015.042.032.081.048.122.052.134.103.267.156.398.28.718.579 1.405.895 2.062 1.885 4.028 4.46 7.59 7.934 9.882a25.252 25.252 0 004.372 2.762c5.907 9.749 18.442 22.252 42.075 14.859 36.255-10.284 56.263 13.809 58.568 15.5 3.399 3.433-8.786-29.835-34.587-44.788-15.253-8.322-5.678-22.656-4.585-27.718 0 0 12.227 8.557 21.087-4.52 8.004 2.062 13.367-1.462 20.25 1.03 4.184 1.833 21.77.726 15.235-9.104 4.11-2.683 4.544-1.815 6.6-5.9 1.104-4.952-1.403-6.012-2.167-7.366z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="-7.65 -13.389 144.98 160"><path fill="#a04d32" stroke="#000" stroke-width="3" d="M133.399 46.067c-.205-3.15-2.842-4.366-5.993-2.125-7.22-1.297-14.305-.687-17.8-.981-7.662-1.073-14.041-5.128-14.041-5.128.932-1.239.486-3.917-5.498-4.101-1.646-.542-3.336-1.327-4.933-1.979.544-1.145-.133-2.836-.133-2.836 2.435-.672 2.808-3.842 1.848-5.709 3.106.084 2.612-4.718 2.183-6.381 2.435-.923 2.77-3.831 1.763-6.129 2.938-.671 3.022-4.114 2.77-6.548 3.023-.168 2.604-5.457 2.604-6.549 2.604-1.679 2.016-3.946 2.425-6.573 1.605-3.25-.577-4.173-2.116-.71-1.651 3.001-3.77 4.311-3.75 6.528.755 1.259-5.625 3.106-3.61 7.052-1.428 1.763-4.785 4.03-3.592 6.733-.606 1.326-4.888 4.433-3.041 7.371-4.03 2.687-3.79 3.335-2.938 5.793-1.147.736-2.318 1.862-2.995 3.094-1.32-1.568-2.603-4.429-2.584-8.294 0-3.275-6.1.318-6.1 6.784 0 .556-.056 1.061-.134 1.542-2.11.243-4.751.707-8.08 1.494-.106.073-.157.186-.182.316a8.704 8.704 0 01-.277-1.553c-.582-3.79-4.934-9.56-7.057-2.434-1.096 2.611-1.74 4.392-2.115 5.789v0s-.336.226-.957.61c-2.62 1.622-3.562 6.686-13.075 9.883-3.211 1.079-7.4 1.945-12.96 2.395-9.57.773-27.887 17.314-29.114 33.097-.283 3.964.31 13.737 3.596 22.31l.005.02c.015.042.032.081.048.122.052.134.103.267.156.398.28.718.579 1.405.895 2.062 1.885 4.028 4.46 7.59 7.934 9.882a25.252 25.252 0 004.372 2.762c5.907 9.749 18.442 22.252 42.075 14.859 36.255-10.284 56.263 13.809 58.568 15.5 3.399 3.433-8.786-29.835-34.587-44.788-15.253-8.322-5.678-22.656-4.585-27.718 0 0 12.227 8.557 21.087-4.52 8.004 2.062 13.367-1.462 20.25 1.03 4.184 1.833 21.77.726 15.235-9.104 4.11-2.683 4.544-1.815 6.6-5.9 1.104-4.952-1.403-6.012-2.167-7.366z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-7.65 -13.389 144.98 160"><path fill="#a04d32" stroke="#000" stroke-width="3" d="M133.399 46.067c-.205-3.15-2.842-4.366-5.993-2.125-7.22-1.297-14.305-.687-17.8-.981-7.662-1.073-14.041-5.128-14.041-5.128.932-1.239.486-3.917-5.498-4.101-1.646-.542-3.336-1.327-4.933-1.979.544-1.145-.133-2.836-.133-2.836 2.435-.672 2.808-3.842 1.848-5.709 3.106.084 2.612-4.718 2.183-6.381 2.435-.923 2.77-3.831 1.763-6.129 2.938-.671 3.022-4.114 2.77-6.548 3.023-.168 2.604-5.457 2.604-6.549 2.604-1.679 2.016-3.946 2.425-6.573 1.605-3.25-.577-4.173-2.116-.71-1.651 3.001-3.77 4.311-3.75 6.528.755 1.259-5.625 3.106-3.61 7.052-1.428 1.763-4.785 4.03-3.592 6.733-.606 1.326-4.888 4.433-3.041 7.371-4.03 2.687-3.79 3.335-2.938 5.793-1.147.736-2.318 1.862-2.995 3.094-1.32-1.568-2.603-4.429-2.584-8.294 0-3.275-6.1.318-6.1 6.784 0 .556-.056 1.061-.134 1.542-2.11.243-4.751.707-8.08 1.494-.106.073-.157.186-.182.316a8.704 8.704 0 01-.277-1.553c-.582-3.79-4.934-9.56-7.057-2.434-1.096 2.611-1.74 4.392-2.115 5.789v0s-.336.226-.957.61c-2.62 1.622-3.562 6.686-13.075 9.883-3.211 1.079-7.4 1.945-12.96 2.395-9.57.773-27.887 17.314-29.114 33.097-.283 3.964.31 13.737 3.596 22.31l.005.02c.015.042.032.081.048.122.052.134.103.267.156.398.28.718.579 1.405.895 2.062 1.885 4.028 4.46 7.59 7.934 9.882a25.252 25.252 0 004.372 2.762c5.907 9.749 18.442 22.252 42.075 14.859 36.255-10.284 56.263 13.809 58.568 15.5 3.399 3.433-8.786-29.835-34.587-44.788-15.253-8.322-5.678-22.656-4.585-27.718 0 0 12.227 8.557 21.087-4.52 8.004 2.062 13.367-1.462 20.25 1.03 4.184 1.833 21.77.726 15.235-9.104 4.11-2.683 4.544-1.815 6.6-5.9 1.104-4.952-1.403-6.012-2.167-7.366z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,83 @@
<vbox id="orgexportannotations-prefs"
onload="window.OrgExportAnnotationsPrefs?.init()">
<linkset>
<html:link rel="localization" href="orgexportannotations-addon.ftl"/>
<html:link rel="localization" href="orgexportannotations-preferences.ftl"/>
</linkset>
<!-- Paths Section -->
<groupbox>
<caption data-l10n-id="prefs-section-paths"/>
<vbox class="orgexportannotations-pref-row">
<hbox align="center">
<label data-l10n-id="prefs-notes-path"
control="orgexportannotations-notes-path"/>
<html:input id="orgexportannotations-notes-path"
type="text"
preference="extensions.zotero.orgexportannotations.notesPath"
style="flex: 1;"/>
<button data-l10n-id="prefs-browse"
oncommand="window.OrgExportAnnotationsPrefs?.browseNotesPath()"/>
</hbox>
<description data-l10n-id="prefs-notes-path-description"
class="orgexportannotations-pref-description"/>
</vbox>
<vbox class="orgexportannotations-pref-row">
<hbox align="center">
<label data-l10n-id="prefs-pandoc-path"
control="orgexportannotations-pandoc-path"/>
<html:input id="orgexportannotations-pandoc-path"
type="text"
preference="extensions.zotero.orgexportannotations.pandocPath"
style="flex: 1;"/>
<button data-l10n-id="prefs-browse"
oncommand="window.OrgExportAnnotationsPrefs?.browsePandocPath()"/>
<button data-l10n-id="prefs-test-pandoc"
oncommand="window.OrgExportAnnotationsPrefs?.testPandoc()"/>
</hbox>
<description data-l10n-id="prefs-pandoc-path-description"
class="orgexportannotations-pref-description"/>
</vbox>
</groupbox>
<!-- Behavior Section -->
<groupbox>
<caption data-l10n-id="prefs-section-behavior"/>
<checkbox id="orgexportannotations-attach-org"
data-l10n-id="prefs-attach-org"
preference="extensions.zotero.orgexportannotations.attachOrgFile"/>
<checkbox id="orgexportannotations-auto-export-sync"
data-l10n-id="prefs-auto-export-sync"
preference="extensions.zotero.orgexportannotations.autoExportOnSync"/>
<checkbox id="orgexportannotations-export-tab-close"
data-l10n-id="prefs-export-tab-close"
preference="extensions.zotero.orgexportannotations.exportOnTabClose"/>
<checkbox id="orgexportannotations-show-notification"
data-l10n-id="prefs-show-notification"
preference="extensions.zotero.orgexportannotations.showNotification"/>
</groupbox>
<!-- Advanced Section -->
<groupbox>
<caption data-l10n-id="prefs-section-advanced"/>
<checkbox id="orgexportannotations-debug"
data-l10n-id="prefs-debug"
preference="extensions.zotero.orgexportannotations.debug"/>
<hbox>
<button data-l10n-id="prefs-export-now"
oncommand="window.OrgExportAnnotationsPrefs?.exportAllNow()"/>
<button data-l10n-id="prefs-force-export"
oncommand="window.OrgExportAnnotationsPrefs?.forceExportAllNow()"/>
</hbox>
</groupbox>
</vbox>

View File

@@ -0,0 +1,76 @@
/* eslint-disable no-undef */
const OrgExportAnnotationsPrefs = {
init() {
try {
console.log("[OrgExportAnnotationsPrefs] Initializing preferences pane");
} catch (error) {
console.error("[OrgExportAnnotationsPrefs] Init error:", error);
}
},
async browseNotesPath() {
const fp = new FilePicker();
// Use browsingContext for Zotero 8+, fall back to window for Zotero 7
const context = window.browsingContext || window;
fp.init(context, "Select Notes Directory", fp.modeGetFolder);
const result = await new Promise((resolve) => fp.open(resolve));
if (result === fp.returnOK) {
const input = document.getElementById("orgexportannotations-notes-path");
if (input) {
input.value = fp.file.path;
input.dispatchEvent(new Event("change"));
}
}
},
async browsePandocPath() {
const fp = new FilePicker();
// Use browsingContext for Zotero 8+, fall back to window for Zotero 7
const context = window.browsingContext || window;
fp.init(context, "Select Pandoc Executable", fp.modeOpen);
const result = await new Promise((resolve) => fp.open(resolve));
if (result === fp.returnOK) {
const input = document.getElementById("orgexportannotations-pandoc-path");
if (input) {
input.value = fp.file.path;
input.dispatchEvent(new Event("change"));
}
}
},
async testPandoc() {
const input = document.getElementById("orgexportannotations-pandoc-path");
const pandocPath = (input && input.value) || "pandoc";
try {
await Zotero.Utilities.Internal.exec(pandocPath, ["--version"]);
alert("Pandoc is working correctly!");
} catch (_error) {
alert(`Pandoc not found at: ${pandocPath}\n\nPlease check the path.`);
}
},
async exportAllNow() {
try {
if (Zotero.OrgExportAnnotations && Zotero.OrgExportAnnotations.hooks) {
await Zotero.OrgExportAnnotations.hooks.onMenuExportAll();
}
} catch (error) {
alert(`Export failed: ${error.message}`);
}
},
async forceExportAllNow() {
try {
if (Zotero.OrgExportAnnotations && Zotero.OrgExportAnnotations.hooks) {
await Zotero.OrgExportAnnotations.hooks.onMenuForceExportAll();
}
} catch (error) {
alert(`Force export failed: ${error.message}`);
}
},
};
window.OrgExportAnnotationsPrefs = OrgExportAnnotationsPrefs;

View File

@@ -0,0 +1,27 @@
name = Zotero Org Export Annotations
description = Export PDF/EPUB annotations to Org-mode files
menu-export-all = Export All Annotations to Org
menu-export-selected = Export Selected to Org
menu-preferences = Org Export Preferences...
notification-export-complete =
{ $count ->
[one] Exported { $count } item to Org
*[other] Exported { $count } items to Org
}
notification-export-error = Export failed: { $error }
notification-no-items = No items with annotations to export
notification-config-required = Please configure the notes path in preferences
error-better-notes-required =
Better Notes plugin is required for Org export.
Please install it from: https://github.com/windingwind/zotero-better-notes
error-pandoc-not-found =
Pandoc not found at: { $path }
Please install pandoc or configure the correct path in preferences.
error-notes-path-not-set =
Notes output path is not configured.
Please set it in Tools > Org Export Preferences.
error-notes-path-invalid =
Notes path does not exist: { $path }

View File

@@ -0,0 +1,40 @@
prefs-title = Org Export Annotations
prefs-section-paths =
.label = Output Paths
prefs-notes-path =
.value = Notes Directory:
prefs-notes-path-description =
Directory where Org files will be saved.
Files are named using the citation key (e.g., smith2020.org).
prefs-pandoc-path =
.value = Pandoc Path:
prefs-pandoc-path-description =
Path to pandoc executable. Leave as "pandoc" to use system PATH.
prefs-browse =
.label = Browse...
prefs-section-behavior =
.label = Behavior
prefs-attach-org =
.label = Attach Org files to Zotero items
prefs-attach-org-description =
Link generated Org files as attachments to their parent items.
prefs-auto-export-sync =
.label = Export automatically after Zotero sync
prefs-export-tab-close =
.label = Export when closing reader tab
prefs-show-notification =
.label = Show notification after export
prefs-section-advanced =
.label = Advanced
prefs-debug =
.label = Enable debug logging
prefs-export-now =
.label = Export All Now
prefs-force-export =
.label = Force Export All
prefs-test-pandoc =
.label = Test Pandoc

20
addon/manifest.json Normal file
View File

@@ -0,0 +1,20 @@
{
"manifest_version": 2,
"name": "Zotero Org Export Annotations",
"version": "1.0.0",
"description": "Export Zotero PDF/EPUB annotations to Org-mode files for Emacs, org-roam, and citar",
"author": "Ignacio",
"homepage_url": "https://github.com/ignaciobll/zotero-org-export-annotations",
"icons": {
"48": "content/icons/icon.svg",
"96": "content/icons/icon@2x.svg"
},
"applications": {
"zotero": {
"id": "org-export-annotations@zotero.org",
"update_url": "https://github.com/ignaciobll/zotero-org-export-annotations/releases/download/release/update.json",
"strict_min_version": "7.0",
"strict_max_version": "8.*"
}
}
}

7
addon/prefs.js Normal file
View File

@@ -0,0 +1,7 @@
pref("extensions.zotero.orgexportannotations.notesPath", "");
pref("extensions.zotero.orgexportannotations.pandocPath", "pandoc");
pref("extensions.zotero.orgexportannotations.attachOrgFile", false);
pref("extensions.zotero.orgexportannotations.autoExportOnSync", true);
pref("extensions.zotero.orgexportannotations.exportOnTabClose", true);
pref("extensions.zotero.orgexportannotations.showNotification", true);
pref("extensions.zotero.orgexportannotations.debug", false);