change: export md
fix: reader note editor not initialized add: export md with citation wrapped fix: MDFileName template bug
This commit is contained in:
parent
d55d03edb8
commit
fa193ad963
File diff suppressed because it is too large
Load Diff
|
|
@ -32,11 +32,15 @@
|
|||
"compressing": "^1.5.1",
|
||||
"esbuild": "^0.14.34",
|
||||
"replace-in-file": "^6.3.2",
|
||||
"tree-model": "^1.0.7"
|
||||
"seedrandom": "^3.0.5",
|
||||
"tree-model": "^1.0.7",
|
||||
"turndown": "^7.1.1",
|
||||
"turndown-plugin-gfm": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jquery": "^3.5.14",
|
||||
"@types/node": "^17.0.31",
|
||||
"@types/turndown": "^5.0.1",
|
||||
"release-it": "^14.14.0",
|
||||
"zotero-types": "^0.0.4"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class AddonEvents extends AddonBase {
|
|||
t < 100
|
||||
) {
|
||||
t += 1;
|
||||
this._Addon.knowledge.setWorkspaceNote();
|
||||
this._Addon.knowledge.setWorkspaceNote("main", undefined, false);
|
||||
await Zotero.Promise.delay(100);
|
||||
}
|
||||
|
||||
|
|
@ -500,15 +500,15 @@ class AddonEvents extends AddonBase {
|
|||
editor._knowledgeUIInitialized = false;
|
||||
|
||||
const currentID = editor._item.id;
|
||||
const noteItem = editor._item;
|
||||
// item.getNote may not be initialized yet
|
||||
if (Zotero.ItemTypes.getID("note") !== noteItem.itemTypeID) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a window for print
|
||||
const isPrint = this._Addon.knowledge._pdfNoteId === currentID;
|
||||
|
||||
const noteItem = Zotero.Items.get(currentID) as Zotero.Item;
|
||||
if (!noteItem.isNote()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mainNoteID = parseInt(
|
||||
Zotero.Prefs.get("Knowledge4Zotero.mainKnowledgeID") as string
|
||||
);
|
||||
|
|
@ -1843,6 +1843,9 @@ class AddonEvents extends AddonBase {
|
|||
await io.deferred.promise;
|
||||
|
||||
const options = io.dataOut as any;
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
if (options.exportFile && options.exportSingleFile) {
|
||||
await this._Addon.knowledge.exportNotesToFile(
|
||||
[item],
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
const TRANSLATOR_ID_BETTER_MARKDOWN = "1412e9e2-51e1-42ec-aa35-e036a895534c";
|
||||
|
||||
const configs = {};
|
||||
|
||||
configs[TRANSLATOR_ID_BETTER_MARKDOWN] = {
|
||||
translatorID: TRANSLATOR_ID_BETTER_MARKDOWN,
|
||||
label: "Better Note Markdown",
|
||||
creator: "Martynas Bagdonas; Winding",
|
||||
target: "md",
|
||||
minVersion: "5.0.97",
|
||||
maxVersion: "",
|
||||
priority: 50,
|
||||
configOptions: {
|
||||
noteTranslator: true,
|
||||
},
|
||||
displayOptions: {
|
||||
includeAppLinks: true,
|
||||
},
|
||||
inRepository: true,
|
||||
translatorType: 2,
|
||||
lastUpdated: "2022-06-01 23:26:46",
|
||||
_codePath:
|
||||
"chrome://Knowledge4Zotero/content/translators/Better Note Markdown.js",
|
||||
};
|
||||
|
||||
async function loadTranslator(id) {
|
||||
const config = configs[id];
|
||||
const code = (await Zotero.File.getContentsAsync(config._codePath)).response;
|
||||
Zotero.debug(code);
|
||||
await Zotero.Translators.save(config, code);
|
||||
await Zotero.Translators.reinit();
|
||||
}
|
||||
|
||||
export { TRANSLATOR_ID_BETTER_MARKDOWN, loadTranslator };
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import Knowledge4Zotero from "./addon";
|
||||
import { OutlineType } from "./base";
|
||||
import { loadTranslator, TRANSLATOR_ID_BETTER_MARKDOWN } from "./exportMD";
|
||||
import { pick } from "./file_picker";
|
||||
import AddonBase from "./module";
|
||||
|
||||
|
|
@ -15,7 +14,6 @@ class Knowledge extends AddonBase {
|
|||
_workspacePromise: any;
|
||||
_exportPath: string;
|
||||
_exportFileDict: object;
|
||||
_exportPromise: any;
|
||||
_pdfNoteId: number;
|
||||
_pdfPrintPromise: any;
|
||||
constructor(parent: Knowledge4Zotero) {
|
||||
|
|
@ -191,7 +189,8 @@ class Knowledge extends AddonBase {
|
|||
|
||||
async setWorkspaceNote(
|
||||
type: "main" | "preview" = "main",
|
||||
note: Zotero.Item | undefined = undefined
|
||||
note: Zotero.Item | undefined = undefined,
|
||||
showPopup: boolean = true
|
||||
) {
|
||||
let _window = this.getWorkspaceWindow() as Window;
|
||||
note = note || this.getWorkspaceNote();
|
||||
|
|
@ -273,10 +272,12 @@ class Knowledge extends AddonBase {
|
|||
.filter((id) => id)
|
||||
.join(",")
|
||||
);
|
||||
this._Addon.views.showProgressWindow(
|
||||
"Better Notes",
|
||||
`Set main Note to: ${note.getNoteTitle()}`
|
||||
);
|
||||
if (showPopup) {
|
||||
this._Addon.views.showProgressWindow(
|
||||
"Better Notes",
|
||||
`Set main Note to: ${note.getNoteTitle()}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -786,12 +787,12 @@ class Knowledge extends AddonBase {
|
|||
async exportNoteToFile(
|
||||
note: Zotero.Item,
|
||||
convertNoteLinks: boolean = true,
|
||||
saveFile: boolean = true,
|
||||
saveMD: boolean = true,
|
||||
saveNote: boolean = false,
|
||||
saveCopy: boolean = false,
|
||||
doCopy: boolean = false,
|
||||
savePDF: boolean = false
|
||||
) {
|
||||
if (!saveFile && !saveNote && !saveCopy && !savePDF) {
|
||||
if (!saveMD && !saveNote && !doCopy && !savePDF) {
|
||||
return;
|
||||
}
|
||||
this._exportFileDict = [];
|
||||
|
|
@ -822,9 +823,7 @@ class Knowledge extends AddonBase {
|
|||
newNote = note;
|
||||
}
|
||||
|
||||
if (saveFile) {
|
||||
await loadTranslator(TRANSLATOR_ID_BETTER_MARKDOWN);
|
||||
|
||||
if (saveMD) {
|
||||
const filename = await pick(
|
||||
Zotero.getString("fileInterface.export"),
|
||||
"save",
|
||||
|
|
@ -836,30 +835,10 @@ class Knowledge extends AddonBase {
|
|||
Zotero.File.pathToFile(filename).parent.path + "/attachments";
|
||||
// Convert to unix format
|
||||
this._exportPath = this._exportPath.replace(/\\/g, "/");
|
||||
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
const hasImage = newNote.getNote().includes("<img");
|
||||
if (hasImage) {
|
||||
await Zotero.File.createDirectoryIfMissingAsync(
|
||||
OS.Path.join(...this._exportPath.split(/\//))
|
||||
);
|
||||
}
|
||||
|
||||
const translator = new Zotero.Translate.Export();
|
||||
translator.setItems([newNote]);
|
||||
translator.setLocation(Zotero.File.pathToFile(filename));
|
||||
this._exportPromise = Zotero.Promise.defer();
|
||||
translator.setTranslator(TRANSLATOR_ID_BETTER_MARKDOWN);
|
||||
translator.translate();
|
||||
await this._exportPromise.promise;
|
||||
this._Addon.views.showProgressWindow(
|
||||
"Better Notes",
|
||||
`Note Saved to ${filename}`
|
||||
);
|
||||
await this._export(newNote, filename, false);
|
||||
}
|
||||
}
|
||||
if (saveCopy) {
|
||||
if (doCopy) {
|
||||
if (!convertNoteLinks) {
|
||||
Zotero_File_Interface.exportItemsToClipboard(
|
||||
[newNote],
|
||||
|
|
@ -944,8 +923,6 @@ class Knowledge extends AddonBase {
|
|||
return;
|
||||
}
|
||||
|
||||
await loadTranslator(TRANSLATOR_ID_BETTER_MARKDOWN);
|
||||
|
||||
this._exportPath = Zotero.File.pathToFile(filepath).path + "/attachments";
|
||||
// Convert to unix format
|
||||
this._exportPath = this._exportPath.replace(/\\/g, "/");
|
||||
|
|
@ -1007,7 +984,6 @@ class Knowledge extends AddonBase {
|
|||
allNoteIds = allNoteIds.concat(subNoteIds);
|
||||
}
|
||||
allNoteIds = Array.from(new Set(allNoteIds));
|
||||
console.log(allNoteIds);
|
||||
const allNoteItems: Zotero.Item[] = Zotero.Items.get(
|
||||
allNoteIds
|
||||
) as Zotero.Item[];
|
||||
|
|
@ -1101,13 +1077,11 @@ class Knowledge extends AddonBase {
|
|||
if (!Zotero.isWin && filename.charAt(0) !== "/") {
|
||||
filename = "/" + filename;
|
||||
}
|
||||
const translator = new Zotero.Translate.Export();
|
||||
translator.setItems([note]);
|
||||
translator.setLocation(Zotero.File.pathToFile(filename));
|
||||
translator.setTranslator(TRANSLATOR_ID_BETTER_MARKDOWN);
|
||||
this._exportPromise = Zotero.Promise.defer();
|
||||
translator.translate();
|
||||
await this._exportPromise.promise;
|
||||
const content: string = await this._Addon.parse.parseNoteToMD(note);
|
||||
console.log(
|
||||
`Exporting MD file: ${filename}, content length: ${content.length}`
|
||||
);
|
||||
await Zotero.File.putContentsAsync(filename, content);
|
||||
this._Addon.views.showProgressWindow(
|
||||
"Better Notes",
|
||||
`Note Saved to ${filename}`
|
||||
|
|
@ -1122,11 +1096,11 @@ class Knowledge extends AddonBase {
|
|||
}
|
||||
|
||||
private _getFileName(noteItem: Zotero.Item) {
|
||||
return this._Addon.template.renderTemplate(
|
||||
"[ExportMDFileName]",
|
||||
"noteItem",
|
||||
[noteItem]
|
||||
);
|
||||
return (
|
||||
this._Addon.template.renderTemplate("[ExportMDFileName]", "noteItem", [
|
||||
noteItem,
|
||||
]) as string
|
||||
).replace(/\\/g, "-");
|
||||
}
|
||||
|
||||
async convertNoteLines(
|
||||
|
|
|
|||
285
src/parse.ts
285
src/parse.ts
|
|
@ -1,9 +1,28 @@
|
|||
import AddonBase from "./module";
|
||||
import { HTML2Markdown, Markdown2HTML } from "./convertMD";
|
||||
import TurndownService = require("turndown");
|
||||
const turndownPluginGfm = require("turndown-plugin-gfm");
|
||||
const TreeModel = require("./treemodel");
|
||||
const asciidoctor = require("asciidoctor")();
|
||||
const seedrandom = require("seedrandom");
|
||||
|
||||
class AddonParse extends AddonBase {
|
||||
// A seedable version of Zotero.Utilities.randomString
|
||||
private randomString(len: number, chars: string, seed: string) {
|
||||
if (!chars) {
|
||||
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
}
|
||||
if (!len) {
|
||||
len = 8;
|
||||
}
|
||||
let randomstring = "";
|
||||
const random: Function = seedrandom(seed);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const rnum = Math.floor(random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
public parseNoteTree(note: Zotero.Item): TreeModel.Node<object> {
|
||||
const noteLines = this._Addon.knowledge.getLinesInNote(note);
|
||||
let tree = new TreeModel();
|
||||
|
|
@ -431,6 +450,272 @@ class AddonParse extends AddonBase {
|
|||
parseAsciiDocToHTML(str: string): string {
|
||||
return asciidoctor.convert(str);
|
||||
}
|
||||
|
||||
// A realization of Markdown Note.js translator
|
||||
async parseNoteToMD(noteItem: Zotero.Item, options: any = {}) {
|
||||
const doc = new DOMParser().parseFromString(
|
||||
noteItem.getNote() || "",
|
||||
"text/html"
|
||||
);
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
doc.querySelectorAll("span").forEach(function (span) {
|
||||
if (span.style.textDecoration === "line-through") {
|
||||
let s = doc.createElement("s");
|
||||
s.append(...span.childNodes);
|
||||
span.replaceWith(s);
|
||||
}
|
||||
});
|
||||
|
||||
// Turndown wants pre content inside additional code block
|
||||
doc.querySelectorAll("pre").forEach(function (pre) {
|
||||
let code = doc.createElement("code");
|
||||
code.append(...pre.childNodes);
|
||||
pre.append(code);
|
||||
});
|
||||
|
||||
// Insert a PDF link for highlight and image annotation nodes
|
||||
doc
|
||||
.querySelectorAll('span[class="highlight"], img[data-annotation]')
|
||||
.forEach((node) => {
|
||||
Zotero.debug(node.outerHTML);
|
||||
try {
|
||||
var annotation = JSON.parse(
|
||||
decodeURIComponent(node.getAttribute("data-annotation"))
|
||||
);
|
||||
} catch (e) {
|
||||
Zotero.debug(e);
|
||||
}
|
||||
|
||||
if (annotation) {
|
||||
// annotation.uri was used before note-editor v4
|
||||
let uri = annotation.attachmentURI || annotation.uri;
|
||||
let position = annotation.position;
|
||||
Zotero.debug("----Debug Link----");
|
||||
Zotero.debug(annotation);
|
||||
if (typeof uri === "string" && typeof position === "object") {
|
||||
Zotero.debug(uri);
|
||||
let openURI;
|
||||
let uriParts = uri.split("/");
|
||||
let libraryType = uriParts[3];
|
||||
let key = uriParts[uriParts.length - 1];
|
||||
Zotero.debug(key);
|
||||
if (libraryType === "users") {
|
||||
openURI = "zotero://open-pdf/library/items/" + key;
|
||||
}
|
||||
// groups
|
||||
else {
|
||||
let groupID = uriParts[4];
|
||||
openURI = "zotero://open-pdf/groups/" + groupID + "/items/" + key;
|
||||
}
|
||||
|
||||
openURI +=
|
||||
"?page=" +
|
||||
(position.pageIndex + 1) +
|
||||
(annotation.annotationKey
|
||||
? "&annotation=" + annotation.annotationKey
|
||||
: "");
|
||||
|
||||
let a = doc.createElement("a");
|
||||
a.href = openURI;
|
||||
a.append("pdf");
|
||||
let fragment = doc.createDocumentFragment();
|
||||
fragment.append(" (", a, ") ");
|
||||
|
||||
if (options.wrapCitation) {
|
||||
const citationKey = annotation.annotationKey
|
||||
? annotation.annotationKey
|
||||
: this.randomString(
|
||||
8,
|
||||
Zotero.Utilities.allowedKeyChars,
|
||||
Zotero.Utilities.Internal.md5(
|
||||
node.getAttribute("data-annotation")
|
||||
)
|
||||
);
|
||||
Zotero.Utilities.Internal.md5(
|
||||
node.getAttribute("data-annotation")
|
||||
);
|
||||
const beforeCitationDecorator = doc.createElement("span");
|
||||
beforeCitationDecorator.innerHTML = `<!-- bn::${citationKey} -->`;
|
||||
const afterCitationDecorator = doc.createElement("span");
|
||||
afterCitationDecorator.innerHTML = `<!-- bn::${citationKey} -->`;
|
||||
node.before(beforeCitationDecorator);
|
||||
fragment.append(afterCitationDecorator);
|
||||
}
|
||||
|
||||
let nextNode = node.nextElementSibling;
|
||||
if (nextNode && nextNode.classList.contains("citation")) {
|
||||
nextNode.parentNode.insertBefore(fragment, nextNode.nextSibling);
|
||||
} else {
|
||||
node.parentNode.insertBefore(fragment, node.nextSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(doc);
|
||||
|
||||
for (const img of doc.querySelectorAll("img[data-attachment-key]")) {
|
||||
let imgKey = img.getAttribute("data-attachment-key");
|
||||
|
||||
const attachmentItem = await Zotero.Items.getByLibraryAndKeyAsync(
|
||||
noteItem.libraryID,
|
||||
imgKey
|
||||
);
|
||||
Zotero.debug(attachmentItem);
|
||||
|
||||
let oldFile = String(await attachmentItem.getFilePathAsync());
|
||||
Zotero.debug(oldFile);
|
||||
let ext = oldFile.split(".").pop();
|
||||
let newAbsPath = OS.Path.join(
|
||||
...`${this._Addon.knowledge._exportPath}/${imgKey}.${ext}`.split(/\//)
|
||||
);
|
||||
if (!Zotero.isWin && newAbsPath.charAt(0) !== "/") {
|
||||
newAbsPath = "/" + newAbsPath;
|
||||
}
|
||||
Zotero.debug(newAbsPath);
|
||||
let newFile = oldFile;
|
||||
try {
|
||||
// Don't overwrite
|
||||
if (await OS.File.exists(newAbsPath)) {
|
||||
newFile = newAbsPath.replace(/\\/g, "/");
|
||||
} else {
|
||||
newFile = Zotero.File.copyToUnique(oldFile, newAbsPath).path;
|
||||
newFile = newFile.replace(/\\/g, "/");
|
||||
}
|
||||
newFile = `attachments/${newFile.split(/\//).pop()}`;
|
||||
} catch (e) {
|
||||
Zotero.debug(e);
|
||||
}
|
||||
Zotero.debug(newFile);
|
||||
|
||||
img.setAttribute("src", newFile ? newFile : oldFile);
|
||||
img.setAttribute("alt", "image");
|
||||
}
|
||||
|
||||
// Transform citations to links
|
||||
doc.querySelectorAll('span[class="citation"]').forEach(function (span) {
|
||||
try {
|
||||
var citation = JSON.parse(
|
||||
decodeURIComponent(span.getAttribute("data-citation"))
|
||||
);
|
||||
} catch (e) {}
|
||||
|
||||
if (citation && citation.citationItems && citation.citationItems.length) {
|
||||
let uris = [];
|
||||
for (let citationItem of citation.citationItems) {
|
||||
let uri = citationItem.uris[0];
|
||||
if (typeof uri === "string") {
|
||||
let uriParts = uri.split("/");
|
||||
let libraryType = uriParts[3];
|
||||
let key = uriParts[uriParts.length - 1];
|
||||
Zotero.debug(key);
|
||||
if (libraryType === "users") {
|
||||
uris.push("zotero://select/library/items/" + key);
|
||||
}
|
||||
// groups
|
||||
else {
|
||||
let groupID = uriParts[4];
|
||||
uris.push("zotero://select/groups/" + groupID + "/items/" + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let items = Array.from(span.querySelectorAll(".citation-item")).map(
|
||||
(x) => x.textContent
|
||||
);
|
||||
// Fallback to pre v5 note-editor schema that was serializing citations as plain text i.e.:
|
||||
// <span class="citation" data-citation="...">(Jang et al., 2005, p. 14; Kongsgaard et al., 2009, p. 790)</span>
|
||||
if (!items.length) {
|
||||
items = span.textContent.slice(1, -1).split("; ");
|
||||
}
|
||||
|
||||
span.innerHTML =
|
||||
"(" +
|
||||
items
|
||||
.map((item, i) => {
|
||||
return `<a href="${uris[i]}">${item}</a>`;
|
||||
})
|
||||
.join("; ") +
|
||||
")";
|
||||
}
|
||||
});
|
||||
// Overwrite escapes
|
||||
const escapes: [RegExp, string][] = [
|
||||
// [/\\/g, '\\\\'],
|
||||
// [/\*/g, '\\*'],
|
||||
[/^-/g, "\\-"],
|
||||
[/^\+ /g, "\\+ "],
|
||||
[/^(=+)/g, "\\$1"],
|
||||
[/^(#{1,6}) /g, "\\$1 "],
|
||||
[/`/g, "\\`"],
|
||||
[/^~~~/g, "\\~~~"],
|
||||
// [/^>/g, "\\>"],
|
||||
// [/_/g, "\\_"],
|
||||
[/^(\d+)\. /g, "$1\\. "],
|
||||
];
|
||||
if (Zotero.Prefs.get("Knowledge4Zotero.convertSquare")) {
|
||||
escapes.push([/\[/g, "\\["]);
|
||||
escapes.push([/\]/g, "\\]"]);
|
||||
}
|
||||
TurndownService.prototype.escape = function (string) {
|
||||
return escapes.reduce(function (accumulator, escape) {
|
||||
return accumulator.replace(escape[0], escape[1]);
|
||||
}, string);
|
||||
};
|
||||
// Initialize Turndown Service
|
||||
let turndownService = new TurndownService({
|
||||
headingStyle: "atx",
|
||||
bulletListMarker: "-",
|
||||
emDelimiter: "*",
|
||||
codeBlockStyle: "fenced",
|
||||
});
|
||||
turndownService.use(turndownPluginGfm.gfm);
|
||||
// Add math block rule
|
||||
turndownService.addRule("mathBlock", {
|
||||
filter: function (node) {
|
||||
return node.nodeName === "PRE" && node.className === "math";
|
||||
},
|
||||
|
||||
replacement: function (content, node, options) {
|
||||
return (
|
||||
"\n\n$$\n" + node.firstChild.textContent.slice(2, -2) + "\n$$\n\n"
|
||||
);
|
||||
},
|
||||
});
|
||||
turndownService.addRule("inlineLinkCustom", {
|
||||
filter: function (node, options) {
|
||||
return (
|
||||
options.linkStyle === "inlined" &&
|
||||
node.nodeName === "A" &&
|
||||
node.getAttribute("href").length > 0
|
||||
);
|
||||
},
|
||||
|
||||
replacement: function (content, node: HTMLElement, options) {
|
||||
var href = node.getAttribute("href");
|
||||
const cleanAttribute = (attribute) =>
|
||||
attribute ? attribute.replace(/(\n+\s*)+/g, "\n") : "";
|
||||
var title = cleanAttribute(node.getAttribute("title"));
|
||||
if (title) title = ' "' + title + '"';
|
||||
if (href.search(/zotero:\/\/note\/\w+\/\w+\//g) !== -1) {
|
||||
// A note link should be converted if it is in the _exportFileDict
|
||||
var _Zotero = Components.classes["@zotero.org/Zotero;1"].getService(
|
||||
Components.interfaces.nsISupports
|
||||
).wrappedJSObject;
|
||||
const noteInfo =
|
||||
_Zotero.Knowledge4Zotero.knowledge._exportFileDict &&
|
||||
_Zotero.Knowledge4Zotero.knowledge._exportFileDict.find((i) =>
|
||||
href.includes(i.link)
|
||||
);
|
||||
if (noteInfo) {
|
||||
href = `./${noteInfo.filename}`;
|
||||
}
|
||||
}
|
||||
return "[" + content + "](" + href + title + ")";
|
||||
},
|
||||
});
|
||||
return turndownService.turndown(doc.body);
|
||||
}
|
||||
}
|
||||
|
||||
export default AddonParse;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class AddonTemplate extends AddonBase {
|
|||
},
|
||||
{
|
||||
name: "[ExportMDFileName]",
|
||||
text: '${(noteItem.getNoteTitle ? noteItem.getNoteTitle().replace(/[/\\?%*:|"<> ]/g, "-") + "-" : "")}${noteItem.key}.md',
|
||||
text: '${(noteItem.getNoteTitle ? noteItem.getNoteTitle().replace(/[/\\\\?%*:|"<> ]/g, "-") + "-" : "")}${noteItem.key}.md',
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"include": [
|
||||
"src",
|
||||
"typing",
|
||||
"node_modules/zotero-types"
|
||||
"node_modules/zotero-types",
|
||||
|
||||
],
|
||||
"exclude": [
|
||||
"builds",
|
||||
|
|
|
|||
Loading…
Reference in New Issue