diff --git a/README.md b/README.md
index 83becde..b732ff2 100644
--- a/README.md
+++ b/README.md
@@ -84,6 +84,8 @@ Last, you can set the language for Google and DeepL translation the label of the
These global settings apply to the plugin as a whole.
![Opening settings](https://raw.githubusercontent.com/frianasoa/Ze-Notes/main/docs/images/07.zenotes-load-save-display-performance.png "Other settings")
+Font settings was added. You can use this to zoom in and out of your table with the shortcut "Ctrl + Mouse wheel" or "Ctrl + Plus/Minus"
+
## Use cases
### How to start a systematic review of the literature?
diff --git a/content/notes/io.js b/content/notes/io.js
index d6144b5..a17b571 100644
--- a/content/notes/io.js
+++ b/content/notes/io.js
@@ -4,6 +4,7 @@ Io = {
var collection = Zotero.getActiveZoteroPane().getSelectedCollection();
this.turndownService = new TurndownService();
this.turndownPluginGfm = TurndownPluginGfmService;
+ this.initmd();
this.currentCollection = "All documents";
if(collection)
{
@@ -11,13 +12,270 @@ Io = {
}
},
+ export(){
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+"."+Zotero.ZeNotes.Prefs.get("export-default-ext", "html");
+ var filters = {
+ "Documents (*.doc)": "*.doc",
+ "Web page, HTML single file (*.html; *.htm)": "*.html; *.htm",
+ "Web page, complete (*.html; *.htm)": "*.html; *.htm",
+ "Markdown, MD single file (*.md; *.MD)": "*.md; *.MD",
+ "Markdown, complete (*.md; *.MD)": "*.md; *.MD",
+ "Markdown, MD with HTML (*.md; *.MD)": "*.md; *.MD",
+ "Markdown, complete, with HTML (*.md; *.MD)": "*.md; *.MD",
+ "Documents (*.xls)": "*.xls",
+ "CSV (*.csv)": "*.csv",
+ }
+
+ for(let idx in filters)
+ {
+ fp.appendFilter(idx, filters[idx]);
+ }
+
+ fp.defaultExtension=Zotero.ZeNotes.Prefs.get("export-default-ext", "html");
+ fp.filterIndex = Zotero.ZeNotes.Prefs.get("export-default-filter-index", 0);
+ fp.init(window, "Save to file", nsIFilePicker.modeSave);
+ fp.open(result=>{
+ if (result == fp.returnOK || result == fp.returnReplace) {
+ let ext = filters[Object.keys(filters)[fp.filterIndex]].split(";")[0].replace("*.", "");
+ var mode1 = "";
+ var mode2 = "";
+ let mode = Object.keys(filters)[fp.filterIndex].replace(/\(.*\)/, "").split(/[\,\(]/);
+
+ if(mode.length==2 && mode[1])
+ {
+ mode1 = mode[1].trim();
+ }
+ else if(mode.length==3 && mode[2])
+ {
+ mode1 = mode[1].trim();
+ mode2 = mode[2].trim();
+ }
+
+ Zotero.ZeNotes.Prefs.set("export-default-ext", ext);
+ Zotero.ZeNotes.Prefs.set("export-default-filter-index", fp.filterIndex);
+ var table = document.getElementById("notes-table");
+
+
+ if(mode1=="complete" || ext.toUpperCase()=="XLS" || ext.toUpperCase()=="CSV")
+ {
+ table = this.createfiles(fp, table, ext);
+ }
+
+ if(fp.file.exists())
+ {
+ fp.file.remove(true);
+ }
+
+ if(ext.toUpperCase()=="MD")
+ {
+ let markdown = "";
+ if(mode1.includes("HTML") || mode2.includes("HTML"))
+ {
+ markdown = Io.turndownServiceFull.turndown(table.outerHTML).replace(/https\:\/\/zotero\//g, "zotero://");
+ }
+ else
+ {
+ markdown = Io.turndownServiceMin.turndown(table.outerHTML).replace(/https\:\/\/zotero\//g, "zotero://");
+ }
+ Zotero.File.putContentsAsync(fp.file, markdown);
+ }
+ else if(ext.toUpperCase()=="HTML")
+ {
+ Zotero.File.putContentsAsync(fp.file, table.outerHTML);
+ }
+ else if(ext.toUpperCase()=="DOC")
+ {
+ var html = table.outerHTML;
+ var style = "";
+
+ html = "
"+style+""+html+""
+ html = html.replace(/(background-color:#.{6})(.{2});\"/g, "$1;\"");
+ Zotero.File.putContentsAsync(fp.file, html);
+ }
+ else if(ext.toUpperCase()=="XLS")
+ {
+ var template = '';
+ var base64 = function(s) {
+ return window.btoa(unescape(encodeURIComponent(s)))
+ }
+ var format = function(s, c) {
+ return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; })
+ }
+ var ctx = {worksheet:"data" || 'Worksheet', table:table.outerHTML};
+ xls = format(template, ctx);
+ Zotero.File.putContentsAsync(fp.file, xls);
+ }
+ else if(ext.toUpperCase()=="CSV")
+ {
+ var rows = table.querySelectorAll('tr');
+ var csv = [];
+ var separator = ",";
+ for (var i = 0; i < rows.length; i++) {
+ var row = [], cols = rows[i].querySelectorAll('td, th');
+ for (var j = 0; j < cols.length; j++) {
+ var data = cols[j].innerText.replace(/(\r\n|\n|\r)/gm, '').replace(/(\s\s)/gm, ' ')
+ data = data.replace(/"/g, '""');
+ row.push('"' + data + '"');
+ }
+ csv.push(row.join(separator));
+ }
+ var csv_string = csv.join('\n');
+ Zotero.File.putContentsAsync(fp.file, csv_string);
+ }
+ }
+ })
+ },
+
+ createfiles(fp, table, fext="MD")
+ {
+ var folder = fp.file.parent.clone();
+ var filename = fp.file.leafName;
+ var foldername = filename.substring(0, filename.lastIndexOf('.'))+"_files";
+ folder.append(foldername);
+ if(!folder.exists())
+ {
+ folder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+ }
+
+ var i = 1;
+ table = table.cloneNode(true);
+ table.querySelectorAll("img").forEach(img=>{
+ let fileparts = img.src.split(',');
+ let ext = fileparts[0].replace("data:image/", "").replace(";base64", "");
+ let base64 = fileparts[1];
+ let filename = foldername+"_"+String(i).padStart(3, '0')+"."+ext;
+ let src = foldername+"/"+filename;
+ let imagefile = folder.clone();
+ imagefile.append(filename);
+ this.savebinary(imagefile, img.src);
+ img.src = src.split(" ").join("%20");
+
+ if(fext.toUpperCase()=="CSV")
+ {
+ let node = document.createTextNode(", image: "+src.split(" ").join("%20")+", ");
+ img.parentNode.insertBefore(node, img);
+ }
+ });
+
+ if(fext.toUpperCase()=="HTML")
+ {
+ var stylefile = folder.clone();
+ stylefile.append("styles.css");
+ this.savebinary(stylefile, "chrome://ze-notes/content/notes/notes.css");
+
+ var html = document.createElement("html");
+ var head = document.createElement("head");
+ var title = document.createElement("title");
+ var body = document.createElement("body");
+ body.style = "width:100%;overflow:auto!important;";
+
+ var style = document.createElement("link");
+ style.href = foldername+"/styles.css";
+ style.rel = "stylesheet";
+ title.innerText = foldername;
+ html.appendChild(head);
+ html.appendChild(body);
+ head.appendChild(title);
+ head.appendChild(style);
+ body.appendChild(table);
+ return html;
+ }
+ return table;
+ },
+
+ initmd()
+ {
+ Io.turndownServiceFull = new TurndownService();
+ Io.turndownPluginGfm.tables(Io.turndownServiceFull);
+
+ Io.turndownServiceFull.keep(['div', 'hr', 'br', 'a', 'img']);
+ Io.turndownServiceFull.addRule('divs', {
+ filter: ['div'],
+ replacement: function (content, node) {
+ if(content.replace(/\s/g, '')){
+ Zotero.warn(node.outerHTML);
+ if(node.style.cssText)
+ {
+ return ""+content+"
";
+ }
+ else
+ {
+ return ""+content+"
";
+ }
+ }
+ else {
+ return "";
+ }
+ }
+ });
+
+ Io.turndownServiceFull.addRule('spans', {
+ filter: ['span'],
+ replacement: function (content, node) {
+ var td = node.closest("td");
+ var annotation = node.closest(".annotation");
+ if(node.className=="quotation-source")
+ {
+ var url = "https://zotero/open-pdf/library/items/"+annotation.dataset.attachmentkey+"?annotation="+annotation.dataset.annotationkey;
+ return "["+node.innerText+"]("+url+")";
+ }
+ else
+ {
+ return node.innerText;
+ }
+ }
+ });
+
+ Io.turndownServiceFull.addRule('hrs', {
+ filter: ['hr'],
+ replacement: function (content, node) {
+ return "---";
+ }
+ });
+
+ Io.turndownServiceMin = new TurndownService();
+ Io.turndownPluginGfm.tables(Io.turndownServiceMin);
+
+ Io.turndownServiceMin.keep(['br']);
+ Io.turndownServiceMin.addRule('links', {
+ filter: ['a'],
+ replacement: function (content, node) {
+ return "["+content+"]("+node.href+")";
+ }
+ });
+
+ Io.turndownServiceMin.addRule('divs', {
+ filter: ['div'],
+ replacement: function (content, node) {
+ if(content.replace(/\s/g, '').replace(/ /g , "")) {
+ return "
"+content+"
";
+ }
+ else
+ {
+ return ""
+ }
+ }
+ });
+
+ Io.turndownServiceMin.addRule('hrs', {
+ filter: ['hr'],
+ replacement: function (content, node) {
+ return "---";
+ }
+ });
+ },
+
download(type, options=[])
{
- if(type=="doc" || type=="html")
+ if(type=="doc" || type=="html" || type=="fullhtml")
{
- var data = document.getElementById("notes-table").outerHTML;
- this.exporthtml(data, type);
+ var table = document.getElementById("notes-table");
+ this.exporthtml(table, type);
}
else if(type=="csv")
{
@@ -36,8 +294,106 @@ Io = {
}
},
- exporthtml(html, type)
+ savebinary(file, url)
+ {
+ fetch(url)
+ .then(res => res.blob())
+ .then(blob=>{
+ Zotero.File.putContentsAsync(file, blob);
+ });
+ },
+
+ fullexport(table, filter, extension, formatter)
+ {
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+"."+extension;
+ fp.appendFilter(...filter);
+ fp.defaultExtension=extension;
+ fp.init(window, "Save to file", nsIFilePicker.modeSave);
+ fp.open(result=>{
+ if (result == fp.returnOK || result == fp.returnReplace) {
+ var folder = fp.file.parent.clone();
+ var filename = fp.file.leafName;
+ var foldername = filename.substring(0, filename.lastIndexOf('.'))+"_files";
+ folder.append(foldername);
+ if(!folder.exists())
+ {
+ folder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+ }
+
+ var i = 1;
+ table = table.cloneNode(true);
+
+ table.querySelectorAll("img").forEach(img=>{
+ let fileparts = img.src.split(',');
+ let ext = fileparts[0].replace("data:image/", "").replace(";base64", "");
+ let base64 = fileparts[1];
+ let filename = foldername+"_"+String(i).padStart(3, '0')+"."+ext;
+ let src = foldername+"/"+filename;
+ let imagefile = folder.clone();
+ imagefile.append(filename);
+ this.savebinary(imagefile, img.src);
+ img.src = src.split(" ").join("%20");
+ });
+
+ if(fp.file.exists())
+ {
+ fp.file.remove(true);
+ }
+ Zotero.File.putContentsAsync(fp.file, formatter(table));
+ }
+ })
+ },
+
+ formathtml(table)
+ {
+ return table.outerHTML;
+ },
+
+ formatmd(table, options)
+ {
+ if(options.includes("html"))
+ {
+ let markdown = Io.turndownServiceFull.turndown(table.outerHTML).replace(/https\:\/\/zotero\//g, "zotero://");
+ return markdown;
+ }
+ else
+ {
+ let markdown = Io.turndownServiceMin.turndown(this.cleantable(table, options)).replace(/https\:\/\/zotero\//g, "zotero://");
+ return markdown;
+ }
+ },
+
+ fullmarkdown(table, options)
+ {
+ this.fullexport(
+ table,
+ ["Markdown (*.md; *.MD)", "*.md; *.MD"],
+ "MD",
+ function(t){return Io.formatmd(t, options)}
+ )
+ },
+
+ fullhtml(table)
+ {
+ this.fullexport(
+ table,
+ ["Web page (*.html; *.htm)", "*.html; *.htm"],
+ "html",
+ this.formathtml
+ )
+ },
+
+ exporthtml(table, type)
{
+ if(type=="fullhtml")
+ {
+ table = Io.fullhtml(table);
+ return;
+ }
+
+ html = table.outerHTML;
var style = "";
@@ -65,6 +421,7 @@ Io = {
html = html.replace(/(background-color:#.{6})(.{2});\"/g, "$1;\"");
}
+
else if(type=="html")
{
fp.defaultString = "ZeNotes - "+Io.currentCollection+".html";
@@ -137,11 +494,11 @@ Io = {
markdown(table, options=[])
{
- Io.turndownPluginGfm.tables(Io.turndownService);
+ Io.turndownPluginGfm.tables(Io.turndownService);
var markdown = "";
if(options.includes("html"))
{
- Io.turndownService.keep(['div', 'hr', 'br', 'a']);
+ Io.turndownService.keep(['div', 'hr', 'br', 'a', 'img']);
Io.turndownService.addRule('divs', {
filter: ['div'],
replacement: function (content, node) {
@@ -165,13 +522,20 @@ Io = {
}
});
}
+
markdown = Io.turndownService.turndown(this.cleantable(table, options)).replace(/https\:\/\/zotero\//g, "zotero://");
- return markdown
+ return markdown
},
exportmarkdown(table, options=[])
- {
- var markdown = this.markdown(table, options)
+ {
+ if(options.includes("full"))
+ {
+ this.fullmarkdown(table, options);
+ return;
+ }
+
+ var markdown = this.markdown(table, options)
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
diff --git a/content/notes/menus.js b/content/notes/menus.js
index 52cda14..c892cd4 100644
--- a/content/notes/menus.js
+++ b/content/notes/menus.js
@@ -187,11 +187,15 @@ Menus = {
Menus.actions(key, options)
},
items: {
- "saveasxls": {name: "Export as xls...", icon: "fa-file-excel"},
- "saveascsv": {name: "Export as csv...", icon: "fa-file-csv"},
- "saveasdoc": {name: "Export as doc...", icon: "fa-file-word"},
- "saveashtml": {name: "Export as html...", icon: "fa-file-code"},
- "saveasmarkdown": {name: "Export as markdown", icon: "fa-markdown", items: {
+ "saveas": {name: "Export as...", icon: "fa-file"},
+ // "saveasxls": {name: "Export as xls...", icon: "fa-file-excel"},
+ // "saveascsv": {name: "Export as csv...", icon: "fa-file-csv"},
+ // "saveasdoc": {name: "Export as doc...", icon: "fa-file-word"},
+ // "saveashtml": {name: "Export as html...", icon: "fa-file-code"},
+ // "saveasfullhtml": {name: "Export as html (complete)", icon: "fa-folder"},
+ // "saveasfullmd": {name: "Export as markdown (complete)", icon: "fa-folder"},
+ // "saveasfullmdhtml": {name: "Export as markdown (complete, with html)", icon: "fa-folder"},
+ "saveasmarkdown": {name: "Export as markdown (legacy)", icon: "fa-markdown", items: {
"saveasmarkdownnoicon": {name: "Simple", icon: "fa-markdown"},
"saveasmarkdown": {name: "With icon", icon: "fa-markdown"},
"sep": "---",
@@ -456,6 +460,10 @@ Menus = {
Find.show();
}
+ else if(key=="saveas" ){
+ Io.export();
+ }
+
else if(key=="saveasxls" ){
Io.download("xls");
}
@@ -468,6 +476,18 @@ Menus = {
Io.download("html");
}
+ else if(key=="saveasfullhtml"){
+ Io.download("fullhtml");
+ }
+
+ else if(key=="saveasfullmdhtml"){
+ Io.download("markdown", ["html", "style", "link-icon", "full"]);
+ }
+
+ else if(key=="saveasfullmd"){
+ Io.download("markdown", ["style", "link-icon", "full"]);
+ }
+
else if(key=="saveasmarkdownnoicon"){
Io.download("markdown", []);
}
diff --git a/content/notes/notes.js b/content/notes/notes.js
index c58342d..a68628f 100644
--- a/content/notes/notes.js
+++ b/content/notes/notes.js
@@ -1,6 +1,7 @@
Notes = {
init() {
var fontsize = Zotero.ZeNotes.Prefs.get("font-size");
+
this.tableutils = Zotero_Preferences.ZNTable;
this.body = document.getElementById("zn-body");
this.infotags = ["id", "key", "title", "date", "journal", "author", "creators", "itemid", "filekey"];
@@ -9,6 +10,7 @@ Notes = {
{
this.body.style.fontSize = fontsize+"px";
}
+ this.fontsize = 1;
},
@@ -347,11 +349,52 @@ Notes = {
Zotero.ZeNotes.Prefs.set("scrolltop", $('#zn-body-wrapper').scrollTop());
Zotero.ZeNotes.Prefs.set("scrollleft", $('#zn-body-wrapper').scrollLeft());
});
+ },
+
+ zoom(sign){
+ this.fontsize = this.fontsize;
+ this.fontsize+=0.05*sign;
+ if(this.fontsize<=0)
+ {
+ this.fontsize = 1;
+ }
+ else if(this.fontsize>10)
+ {
+ this.fontsize = 10;
+ }
+ Notes.body.style.fontSize = this.fontsize+"em";
+ let pxsize = parseFloat(getComputedStyle(Notes.body).fontSize);
+ Zotero.ZeNotes.Prefs.set("font-size", pxsize);
}
+
}
window.addEventListener("load", function(){
Notes.init();
Notes.loaddata();
Notes.initscroll();
+})
+
+document.addEventListener("wheel", function(e){
+ if(e.ctrlKey){
+ let delta = e.deltaY;
+ delta = delta && delta / Math.abs(delta);
+ let sign = delta*-1;
+ Notes.zoom(sign);
+ }
+})
+
+document.addEventListener("keyup", function(e){
+ if(e.ctrlKey){
+ let sign = 1;
+ if(e.keyCode==107)
+ {
+ sign = 1;
+ }
+ else if(e.keyCode==109)
+ {
+ sign=-1;
+ }
+ Notes.zoom(sign);
+ }
})
\ No newline at end of file
diff --git a/content/notes/zotero.js b/content/notes/zotero.js
index 7e876ae..0c1b00f 100644
--- a/content/notes/zotero.js
+++ b/content/notes/zotero.js
@@ -7,6 +7,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
Services: "resource://gre/modules/Services.jsm",
setTimeout: "resource://gre/modules/Timer.jsm",
+ FileUtils: "resource://gre/modules/FileUtils.jsm"
});
// Zotero.Utilities.Internal.openPreferences('zotero-prefpane-advanced');
diff --git a/core/format.js b/core/format.js
index c1d079e..07e5194 100644
--- a/core/format.js
+++ b/core/format.js
@@ -236,7 +236,11 @@ Format = {
comment = comment.split("\n").join("
\n");
- var contents = "‟"+annotationtext+"” ("+Format.creatorshort(item)+" "+Format.year(item)+", p. "+note["annotationPageLabel"]+")";
+ // var url = "zotero://open-pdf/library/items/"+note["parentItem"].key+"?annotation="+note["key"];
+ var ref = Format.creatorshort(item)+" "+Format.year(item)+", p. "+note["annotationPageLabel"];
+ // ref = ""+ref+"";
+
+ var contents = "‟"+annotationtext+"” ("+ref+")";
var img = "";
if(note.annotationType=="image")
@@ -248,7 +252,7 @@ Format = {
}
var img = "";
- var contents = annotationtext+"
Source: "+Format.creatorshort(item)+" "+Format.year(item)+", p. "+note["annotationPageLabel"]+"";
+ var contents = annotationtext+"
Source: "+ref+"";
}
var annotationpage = JSON.parse(note["annotationPosition"])["pageIndex"];
diff --git a/install.rdf b/install.rdf
index c03738f..036c8a5 100644
--- a/install.rdf
+++ b/install.rdf
@@ -5,7 +5,7 @@
zenotes@alefa.net
ZeNotes
- 0.7.8
+ 0.7.9
true
https://raw.githubusercontent.com/frianasoa/zenotes/main/zenote-update.json
https://github.com/frianasoa/zenotes
diff --git a/manifest.json b/manifest.json
index 0151b26..b36d45e 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Ze Notes",
- "version": "0.7.8",
+ "version": "0.7.9",
"description": "Advanced notes manager",
"homepage_url": "https://github.com/frianasoa/zenotes",
"author": "Fanantenana Rianasoa Andriariniaina",
diff --git a/zenote-update.json b/zenote-update.json
index 1b7ce37..2a510ba 100644
--- a/zenote-update.json
+++ b/zenote-update.json
@@ -3,9 +3,9 @@
"zenotes@alefa.net": {
"updates": [
{
- "version": "0.7.8",
- "update_link": "https://github.com/frianasoa/Ze-Notes/releases/download/v0.7.8/zenotes-v0.7.8.xpi",
- "update_hash": "sha256:2d45d794a0b648399351af95f6990342d3c5ebb78188462a5880c8bc431215e2",
+ "version": "0.7.9",
+ "update_link": "https://github.com/frianasoa/Ze-Notes/releases/download/v0.7.9/zenotes-v0.7.9.xpi",
+ "update_hash": "sha256:67fda1e59dfad8c3bed4f17c9193685f57f12ae942d5159d28a69461d70ced2e",
"applications": {
"gecko": {
"strict_min_version": "60.0"
diff --git a/zenote-update.rdf b/zenote-update.rdf
index b870d85..752de07 100644
--- a/zenote-update.rdf
+++ b/zenote-update.rdf
@@ -5,13 +5,13 @@
- 0.7.8
+ 0.7.9
zotero@chnm.gmu.edu
5.0.0
6.*
- https://github.com/frianasoa/Ze-Notes/releases/download/v0.7.8/zenotes-v0.7.8.xpi
+ https://github.com/frianasoa/Ze-Notes/releases/download/v0.7.9/zenotes-v0.7.9.xpi
@@ -20,7 +20,7 @@
juris-m@juris-m.github.io
4.999
6.*
- https://github.com/frianasoa/Ze-Notes/releases/download/v0.7.8/zenotes-v0.7.8.xpi
+ https://github.com/frianasoa/Ze-Notes/releases/download/v0.7.9/zenotes-v0.7.9.xpi