Skip to content

Commit 032c545

Browse files
committed
support multiple md files per zotero item
1 parent a69f28b commit 032c545

File tree

7 files changed

+117
-42
lines changed

7 files changed

+117
-42
lines changed

README.md

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Currently this add-on is primarily designed to be a minimal companion to the [ob
1111

1212
Please post any bugs, questions, or feature requests in the Github repository.
1313

14-
1514
## Plugin Functions
1615

1716
Adds a colored tag to Zotero items for which there are associated reading notes in an external folder.
@@ -20,30 +19,26 @@ Opens an existing Markdown note in [Obsidian](https://obsidian.md) from the cont
2019

2120
![ZoteroObsidianCitationsMenu](ZoteroObsidianCitationsMenu.png)
2221

23-
2422
## Instalation
2523

2624
- Download the add-on (the .xpi file) from the latest release: https://github.com/daeh/zotero-obsidian-citations/releases
2725
- To download the .xpi file, right click it and select 'Save link as'
2826
- Run Zotero (version 5.x)
2927
- Go to `Tools -> Add-ons`
3028
- `Install Add-on From File`
31-
- Choose the file `zotero-obsidian-citations-0.0.11.xpi`
29+
- Choose the file `zotero-obsidian-citations-0.0.12.xpi`
3230
- Restart Zotero
3331

34-
3532
## Setup
3633

37-
_ZoteroObsidianCitations_ presumes that a given Zotero item corresponds to single Markdown file. A Markdown file can specify which Zotero item it's linked to using either a [Better BibTex](https://retorque.re/zotero-better-bibtex/) citekey or a Zotero-Item-Key.
38-
34+
_ZoteroObsidianCitations_ presumes that a given Zotero item corresponds to single Markdown file. A Markdown file can specify which Zotero item it's linked to using either a [Better BibTex](https://retorque.re/zotero-better-bibtex/) citekey or a Zotero-Item-Key.
3935

4036
1. Link Markdown files to Zotero items using **Better BibTex citekeys**.
4137

4238
- This is recommended if you created the Markdown notes with [obsidian-citation-plugin](https://github.com/hans/obsidian-citation-plugin).
4339

4440
- The Markdown file names should start with `@mycitekey` but can include extra information after it (e.g. a reading note might have the file name `@shepard1987science.md` or `@shepard1987science Toward a universal law of generalization for psychological science.md`, where `shepard1987science` is the BetterBibTex citekey).
4541

46-
4742
2. Link Markdown files to Zotero items using **Zotero Item Keys**.
4843

4944
- This is recommended if you created the Markdown notes with the `Export Note` feature of Zotero.
@@ -53,19 +48,18 @@ _ZoteroObsidianCitations_ presumes that a given Zotero item corresponds to singl
5348

5449
---
5550

56-
5751
### Option 1: Using BetterBibTex citekeys
5852

5953
_ZoteroObsidianCitations_ can extract the BetterBibTex citekey that specifies which Zotero Item a Markdown note corresponds to. The BetterBibTex citekey can be taken from the Markdown filename or yaml metadata.
6054

6155
- In `ZoteroObsidianCitations Preferences...` (under the `Tools` menu),
6256

6357
- Specify the location of the folder that contains your Markdown reading notes (e.g. `/Users/me/Documents/ObsVault/ReadingNotes/`). The _ZoteroObsidianCitations_ add-on will recursively search this path for Markdown files beginning with `@`.
64-
58+
6559
- Select the `Match notes based on BetterBibTex citekey` option.
6660

6761
- _ZoteroObsidianCitations_ expects that the filenames of your Markdown reading note files begin with `@mycitekey` but can include extra information after it (e.g. a reading note might have the file name `@shepard1987science.md` or `@shepard1987science Toward a universal law of generalization for psychological science.md`, where `shepard1987science` is the BetterBibTex citekey).
68-
62+
6963
- Optionally, you can have _ZoteroObsidianCitations_ read the metadata of your Markdown notes and extract the citekey from one of the fields. To enable this, specify the metadata ID (`citekey` is a common value).
7064

7165
- This is necessary if the file names do not begin with the correct citekey, which may happen if the citekeys include special characters (e.g. if a citekey contains `:`, it will probably need to be taken from the yaml metadata rather than the filename).
@@ -79,36 +73,33 @@ _ZoteroObsidianCitations_ can extract the BetterBibTex citekey that specifies wh
7973
### Option 2: Using Zotero Item Keys
8074

8175
_ZoteroObsidianCitations_ can extract the Zotero-Item-Key that specifies which Zotero Item a Markdown note corresponds to. The Zotero-Item-Key is taken from the Markdown file contents using a custom RegEx pattern.
82-
Zotero automatically generates Item Keys, they take the form of `ABCD1234`, as in `zotero://select/library/items/ABCD1234`. NB this is not the same as the BetterBibTex citekey you assigned an item (e.g. `mycitekey` in `zotero://select/items/@mycitekey`).
76+
77+
Zotero automatically generates Item Keys, they take the form of `ABCD1234`, as in `zotero://select/library/items/ABCD1234`. NB this is not the same as the BetterBibTex citekey you assigned an item (e.g. `mycitekey` in `zotero://select/items/@mycitekey`).
8378

8479
- In `ZoteroObsidianCitations Preferences...` (under the `Tools` menu),
8580

8681
- Specify the location of the folder that contains your Markdown reading notes (e.g. `/Users/me/Documents/ObsVault/ReadingNotes/`). The _ZoteroObsidianCitations_ add-on will recursively search this path for Markdown files beginning with `@`.
87-
8882
- Select the `Match notes based on Zotero-Item-Key` option.
89-
9083
- Specify a RegEx pattern to extract the Zotero-Item-Key from the Markdown contents.
9184

9285
E.g. if your note has the line
9386

9487
`- local:: [local zotero](zotero://select/library/items/GZ9DQ2AM)`
9588

9689
you could extract the Zotero key (`GZ9DQ2AM`) using this RegEx pattern:
97-
90+
9891
`^- local::.+\/items\/(\w+)\)`
9992

10093
- Run the synchronization function from `Tools -> ZoteroObsidianCitations Sync Tags`.
10194
- This will add a tag (`ObsCite`) to every Zotero item for which there exists a reading note in the external folder you specified.
10295
- In the `Tags` plane of Zotero, right-click on the `ObsCite` tag and assign it a color, which will mark the tagged items in the preview plane of Zotero.
10396

104-
10597
## Notes
10698

10799
[GitHub](https://github.com/daeh/zotero-obsidian-citations): Source code repository
108100

109101
Code for this extension is based on [ZotFile](https://github.com/jlegewie/zotfile) and [Zotero Citationcounts](https://github.com/eschnett/zotero-citationcounts) (which is based on [Zotero DOI Manager](https://github.com/bwiernik/zotero-shortdoi), which is based in part on [Zotero Google Scholar Citations](https://github.com/beloglazov/zotero-scholar-citations)).
110102

111-
112103
## License
113104

114-
Distributed under the MIT License.
105+
Distributed under the MIT License.

bin/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
version='0.0.11'
3+
version='0.0.12'
44

55
rm -f zotero-obsidian-citations-${version}.xpi
66
zip -r zotero-obsidian-citations-${version}.xpi chrome/* defaults/* chrome.manifest install.rdf

chrome/content/overlay.xul

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,33 @@
2121
</menupopup>
2222

2323
<menupopup id="zotero-itemmenu" onpopupshowing="Zotero.ObsCite.buildItemContextMenu();">
24-
<menuitem id="id-obscite-itemmenu-open-obsidian" label="&obscite.item-menu.open-obsidian-label;" hidden="false" oncommand="Zotero.ObsCite.openSelectedItemsObsidian()"/>
25-
<menuitem id="id-obscite-itemmenu-show-md" label="&obscite.item-menu.show-md-label;" hidden="false" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem()"/>
24+
<menuseparator id="id-obscite-itemmenu-separator-top"/>
25+
<menuitem id="id-obscite-itemmenu-open-obsidian" label="&obscite.item-menu.open-obsidian-label;" hidden="false" oncommand="Zotero.ObsCite.openSelectedItemsObsidian(0)"/>
26+
<menuitem id="id-obscite-itemmenu-show-md" label="&obscite.item-menu.show-md-label;" hidden="false" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(0)"/>
27+
28+
29+
<menu id="id-obscite-itemmenu-listmd-restrict" label="&obscite.item-menu.list-md-label;" >
30+
<menupopup id="id-obscite-itemmenu-listmd-menu" onpopupshowing="Zotero.ObsCite.buildItemContextMenuListMD();">
31+
<menuitem id="id-obscite-itemmenu-listmd-file-00" hidden="true" label="menu1" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(0);"/>
32+
<menuitem id="id-obscite-itemmenu-listmd-file-01" hidden="true" label="menu1" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(1);"/>
33+
<menuitem id="id-obscite-itemmenu-listmd-file-02" hidden="true" label="menu2" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(2);"/>
34+
<menuitem id="id-obscite-itemmenu-listmd-file-03" hidden="true" label="menu3" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(3);"/>
35+
<menuitem id="id-obscite-itemmenu-listmd-file-04" hidden="true" label="menu4" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(4);"/>
36+
<menuitem id="id-obscite-itemmenu-listmd-file-05" hidden="true" label="menu5" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(5);"/>
37+
<menuitem id="id-obscite-itemmenu-listmd-file-06" hidden="true" label="menu6" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(6);"/>
38+
<menuitem id="id-obscite-itemmenu-listmd-file-07" hidden="true" label="menu7" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(7);"/>
39+
<menuitem id="id-obscite-itemmenu-listmd-file-08" hidden="true" label="menu8" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(8);"/>
40+
<menuitem id="id-obscite-itemmenu-listmd-file-09" hidden="true" label="menu9" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(9);"/>
41+
<menuitem id="id-obscite-itemmenu-listmd-file-10" hidden="true" label="menu10" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(10);"/>
42+
<menuitem id="id-obscite-itemmenu-listmd-file-11" hidden="true" label="menu11" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(11);"/>
43+
<menuitem id="id-obscite-itemmenu-listmd-file-12" hidden="true" label="menu12" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(12);"/>
44+
<menuitem id="id-obscite-itemmenu-listmd-file-13" hidden="true" label="menu13" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(13);"/>
45+
<menuitem id="id-obscite-itemmenu-listmd-file-14" hidden="true" label="menu14" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(14);"/>
46+
<menuitem id="id-obscite-itemmenu-listmd-file-15" hidden="true" label="menu15" tooltiptext="" oncommand="Zotero.ObsCite.showSelectedItemMarkdownInFilesystem(15);"/>
47+
</menupopup>
48+
</menu>
49+
50+
2651
</menupopup>
2752

2853

chrome/content/scripts/zoteroobscite.js

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ if (typeof Zotero === 'undefined') {
1313
}
1414

1515
Zotero.ObsCite = {
16-
version: '0.0.11',
16+
version: '0.0.12',
1717
folderSep: null,
1818
cleanrun: true,
1919
suppressNotifications: false,
@@ -194,7 +194,7 @@ Zotero.ObsCite = {
194194

195195
if (matchstrategy === 'bbtcitekey') {
196196
const bbtactive = await this._checkBBTinstalled();
197-
if (!bbtactive) return false;
197+
if (!bbtactive || !bbtactive[0]) return false;
198198
if (this._getParam_metadatakeyword() == null) return false;
199199
} else if (matchstrategy === 'zotitemkey') {
200200
const zotkeyregex = this._getParam_zotkeyregex();
@@ -651,16 +651,16 @@ Zotero.ObsCite = {
651651
let deferred = Zotero.Promise.defer();
652652

653653
function _checkBTT(addon) {
654-
let found = false;
654+
let res = [];
655655
if (addon === null || !addon.isActive) {
656-
found = false;
656+
res.push(false);
657657
} else {
658658
let win = Services.wm.getMostRecentWindow("navigator:browser");
659-
found = win.Zotero.BetterBibTeX.ready.then(() => {
660-
found = true;
659+
win.Zotero.BetterBibTeX.ready.then(() => {
660+
res.push(true);
661661
});
662662
}
663-
deferred.resolve(found);
663+
deferred.resolve(res);
664664
}
665665

666666
AddonManager.getAddonByID("[email protected]", _checkBTT);
@@ -998,29 +998,83 @@ Zotero.ObsCite = {
998998
//// Controls for Item menu
999999

10001000
buildItemContextMenu: function () {
1001-
let show = false;
1001+
let found_single = false;
1002+
let found_multiple = false;
10021003
const pane = Services.wm.getMostRecentWindow("navigator:browser").ZoteroPane;
10031004
const doc = pane.document;
10041005
const items = pane.getSelectedItems();
10051006
for (const item of items) {
10061007
if (this.dataKeys.includes(item.id)) {
1007-
show = true;
1008+
show_single = true;
1009+
if (this.data[item.id.toString()].length > 1) {
1010+
found_multiple = true;
1011+
} else {
1012+
found_single = true;
1013+
}
1014+
/// only process first item if multiple selected
1015+
break;
1016+
}
1017+
}
1018+
1019+
if (found_multiple) {
1020+
doc.getElementById("id-obscite-itemmenu-separator-top").hidden = false;
1021+
doc.getElementById("id-obscite-itemmenu-open-obsidian").hidden = true;
1022+
doc.getElementById("id-obscite-itemmenu-show-md").hidden = true;
1023+
doc.getElementById("id-obscite-itemmenu-listmd-restrict").hidden = false;
1024+
} else if (found_single) {
1025+
doc.getElementById("id-obscite-itemmenu-separator-top").hidden = false;
1026+
doc.getElementById("id-obscite-itemmenu-open-obsidian").hidden = false;
1027+
doc.getElementById("id-obscite-itemmenu-show-md").hidden = false;
1028+
doc.getElementById("id-obscite-itemmenu-listmd-restrict").hidden = true;
1029+
} else {
1030+
doc.getElementById("id-obscite-itemmenu-separator-top").hidden = true;
1031+
doc.getElementById("id-obscite-itemmenu-open-obsidian").hidden = true;
1032+
doc.getElementById("id-obscite-itemmenu-show-md").hidden = true;
1033+
doc.getElementById("id-obscite-itemmenu-listmd-restrict").hidden = true;
1034+
}
1035+
1036+
},
1037+
1038+
buildItemContextMenuListMD: function () {
1039+
let win = Services.wm.getMostRecentWindow('navigator:browser');
1040+
let nodes = win.ZoteroPane.document.getElementById('id-obscite-itemmenu-listmd-menu').childNodes;
1041+
// hide all items by default
1042+
for (let i = 0; i < nodes.length; i++) nodes[i].setAttribute('hidden', true);
1043+
1044+
const items = Services.wm.getMostRecentWindow("navigator:browser").ZoteroPane.getSelectedItems();
1045+
for (const item of items) {
1046+
if (this.dataKeys.includes(item.id)) {
1047+
const entry_res_list = this.data[item.id.toString()];
1048+
let ii = 0;
1049+
for (const entry_res of entry_res_list) {
1050+
if (ii < entry_res_list.length) {
1051+
// set attributes of menu item
1052+
nodes[ii].setAttribute('label', entry_res.name);
1053+
// nodes[ii].setAttribute('tooltiptext', this.ZFgetString('menu.collection.tooltip', [folder.path]));
1054+
// show menu item
1055+
nodes[ii].setAttribute('hidden', false);
1056+
} else {
1057+
break;
1058+
}
1059+
ii++;
1060+
}
1061+
/// only process first item if multiple selected
10081062
break;
10091063
}
10101064
}
1011-
doc.getElementById("id-obscite-itemmenu-open-obsidian").hidden = !show;
1012-
doc.getElementById("id-obscite-itemmenu-show-md").hidden = !show;
10131065
},
10141066

1015-
openSelectedItemsObsidian: function () {
1067+
openSelectedItemsObsidian: function (idx) {
1068+
idx = idx || 0;
10161069
const items = Services.wm.getMostRecentWindow("navigator:browser").ZoteroPane.getSelectedItems();
10171070
const vaultName = ''; ///TODO add preference to specify vault
10181071
const vaultKey = (vaultName.length > 0) ? 'vault=' + vaultName + '&' : '';
10191072
for (const item of items) {
10201073
if (this.dataKeys.includes(item.id)) {
10211074
const entry_res_list = this.data[item.id.toString()];
1022-
/// NB ignore all be first file entry associated with an itemID
1023-
const entry_res = entry_res_list[0];
1075+
1076+
idx = (idx < entry_res_list.length) ? idx : 0;
1077+
const entry_res = entry_res_list[idx];
10241078

10251079
const uriEncoded = encodeURIComponent(entry_res.path);
10261080
Zotero.launchURL("obsidian://open?" + vaultKey + "path=" + uriEncoded);
@@ -1029,19 +1083,22 @@ Zotero.ObsCite = {
10291083
// const uriEncoded = encodeURIComponent(entry_res.name);
10301084
// Zotero.launchURL("obsidian://open?" + vaultKey + "file=" + uriEncoded);
10311085

1032-
/// only open first item note
1086+
/// only process first item if multiple selected
10331087
break;
10341088
}
10351089
}
10361090
},
10371091

1038-
showSelectedItemMarkdownInFilesystem: function () {
1092+
showSelectedItemMarkdownInFilesystem: function (idx) {
1093+
idx = idx || 0;
10391094
const items = Services.wm.getMostRecentWindow("navigator:browser").ZoteroPane.getSelectedItems();
10401095
for (const item of items) {
10411096
if (this.dataKeys.includes(item.id)) {
10421097
const entry_res_list = this.data[item.id.toString()];
1043-
/// NB ignore all be firs file entry associated with an itemID
1044-
const entry_res = entry_res_list[0];
1098+
1099+
idx = (idx < entry_res_list.length) ? idx : 0;
1100+
const entry_res = entry_res_list[idx];
1101+
10451102
let file = new FileUtils.File(OS.Path.normalize(entry_res.path));
10461103
if (file.exists()) {
10471104
try {
@@ -1053,7 +1110,7 @@ Zotero.ObsCite = {
10531110
Zotero.launchFile(file.parent);
10541111
}
10551112
}
1056-
/// only open first item note
1113+
/// only process first item if multiple selected
10571114
break;
10581115
}
10591116
}

chrome/locale/en-US/overlay.dtd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33

44
<!ENTITY obscite.item-menu.open-obsidian-label "Open ObsidianMD Note">
55
<!ENTITY obscite.item-menu.show-md-label "Show Markdown File">
6+
7+
<!ENTITY obscite.item-menu.list-md-label "Linked Markdown Files">

install.rdf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<Description about="urn:mozilla:install-manifest">
66
<em:id>[email protected]</em:id>
77
<em:name>ZoteroObsidianCitations</em:name>
8-
<em:version>0.0.11</em:version>
8+
<em:version>0.0.12</em:version>
99
<em:type>2</em:type>
1010
<em:creator>Dae Houlihan</em:creator>
1111
<em:description>Add a tag to Zotero items that have a external note.</em:description>

update.rdf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
<rdf:Seq>
77
<rdf:li>
88
<rdf:Description>
9-
<em:version>0.0.11</em:version>
9+
<em:version>0.0.12</em:version>
1010
<em:targetApplication>
1111
<rdf:Description>
1212
<em:id>[email protected]</em:id>
1313
<em:minVersion>5.0.0</em:minVersion>
1414
<em:maxVersion>5.*</em:maxVersion>
15-
<em:updateLink>https://github.com/daeh/zotero-obsidian-citations/releases/download/v0.0.11/zotero-obsidian-citations-0.0.11.xpi</em:updateLink>
15+
<em:updateLink>https://github.com/daeh/zotero-obsidian-citations/releases/download/v0.0.12/zotero-obsidian-citations-0.0.12.xpi</em:updateLink>
1616
</rdf:Description>
1717
</em:targetApplication>
1818

0 commit comments

Comments
 (0)