diff --git a/bootstrap.js b/bootstrap.js
index 3d15aa2..7886902 100644
--- a/bootstrap.js
+++ b/bootstrap.js
@@ -180,6 +180,7 @@ async function install() {
async function startup({ id, version, resourceURI, rootURI = resourceURI.spec }) {
await waitForZotero();
+
log("Starting Ze-Notes");
initPreferences(rootURI);
@@ -222,6 +223,7 @@ async function startup({ id, version, resourceURI, rootURI = resourceURI.spec })
Services.scriptloader.loadSubScript(rootURI + 'core/languages.js');
Services.scriptloader.loadSubScript(rootURI + 'lib/CryptoJS 3.1.2/aes.js');
+
ZeNotes.init({ id, version, rootURI });
Zotero.ZeNotes = ZeNotes;
ZeNotes.addToAllWindows();
diff --git a/content/notes/format.js b/content/notes/format.js
new file mode 100644
index 0000000..ba842b7
--- /dev/null
+++ b/content/notes/format.js
@@ -0,0 +1,262 @@
+Format = {
+ init()
+ {
+ this.turndownService = new TurndownService();
+ this.turndownPluginGfm = TurndownPluginGfmService;
+ this.initturndown();
+ },
+
+ initturndown()
+ {
+ this.turndownServiceFull = new TurndownService();
+ this.turndownPluginGfm.tables(this.turndownServiceFull);
+
+ this.turndownServiceFull.keep(['div', 'hr', 'br', 'a', 'img']);
+ this.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 "";
+ }
+ }
+ });
+
+ this.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;
+ }
+ }
+ });
+
+ this.turndownServiceFull.addRule('hrs', {
+ filter: ['hr'],
+ replacement: function (content, node) {
+ return "---";
+ }
+ });
+
+ this.turndownServiceMin = new TurndownService();
+ this.turndownPluginGfm.tables(this.turndownServiceMin);
+
+ this.turndownServiceMin.keep(['br']);
+ this.turndownServiceMin.addRule('links', {
+ filter: ['a'],
+ replacement: function (content, node) {
+ return "["+content+"]("+node.href+")";
+ }
+ });
+
+ this.turndownServiceMin.addRule('divs', {
+ filter: ['div'],
+ replacement: function (content, node) {
+ if(content.replace(/\s/g, '').replace(/ /g , "")) {
+ return "
"+content+"
";
+ }
+ else
+ {
+ return ""
+ }
+ }
+ });
+
+ this.turndownServiceMin.addRule('hrs', {
+ filter: ['hr'],
+ replacement: function (content, node) {
+ return "---";
+ }
+ });
+ },
+
+ async process(table, typedesc, foldername, callback)
+ {
+ var contents = "";
+
+ if(Zotero.ZeNotes.Prefs.get("notes-add-links", false)==true)
+ {
+ this.addlink(table);
+ }
+
+ if(typedesc.includes("CSV"))
+ {
+ contents = this.csv(table);
+ }
+ else if(typedesc.includes("Document"))
+ {
+ contents = this.doc(table);
+ }
+ else if(typedesc.includes("Excel"))
+ {
+ contents = this.xls(table, foldername, callback);
+ }
+ else if(typedesc.includes("Web page"))
+ {
+ if(typedesc.includes("single file"))
+ {
+ contents = this.html(table);
+ }
+ else if(typedesc.includes("complete"))
+ {
+ contents = this.html(table, foldername, callback);
+ }
+ }
+ else if(typedesc.includes("Markdown"))
+ {
+ if(typedesc.includes("single file"))
+ {
+ contents = this.md(table);
+ }
+ else if(typedesc.includes("complete, with HTML"))
+ {
+ contents = this.md(table, html, foldername, callback);
+ }
+ else if(typedesc.includes("complete"))
+ {
+ contents = this.md(table, false, foldername, callback);
+ }
+ else if(typedesc.includes("with HTML"))
+ {
+ contents = this.md(table, true);
+ }
+ }
+ return contents;
+ },
+
+ csv(table, separator=",")
+ {
+ var rows = table.querySelectorAll('tr');
+ var csv = [];
+ 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));
+ }
+ return csv.join('\n');
+ },
+
+ xls(table, foldername, callback)
+ {
+ var template = '';
+ var format = function(s, c)
+ {
+ return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; });
+ }
+
+ // Execute callback: normally assets creation
+ if(callback)
+ {
+ var files = this.splitassets(table, foldername);
+ callback(files);
+ }
+
+ var ctx = {worksheet:"data" || 'Worksheet', table:table.outerHTML};
+ contents = format(template, ctx);
+ return contents;
+ },
+
+ doc(table)
+ {
+ var html = table.outerHTML;
+ var style = "";
+
+ contents = ""+style+""+html+""
+ contents = contents.replace(/(background-color:#.{6})(.{2});\"/g, "$1;\"");
+ return contents;
+ },
+
+ html(table, foldername=null, callback=null)
+ {
+ table.style = "width: 100%; border-spacing:0;";
+ table.querySelectorAll('td').forEach(td=>{
+ td.style = "border: solid 1px; padding: 0.3em;";
+ });
+
+ table.querySelectorAll('hr').forEach(hr=>{
+ hr.style = "border solid 1px #efefef; width: 75%;";
+ });
+
+ // Execute callback: normally assets creation
+ if(callback)
+ {
+ var files = this.splitassets(table, foldername);
+ callback(files);
+ }
+ contents = table.outerHTML;
+ return contents;
+ },
+
+ md(table, html=false, foldername=null, callback=null)
+ {
+ if(callback)
+ {
+ var files = this.splitassets(table, foldername);
+ callback(files);
+ }
+ if(html)
+ {
+ contents = this.turndownServiceFull.turndown(table.outerHTML).replace(/https\:\/\/zotero\//g, "zotero://");
+ }
+ else
+ {
+ contents = this.turndownServiceMin.turndown(table.outerHTML).replace(/https\:\/\/zotero\//g, "zotero://");
+ }
+ return contents;
+ },
+
+ addlink(table)
+ {
+ table.querySelectorAll('.quotation-source').forEach(annotation=>{
+ var div = annotation.closest("div.annotation");
+ var lnk = document.createElement("a");
+ lnk.innerHTML = "🔗";
+ lnk.href= "zotero://open-pdf/library/items/"+div.dataset.attachmentkey+"?annotation="+div.dataset.annotationkey;
+ annotation.appendChild(lnk);
+ });
+ },
+
+ splitassets(table, foldername)
+ {
+ var imgs = table.querySelectorAll('img');
+ var i = 1;
+ var files = [];
+ for(img of imgs)
+ {
+ let ext = img.src.split(',')[0].replace("data:image/", "").replace(";base64", "");
+ let filename = "image_"+String(i).padStart(3, '0')+"."+ext;
+ files.push({filename: filename, data: img.src});
+ img.src = "./"+(foldername+"/"+filename).split(" ").join("%20");
+ i++;
+ }
+ return files;
+ }
+}
+
+window.addEventListener("load", function(e){
+ Format.init();
+})
\ No newline at end of file
diff --git a/content/notes/io.js b/content/notes/io.js
index a17b571..db7e7b9 100644
--- a/content/notes/io.js
+++ b/content/notes/io.js
@@ -1,299 +1,72 @@
+var { OS } = ChromeUtils.importESModule("chrome://zotero/content/osfile.mjs");
+var { FilePicker } = ChromeUtils.importESModule('chrome://zotero/content/modules/filePicker.mjs');
+
Io = {
+ filters:{
+ "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",
+ "CSV (*.csv)": "*.csv",
+ "Document (*.doc)": "*.doc",
+ "Excel workbook (*.xls)": "*.xls",
+ },
+
init()
{
+ this.currentCollection = "All documents";
var collection = Zotero.getActiveZoteroPane().getSelectedCollection();
- this.turndownService = new TurndownService();
- this.turndownPluginGfm = TurndownPluginGfmService;
- this.initmd();
- this.currentCollection = "All documents";
if(collection)
{
this.currentCollection = collection.name;
}
},
- 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",
- }
+ async export()
+ {
+ this.init();
+ var title = "Export as ... ";
+ var fp = new FilePicker();
- for(let idx in filters)
- {
- fp.appendFilter(idx, filters[idx]);
- }
+ fp.init(window, title, fp.modeSave);
- 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())
+ fp.defaultExtension = Zotero.ZeNotes.Prefs.get("export-default-ext", "html");
+
+ for(let idx in this.filters)
{
- folder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+ fp.appendFilter(idx, this.filters[idx]);
}
- 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");
+ fp.defaultString = "ZeNotes - "+Io.currentCollection;
+
+ var rv = await fp.show();
+ if(rv == fp.returnOK || rv == fp.returnReplace)
+ {
+ var typedesc = Object.keys(this.filters)[fp.filterIndex];
+ var table = document.getElementById("notes-table").cloneNode(true);
- if(fext.toUpperCase()=="CSV")
+ var parts = fp.file.split(".");
+ let outputFile = fp.file;
+ if(parts.length>1)
{
- let node = document.createTextNode(", image: "+src.split(" ").join("%20")+", ");
- img.parentNode.insertBefore(node, img);
+ parts.pop();
}
- });
-
- if(fext.toUpperCase()=="HTML")
- {
- var stylefile = folder.clone();
- stylefile.append("styles.css");
- this.savebinary(stylefile, "chrome://ze-notes/content/notes/notes.css");
+ var directory = parts.join(".");
+ var dir_comp = OS.Path.split(directory).components;
+ var foldername = dir_comp[dir_comp.length-1];
+ var contents = await Format.process(table, typedesc, foldername, function(files){
+ Io.assets(directory, files);
+ });
- 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;";
+ Zotero.File.putContentsAsync(outputFile, contents);
- 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;
+ Zotero.ZeNotes.Prefs.set("export-default-filter-index", fp.filterIndex);
+ Zotero.ZeNotes.Prefs.set("export-default-ext", fp.defaultExtension);
}
- 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" || type=="fullhtml")
- {
- var table = document.getElementById("notes-table");
- this.exporthtml(table, type);
- }
- else if(type=="csv")
- {
- var table = document.getElementById("notes-table");
- this.exportcsv(table);
- }
- else if(type=="markdown")
- {
- var table = document.getElementById("notes-table");
- this.exportmarkdown(table, options);
- }
- else
- {
- var data = document.getElementById("notes-table").outerHTML;
- this.exportxls(data);
- }
- },
-
savebinary(file, url)
{
fetch(url)
@@ -302,334 +75,18 @@ Io = {
Zotero.File.putContentsAsync(file, blob);
});
},
-
- fullexport(table, filter, extension, formatter)
+ assets(directory, files)
{
- 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);
+ Zotero.File.createDirectoryIfMissingAsync(directory).then(()=>{
+ files.forEach(file=>{
+ try {
+ Io.savebinary(OS.Path.join(directory, file.filename), file.data);
}
-
- 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())
+ catch(e)
{
- fp.file.remove(true);
+ alert(e);
}
- 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 = "";
-
- html = ""+style+""+html+""
-
- var nsIFilePicker = Components.interfaces.nsIFilePicker;
- var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
-
- /**
- Parent window
- window
- */
-
- fp.init(window, "Save to file", nsIFilePicker.modeSave);
- if(type=="doc")
- {
- fp.defaultString = "ZeNotes - "+Io.currentCollection+".doc";
- fp.appendFilter("Documents (*.doc)", "*.doc");
- fp.defaultExtension="doc";
-
- /**
- clean HTML
- */
- html = html.replace(/(background-color:#.{6})(.{2});\"/g, "$1;\"");
-
- }
-
- else if(type=="html")
- {
- fp.defaultString = "ZeNotes - "+Io.currentCollection+".html";
- fp.appendFilter("Web page (*.html; *.htm)", "*.html; *.htm");
- fp.defaultExtension="html";
- }
-
- fp.open(function()
- {
- var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
- outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
- var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
- converter.init(outputStream, "UTF-8", 0, 0);
- converter.writeString(html);
- converter.close();
- outputStream.close();
- });
- },
-
- cleantable(table, options=[])
- {
- var newtable = table.cloneNode(true);
- var children = newtable.querySelectorAll("td");
- children.forEach(td=>{
- var data = "";
- td.childNodes.forEach(c=>{
- var value = "";
- if(c.innerText!=undefined)
- {
- if(c.tagName=="DIV")
- {
- if(options.includes("style"))
- {
- if(options.includes("link-icon"))
- {
- value = "
";
- }
- else
- {
- value = "
";
- }
- }
- else
- {
- if(options.includes("link-icon"))
- {
- value = "
";
- }
- else
- {
- value = "
";
- }
- }
- }
- else
- {
- value = c.innerText;
- }
- }
- else if(c.textContent!=undefined)
- {
- value = c.textContent;
- }
- data+=value;
- });
- td.innerHTML = data;
- });
- return newtable;
- },
-
- markdown(table, options=[])
- {
- Io.turndownPluginGfm.tables(Io.turndownService);
- var markdown = "";
- if(options.includes("html"))
- {
- Io.turndownService.keep(['div', 'hr', 'br', 'a', 'img']);
- Io.turndownService.addRule('divs', {
- filter: ['div'],
- replacement: function (content, node) {
- return ""+content+"
";
- }
- });
- }
- else
- {
- Io.turndownService.keep(['br']);
- Io.turndownService.addRule('links', {
- filter: ['a'],
- replacement: function (content, node) {
- return "["+content+"]("+node.href+")";
- }
- });
- Io.turndownService.addRule('divs', {
- filter: ['div', 'hr'],
- replacement: function (content, node) {
- return "
**"+content+"**
";
- }
- });
- }
-
- markdown = Io.turndownService.turndown(this.cleantable(table, options)).replace(/https\:\/\/zotero\//g, "zotero://");
- return markdown
- },
-
- exportmarkdown(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);
-
- fp.defaultString = "ZeNotes - "+Io.currentCollection+".md";
- fp.init(window, "Save to file", nsIFilePicker.modeSave);
- fp.appendFilter("Markdown (*.md; *.MD)", "*.md; *.MD");
- fp.defaultExtension="MD";
-
- fp.open(function()
- {
- var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
- outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
- var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
- converter.init(outputStream, "UTF-8", 0, 0);
- converter.writeString(markdown);
- converter.close();
- outputStream.close();
- });
- },
-
- exportcsv(table)
- {
- 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');
-
- var nsIFilePicker = Components.interfaces.nsIFilePicker;
- var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
-
- fp.defaultString = "ZeNotes - "+Io.currentCollection+".csv";
- fp.init(window, "Save to file", nsIFilePicker.modeSave);
- fp.appendFilter("CSV (*.csv; *.txt)", "*.csv; *.txt");
- fp.defaultExtension="csv";
-
- fp.open(function()
- {
- var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
- outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
- var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
- converter.init(outputStream, "UTF-8", 0, 0);
- converter.writeString(csv_string);
- converter.close();
- outputStream.close();
- });
-
- },
-
- exportxls(xls)
- {
- var uri = 'data:application/vnd.ms-excel;base64,';
- 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: xls}
- // xls = base64(format(template, ctx))
- xls = format(template, ctx)
-
- var nsIFilePicker = Components.interfaces.nsIFilePicker;
- var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
-
- fp.defaultString = "ZeNotes - "+Io.currentCollection+".xls";
- fp.init(window, "Save to file", nsIFilePicker.modeSave);
- fp.appendFilter("Documents (*.xls)", "*.xls");
- fp.appendFilter("Web page (*.csv)", "*.csv");
- fp.defaultExtension="xls";
-
-
- fp.open(function()
- {
- var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
- outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
- var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
- converter.init(outputStream, "UTF-8", 0, 0);
- converter.writeString(xls);
- converter.close();
- outputStream.close();
- });
- }
-}
-
-window.addEventListener("load", function(){
- Io.init();
-})
\ No newline at end of file
+ });
+ });
+ }
+}
\ No newline at end of file
diff --git a/content/notes/io6.js b/content/notes/io6.js
new file mode 100644
index 0000000..052b03d
--- /dev/null
+++ b/content/notes/io6.js
@@ -0,0 +1,634 @@
+Io = {
+ init()
+ {
+ var collection = Zotero.getActiveZoteroPane().getSelectedCollection();
+ this.turndownService = new TurndownService();
+ this.turndownPluginGfm = TurndownPluginGfmService;
+ this.initmd();
+ this.currentCollection = "All documents";
+ if(collection)
+ {
+ this.currentCollection = collection.name;
+ }
+ },
+
+ 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" || type=="fullhtml")
+ {
+ var table = document.getElementById("notes-table");
+ this.exporthtml(table, type);
+ }
+ else if(type=="csv")
+ {
+ var table = document.getElementById("notes-table");
+ this.exportcsv(table);
+ }
+ else if(type=="markdown")
+ {
+ var table = document.getElementById("notes-table");
+ this.exportmarkdown(table, options);
+ }
+ else
+ {
+ var data = document.getElementById("notes-table").outerHTML;
+ this.exportxls(data);
+ }
+ },
+
+ 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 = "";
+
+ html = ""+style+""+html+""
+
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+
+ /**
+ Parent window
+ window
+ */
+
+ fp.init(window, "Save to file", nsIFilePicker.modeSave);
+ if(type=="doc")
+ {
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+".doc";
+ fp.appendFilter("Documents (*.doc)", "*.doc");
+ fp.defaultExtension="doc";
+
+ /**
+ clean HTML
+ */
+ html = html.replace(/(background-color:#.{6})(.{2});\"/g, "$1;\"");
+
+ }
+
+ else if(type=="html")
+ {
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+".html";
+ fp.appendFilter("Web page (*.html; *.htm)", "*.html; *.htm");
+ fp.defaultExtension="html";
+ }
+
+ fp.open(function()
+ {
+ var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
+ outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(outputStream, "UTF-8", 0, 0);
+ converter.writeString(html);
+ converter.close();
+ outputStream.close();
+ });
+ },
+
+ cleantable(table, options=[])
+ {
+ var newtable = table.cloneNode(true);
+ var children = newtable.querySelectorAll("td");
+ children.forEach(td=>{
+ var data = "";
+ td.childNodes.forEach(c=>{
+ var value = "";
+ if(c.innerText!=undefined)
+ {
+ if(c.tagName=="DIV")
+ {
+ if(options.includes("style"))
+ {
+ if(options.includes("link-icon"))
+ {
+ value = "
";
+ }
+ else
+ {
+ value = "
";
+ }
+ }
+ else
+ {
+ if(options.includes("link-icon"))
+ {
+ value = "
";
+ }
+ else
+ {
+ value = "
";
+ }
+ }
+ }
+ else
+ {
+ value = c.innerText;
+ }
+ }
+ else if(c.textContent!=undefined)
+ {
+ value = c.textContent;
+ }
+ data+=value;
+ });
+ td.innerHTML = data;
+ });
+ return newtable;
+ },
+
+ markdown(table, options=[])
+ {
+ Io.turndownPluginGfm.tables(Io.turndownService);
+ var markdown = "";
+ if(options.includes("html"))
+ {
+ Io.turndownService.keep(['div', 'hr', 'br', 'a', 'img']);
+ Io.turndownService.addRule('divs', {
+ filter: ['div'],
+ replacement: function (content, node) {
+ return ""+content+"
";
+ }
+ });
+ }
+ else
+ {
+ Io.turndownService.keep(['br']);
+ Io.turndownService.addRule('links', {
+ filter: ['a'],
+ replacement: function (content, node) {
+ return "["+content+"]("+node.href+")";
+ }
+ });
+ Io.turndownService.addRule('divs', {
+ filter: ['div', 'hr'],
+ replacement: function (content, node) {
+ return "
**"+content+"**
";
+ }
+ });
+ }
+
+ markdown = Io.turndownService.turndown(this.cleantable(table, options)).replace(/https\:\/\/zotero\//g, "zotero://");
+ return markdown
+ },
+
+ exportmarkdown(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);
+
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+".md";
+ fp.init(window, "Save to file", nsIFilePicker.modeSave);
+ fp.appendFilter("Markdown (*.md; *.MD)", "*.md; *.MD");
+ fp.defaultExtension="MD";
+
+ fp.open(function()
+ {
+ var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
+ outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(outputStream, "UTF-8", 0, 0);
+ converter.writeString(markdown);
+ converter.close();
+ outputStream.close();
+ });
+ },
+
+ exportcsv(table)
+ {
+ 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');
+
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+".csv";
+ fp.init(window, "Save to file", nsIFilePicker.modeSave);
+ fp.appendFilter("CSV (*.csv; *.txt)", "*.csv; *.txt");
+ fp.defaultExtension="csv";
+
+ fp.open(function()
+ {
+ var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
+ outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0 );
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(outputStream, "UTF-8", 0, 0);
+ converter.writeString(csv_string);
+ converter.close();
+ outputStream.close();
+ });
+
+ },
+
+ exportxls(xls)
+ {
+ var uri = 'data:application/vnd.ms-excel;base64,';
+ 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: xls}
+ // xls = base64(format(template, ctx))
+ xls = format(template, ctx)
+
+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
+ var fp =Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+
+ fp.defaultString = "ZeNotes - "+Io.currentCollection+".xls";
+ fp.init(window, "Save to file", nsIFilePicker.modeSave);
+ fp.appendFilter("Documents (*.xls)", "*.xls");
+ fp.appendFilter("Web page (*.csv)", "*.csv");
+ fp.defaultExtension="xls";
+
+ fp.open(function()
+ {
+ var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance( Components.interfaces.nsIFileOutputStream);
+ outputStream.init(fp.file, 0x04 | 0x08 | 0x20, 420, 0);
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(outputStream, "UTF-8", 0, 0);
+ converter.writeString(xls);
+ converter.close();
+ outputStream.close();
+ });
+ }
+}
+
+window.addEventListener("load", function(){
+ Io.init();
+})
\ No newline at end of file
diff --git a/content/notes/loader.js b/content/notes/loader.js
new file mode 100644
index 0000000..42a5c5f
--- /dev/null
+++ b/content/notes/loader.js
@@ -0,0 +1,31 @@
+Loader = {
+ start()
+ {
+ if (Zotero.platformMajorVersion < 102)
+ {
+ this.load("io6.js", "Io");
+ }
+ else
+ {
+ this.load("format.js", "Format");
+ this.load("io.js");
+ }
+ },
+
+ load(url, object=null)
+ {
+ const script = document.createElement('script');
+ script.src = url;
+ if(object)
+ {
+ script.onload = () => {
+ window[object].init();
+ };
+ }
+ document.head.appendChild(script);
+ }
+}
+
+window.addEventListener("load", function(){
+ Loader.start();
+})
\ No newline at end of file
diff --git a/content/notes/notes.xhtml b/content/notes/notes.xhtml
index e722e7f..11fc240 100644
--- a/content/notes/notes.xhtml
+++ b/content/notes/notes.xhtml
@@ -9,6 +9,7 @@
+
@@ -19,7 +20,7 @@
-
+
diff --git a/content/settings/export.xhtml b/content/settings/export.xhtml
new file mode 100644
index 0000000..eb45a0d
--- /dev/null
+++ b/content/settings/export.xhtml
@@ -0,0 +1,5 @@
+
diff --git a/content/settings/preferences.js b/content/settings/preferences.js
index 9c05299..f44802c 100644
--- a/content/settings/preferences.js
+++ b/content/settings/preferences.js
@@ -303,6 +303,11 @@ Zotero_Preferences.ZeNotes = {
["paraphrase-custom-prompt", "zn-paraphrase-custom-prompt"]
];
break;
+ case 'export':
+ args = [
+ ["notes-add-links", "zn-notes-add-links"]
+ ];
+ break;
case 'performance':
args = [
["load-on-change", "zn-reload-on-change"],
diff --git a/content/settings/preferences.xhtml b/content/settings/preferences.xhtml
index fd5999e..b4c06a1 100644
--- a/content/settings/preferences.xhtml
+++ b/content/settings/preferences.xhtml
@@ -45,6 +45,11 @@
+
+