Compare commits
11 Commits
v2.2.3-bet
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
568e460189 | ||
|
|
5851b95ff1 | ||
|
|
719be35dca | ||
|
|
bf46815ddb | ||
|
|
476b569555 | ||
|
|
7ec71c9a10 | ||
|
|
83151daf7f | ||
|
|
6259a9a2a6 | ||
|
|
79f7c81886 | ||
|
|
270d7fcb7f | ||
|
|
cfedb94159 |
|
|
@ -43,7 +43,6 @@ body:
|
|||
- Item
|
||||
- Text
|
||||
- QuickInsert
|
||||
- QuickBackLink
|
||||
- QuickImport
|
||||
- QuickNote
|
||||
- ExportMDFileName
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
"\tremoveIfExists: ${13:true},",
|
||||
"\tcustomCheck: (doc: Document, options: ElementOptions) => ${14:true},",
|
||||
"\tchildren: [$15]",
|
||||
"}, ${16:container});"
|
||||
]
|
||||
"}, ${16:container});",
|
||||
],
|
||||
},
|
||||
"appendElement - minimum": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "appendElement",
|
||||
"body": "appendElement({ tag: '$1' }, $2);"
|
||||
"body": "appendElement({ tag: '$1' }, $2);",
|
||||
},
|
||||
"register Notifier": {
|
||||
"scope": "javascript,typescript",
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
"\t) => {",
|
||||
"\t\t$0",
|
||||
"\t}",
|
||||
"});"
|
||||
]
|
||||
}
|
||||
"});",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
|||
32
README.md
32
README.md
|
|
@ -90,7 +90,7 @@ and:
|
|||
|
||||
- Download the plugin (.xpi file) from below.
|
||||
|
||||
- [Latest Version: 2.2.3-beta.4](https://github.com/windingwind/zotero-better-notes/releases/download/v2.2.3-beta.4/better-notes-for-zotero.xpi)
|
||||
- [Latest Version: 2.2.5](https://github.com/windingwind/zotero-better-notes/releases/download/v2.2.5/better-notes-for-zotero.xpi)
|
||||
- [Latest Stable](https://github.com/windingwind/zotero-better-notes/releases/latest)
|
||||
- [All Releases](https://github.com/windingwind/zotero-better-notes/releases)
|
||||
|
||||
|
|
@ -240,6 +240,17 @@ BN provides APIs for other plugin developers in `Zotero.BetterNotes.api.${API_MO
|
|||
- `$export`: Export note
|
||||
- `$import`: Import note
|
||||
- `editor`: Note editor APIs. Give your script full control of contents in the note editor.
|
||||
- `note`: Note APIs. Parse and manipulate note content.
|
||||
- `relation`: Note relation APIs. Get and set note relations.
|
||||
- `utils`: Utility functions.
|
||||
|
||||
### Concepts about Note-Related APIs
|
||||
|
||||
In Zotero, the content of a note is stored as rich text, while when a note is opened in the note editor, it is rendered by ProseMirror as HTML.
|
||||
|
||||
Most of the time, it is recommended to use the `editor` API to interact with the content of the note, as it supports undo/redo and other features provided by editor. The `editor` API provides a set of powerful functions to analyze and manipulate the content in the note editor. Most of them needs an `editor` instance as the input, you can get the instance by calling `Zotero.BetterNotes.api.editor.getEditorInstance(noteId)`.
|
||||
|
||||
However, if note is not opened in the editor, you cannot get the `editor` instance. In this case, you can use the `note` API to interact with the content of the note.
|
||||
|
||||
## 🔧 Development
|
||||
|
||||
|
|
@ -256,14 +267,31 @@ npm run build
|
|||
|
||||
The plugin is built to `./builds/*.xpi`.
|
||||
|
||||
To debug, run
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
This will open a new Zotero instance with the plugin installed.
|
||||
|
||||
To test the plugin, run
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
```
|
||||
|
||||
This will run the tests in the `./test` directory.
|
||||
|
||||
## 🔔 Disclaimer
|
||||
|
||||
Use this code under AGPL. No warranties are provided. Keep the laws of your locality in mind!
|
||||
|
||||
## 🔎 My Zotero Plugins
|
||||
|
||||
- [Translate for Zotero](https://github.com/windingwind/zotero-pdf-translate): PDF translation for Zotero
|
||||
- [Translate for Zotero](https://github.com/windingwind/zotero-pdf-translate): Translate PDF, EPub, webpage, metadata, annotations, notes to the target language.
|
||||
- [Actions & Tags for Zotero](https://github.com/windingwind/zotero-tag): Customize your Zotero workflow.
|
||||
- [Bionic for Zotero](https://github.com/windingwind/bionic-for-zotero): Bionic reading experience with Zotero.
|
||||
|
||||
## 🙌 Sponsors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
var { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@
|
|||
</style>
|
||||
<script>
|
||||
var browser;
|
||||
var { Services } = ChromeUtils.import(
|
||||
"resource://gre/modules/Services.jsm",
|
||||
);
|
||||
var { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@
|
|||
</xul:keyset>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", (ev) => {
|
||||
const { Services } = ChromeUtils.import(
|
||||
"resource://gre/modules/Services.jsm",
|
||||
);
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://zotero/content/include.js",
|
||||
this,
|
||||
|
|
|
|||
|
|
@ -45,10 +45,6 @@
|
|||
</xul:keyset>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", (ev) => {
|
||||
const { Services } = ChromeUtils.import(
|
||||
"resource://gre/modules/Services.jsm",
|
||||
);
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://zotero/content/include.js",
|
||||
this,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ One-click to import.
|
|||
```yaml
|
||||
# This template is specifically for importing/sharing, using better
|
||||
# notes 'import from clipboard': copy the content and
|
||||
# goto Zotero menu bar, click Edit->New Template from Clipboard.
|
||||
# goto Zotero menu bar, click Tools->New Template from Clipboard.
|
||||
# Do not copy-paste this to better notes template editor directly.
|
||||
name: "[Text] Current Time"
|
||||
content: |-
|
||||
|
|
@ -32,7 +32,7 @@ content: |-
|
|||
|
||||
</details>
|
||||
|
||||
2. Goto Zotero menubar, click `Edit`->`New Template from Clipboard`.
|
||||
2. Goto Zotero menubar, click `Tools`->`New Template from Clipboard`.
|
||||
3. Click OK.
|
||||
|
||||
Now you can open a note/the workspace and in editor toolbar, click `Insert Template to cursor line`. Select the template, it is inserted to the note.
|
||||
|
|
@ -88,7 +88,9 @@ Let the compiler know you are using markdown. Otherwise the template will be pro
|
|||
Allow the generated content to be updated using the `Update content from templates` in the note editor.
|
||||
The generated content will be wrapped in separators with a YAML metadata section for update.
|
||||
|
||||
> The template with this pragma should not contain any separator (`---` or `<hr>`) in the content.
|
||||
The template with this pragma should not contain any separator (`---` or `<hr>`) in the content.
|
||||
|
||||
> Since the first line of the content is a separator, the note generated from a template with this pragma will have a blank note title. See the solution [here](https://github.com/windingwind/zotero-better-notes/issues/1247#issuecomment-2573739339).
|
||||
|
||||
### `// @author`
|
||||
|
||||
|
|
@ -148,7 +150,7 @@ If no stage pragma is given, the whole template will be processed on the default
|
|||
```yaml
|
||||
# This template is specifically for importing/sharing, using better
|
||||
# notes 'import from clipboard': copy the content and
|
||||
# goto Zotero menu bar, click Edit->New Template from Clipboard.
|
||||
# goto Zotero menu bar, click Tools->New Template from Clipboard.
|
||||
# Do not copy-paste this to better notes template editor directly.
|
||||
name: "[Item] Example Item Template"
|
||||
content: |-
|
||||
|
|
@ -214,7 +216,6 @@ The name of builtin templates are not allowed to be modified.
|
|||
| Name | Description | Variables |
|
||||
| ------------------- | -------------------------------------------------------- | ------------------------------------- |
|
||||
| QuickInsert | For forward link. | link, linkText, subNoteItem, noteItem |
|
||||
| QuickBackLink | For back link. | link, linkText, subNoteItem, noteItem |
|
||||
| QuickImport | For importing note link content. | link, noteItem |
|
||||
| QuickNote | For generating note from annotation. | annotationItem, topItem, noteItem |
|
||||
| ExportMDFileName | For generating Markdown file name when exporting. | noteItem |
|
||||
|
|
@ -408,7 +409,7 @@ A template snippet should be in YAML format (YAML has better support for multi-l
|
|||
```yaml
|
||||
# This template is specifically for importing/sharing, using better
|
||||
# notes 'import from clipboard': copy the content and
|
||||
# goto Zotero menu bar, click Edit->New Template from Clipboard.
|
||||
# goto Zotero menu bar, click Tools->New Template from Clipboard.
|
||||
# Do not copy-paste this to better notes template editor directly.
|
||||
name: "[TYPE] TEMPLATE NAME"
|
||||
content: |-
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "zotero-better-notes",
|
||||
"version": "2.2.3-beta.4",
|
||||
"version": "2.2.5",
|
||||
"description": "Everything about note management. All in Zotero.",
|
||||
"config": {
|
||||
"addonName": "Better Notes for Zotero",
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
"homepage": "https://github.com/windingwind/zotero-better-notes#readme",
|
||||
"dependencies": {
|
||||
"asciidoctor": "^3.0.4",
|
||||
"dexie": "^4.0.10",
|
||||
"dexie": "^4.0.11",
|
||||
"diff": "^5.2.0",
|
||||
"hast-util-to-html": "^9.0.4",
|
||||
"hast-util-to-mdast": "^8.4.1",
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
"hastscript": "^8.0.0",
|
||||
"html-docx-js": "^0.3.1",
|
||||
"html-docx-js-typescript": "^0.1.5",
|
||||
"katex": "^0.16.19",
|
||||
"katex": "^0.16.21",
|
||||
"path-browserify": "^1.0.1",
|
||||
"rehype-format": "^4.0.1",
|
||||
"rehype-parse": "^8.0.5",
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
"unist-util-visit": "^5.0.0",
|
||||
"unist-util-visit-parents": "^6.0.1",
|
||||
"yamljs": "^0.3.0",
|
||||
"zotero-plugin-toolkit": "^4.1.0"
|
||||
"zotero-plugin-toolkit": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
"@types/html-docx-js": "^0.3.4",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "^20.17.10",
|
||||
"@types/node": "^20.17.14",
|
||||
"@types/path-browserify": "^1.0.3",
|
||||
"@types/seedrandom": "^3.0.8",
|
||||
"@types/yamljs": "^0.2.34",
|
||||
|
|
@ -86,10 +86,10 @@
|
|||
"prosemirror-transform": "^1.10.2",
|
||||
"prosemirror-view": "^1.37.1",
|
||||
"replace-in-file": "^7.2.0",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript": "^5.7.3",
|
||||
"xslt3": "^2.7.0",
|
||||
"zotero-plugin-scaffold": "^0.2.0-beta.17",
|
||||
"zotero-types": "^3.1.0"
|
||||
"zotero-plugin-scaffold": "^0.2.0-beta.20",
|
||||
"zotero-types": "^3.1.6"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"env": {
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class PluginState {
|
|||
height: auto;
|
||||
}
|
||||
.link-preview .primary-editor li {
|
||||
white-space: nowrap;
|
||||
white-space: normal;
|
||||
}
|
||||
</style>`),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -141,6 +141,13 @@ async function onNotify(
|
|||
if (extraData?.skipBN) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
["add", "close"].includes(event) &&
|
||||
type === "tab" &&
|
||||
extraData[ids[0]]?.type === "note"
|
||||
) {
|
||||
Zotero.Session.debounceSave();
|
||||
}
|
||||
if (event === "select" && type === "tab") {
|
||||
onTabSelect(extraData[ids[0]].type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,8 +199,9 @@ export async function showTemplateEditor() {
|
|||
const editorWin = (_window.document.querySelector("#editor") as any)
|
||||
.contentWindow;
|
||||
await waitUtilAsync(() => editorWin?.loadMonaco);
|
||||
const isDark = editorWin?.matchMedia("(prefers-color-scheme: dark)")
|
||||
.matches;
|
||||
const isDark = editorWin?.matchMedia(
|
||||
"(prefers-color-scheme: dark)",
|
||||
).matches;
|
||||
const { monaco, editor } = await editorWin.loadMonaco({
|
||||
language: "javascript",
|
||||
theme: "vs-" + (isDark ? "dark" : "light"),
|
||||
|
|
|
|||
|
|
@ -93,25 +93,6 @@ async function renderTemplatePreview(
|
|||
},
|
||||
);
|
||||
}
|
||||
} else if (templateName.includes("QuickBackLink")) {
|
||||
// link, linkText, subNoteItem, noteItem
|
||||
const data = inputItems?.find((item) => item.isNote());
|
||||
if (!data) {
|
||||
html = messages.noNoteItem;
|
||||
} else {
|
||||
const link = getNoteLink(data);
|
||||
const noteItem = new Zotero.Item("note");
|
||||
const linkText = noteItem.getNoteTitle().trim() || "Workspace Note";
|
||||
const subNoteItem = data;
|
||||
html = await addon.api.template.runTemplate(
|
||||
templateName,
|
||||
"link, linkText, subNoteItem, noteItem",
|
||||
[link, linkText, subNoteItem, noteItem],
|
||||
{
|
||||
dryRun: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if (templateName.includes("QuickImport")) {
|
||||
// link, noteItem
|
||||
const data = inputItems?.find((item) => item.isNote());
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ export async function restoreNoteTabs() {
|
|||
select: !!tab.selected,
|
||||
});
|
||||
}
|
||||
Zotero.Session.debounceSave();
|
||||
}
|
||||
|
||||
export function onUpdateNoteTabsTitle(noteItems: Zotero.Item[]) {
|
||||
|
|
|
|||
|
|
@ -428,11 +428,12 @@ async function rehype2remark(rehype: HRoot) {
|
|||
return mNode;
|
||||
}
|
||||
const children: any[] = [];
|
||||
const paragraphNodes = ["list", "code", "math", "table"];
|
||||
// Merge none-list nodes inside li into the previous paragraph node to avoid line break
|
||||
while (mNode.children.length > 0) {
|
||||
const current = mNode.children.shift();
|
||||
const cached = children[children.length - 1];
|
||||
if (current?.type !== "list") {
|
||||
if (current?.type && !paragraphNodes.includes(current?.type)) {
|
||||
if (cached?.type === "paragraph") {
|
||||
cached.children.push(current);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,11 @@ async function addLineToNote(
|
|||
if (editor && !forceMetadata) {
|
||||
// The note is opened. Add line via note editor
|
||||
// If the lineIndex is out of range, the line will be inserted at the end (after the last line)
|
||||
const pos = getPositionAtLine(editor, lineIndex, lineIndex >= noteLines.length ? "end" : "start");
|
||||
const pos = getPositionAtLine(
|
||||
editor,
|
||||
lineIndex,
|
||||
lineIndex >= noteLines.length ? "end" : "start",
|
||||
);
|
||||
ztoolkit.log("Add note line via note editor", pos);
|
||||
insert(editor, html, pos);
|
||||
// The selection is automatically moved to the next line
|
||||
|
|
@ -386,9 +390,8 @@ async function copyEmbeddedImagesInHTML(
|
|||
if (!copiedAttachment) {
|
||||
continue;
|
||||
}
|
||||
nodes.forEach(
|
||||
(node) =>
|
||||
node?.setAttribute("data-attachment-key", copiedAttachment!.key),
|
||||
nodes.forEach((node) =>
|
||||
node?.setAttribute("data-attachment-key", copiedAttachment!.key),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export {
|
|||
unregisterPrefObserver,
|
||||
};
|
||||
|
||||
type _PluginPrefsMap = object;
|
||||
type _PluginPrefsMap = _ZoteroTypes.Prefs["PluginPrefsMap"];
|
||||
|
||||
function getPref<K extends keyof _PluginPrefsMap>(key: K): _PluginPrefsMap[K];
|
||||
function getPref(key: string): string | number | boolean;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,255 @@
|
|||
/* eslint-disable no-irregular-whitespace */
|
||||
/* eslint-disable no-useless-escape */
|
||||
import { ClipboardHelper } from "zotero-plugin-toolkit";
|
||||
import { getAddon } from "../utils/global";
|
||||
import { resetAll } from "../utils/status";
|
||||
import { getNoteContent, parseTemplateString } from "../utils/note";
|
||||
import { getTempDirectory } from "../utils/io";
|
||||
|
||||
describe("Export", function () {
|
||||
const addon = getAddon();
|
||||
this.beforeAll(async function () {
|
||||
await resetAll();
|
||||
});
|
||||
|
||||
this.afterEach(async function () {});
|
||||
|
||||
it("api.$export.saveMD", async function () {
|
||||
const note = new Zotero.Item("note");
|
||||
note.setNote(getNoteContent());
|
||||
await note.saveTx();
|
||||
|
||||
const tempDir = await getTempDirectory();
|
||||
|
||||
const filePath = PathUtils.join(tempDir, "test.md");
|
||||
|
||||
await getAddon().api.$export.saveMD(filePath, note.id, {
|
||||
keepNoteLink: true,
|
||||
withYAMLHeader: false,
|
||||
});
|
||||
|
||||
debug("Note saved to", filePath);
|
||||
|
||||
const content = await Zotero.File.getContentsAsync(filePath);
|
||||
|
||||
const expected = `# Markdown Test Document
|
||||
|
||||
## Headers
|
||||
|
||||
# H1 Header
|
||||
|
||||
## H2 Header
|
||||
|
||||
### H3 Header
|
||||
|
||||
#### H4 Header
|
||||
|
||||
##### H5 Header
|
||||
|
||||
###### H6 Header
|
||||
|
||||
## Emphasis
|
||||
|
||||
*This text is italicized.* *This text is also italicized.*
|
||||
|
||||
**This text is bold.** **This text is also bold.**
|
||||
|
||||
***This text is bold and italicized.*** ***This text is also bold and italicized.***
|
||||
|
||||
## Links
|
||||
|
||||
[Link with title](https://example.com "Title") [Link without title](https://example.com)
|
||||
|
||||
## Images
|
||||
|
||||
## Blockquotes
|
||||
|
||||
> This is a blockquote.
|
||||
>
|
||||
> > Nested blockquote.
|
||||
>
|
||||
> Back to the outer blockquote.
|
||||
|
||||
## Lists
|
||||
|
||||
### Unordered List
|
||||
|
||||
* Item 1
|
||||
|
||||
* Subitem 1.1
|
||||
|
||||
* Subitem 1.1.1
|
||||
|
||||
* Item 2
|
||||
|
||||
### Ordered List
|
||||
|
||||
1. First item
|
||||
|
||||
1. Subitem 1.1
|
||||
|
||||
1. Subitem 1.1.1
|
||||
|
||||
2. Second item
|
||||
|
||||
## Code
|
||||
|
||||
### Inline Code
|
||||
|
||||
Here is some \`inline code\`.
|
||||
|
||||
### Code Block
|
||||
|
||||
\`\`\`
|
||||
def hello_world():
|
||||
print("Hello, world!")
|
||||
|
||||
\`\`\`
|
||||
|
||||
## Horizontal Rules
|
||||
|
||||
***
|
||||
|
||||
This is text between horizontal rules
|
||||
|
||||
***
|
||||
|
||||
## Tables
|
||||
|
||||
| Header 1 | Header 2 | Header 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| Row 1 | Data 1.2 | Data 1.3 |
|
||||
| Row 2 | Data 2.2 | Data 2.3 |
|
||||
|
||||
## Math
|
||||
|
||||
### Inline Math
|
||||
|
||||
This is an inline math equation: \$E = mc^2\$.
|
||||
|
||||
### Block Math
|
||||
|
||||
Below is a block math equation:
|
||||
|
||||
\$\$
|
||||
\\\\int_a^b f(x) \\\\, dx = F(b) - F(a)
|
||||
\$\$
|
||||
|
||||
### Complex Math
|
||||
|
||||
Solve the quadratic equation:
|
||||
|
||||
\$\$
|
||||
x = \\\\frac\{-b \\\\pm \\\\sqrt\{b^2 - 4ac\}\}\{2a\}
|
||||
\$\$
|
||||
|
||||
## Nested Elements
|
||||
|
||||
### Nested Code and Lists
|
||||
|
||||
1. Ordered list item
|
||||
|
||||
* Unordered subitem
|
||||
|
||||
\`\`\`
|
||||
console.log("Nested code block");
|
||||
|
||||
\`\`\`
|
||||
|
||||
2. This is a nested math
|
||||
|
||||
\$\$
|
||||
y=x^2
|
||||
\$\$
|
||||
|
||||
3. This is a inline math\$123\$
|
||||
|
||||
4. This is a line table
|
||||
|
||||
| | | |
|
||||
| - | - | - |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
| 7 | 8 | 9 |
|
||||
|
||||
## Special Characters
|
||||
|
||||
Escape sequences for special characters: \\* \\_ \\\\\\\` \\[ ] ( ) # + - .
|
||||
|
||||
## HTML in Markdown
|
||||
|
||||
This is a HTML block inside Markdown.
|
||||
|
||||
## Highlight Text
|
||||
|
||||
Highlight <span style="background-color: rgba(255, 102, 102, 0.5)">text</span> is here
|
||||
|
||||
## Colored Text
|
||||
|
||||
Colored <span style="color: rgb(255, 32, 32)">text</span> is here
|
||||
|
||||
## Task Lists
|
||||
|
||||
* Completed item
|
||||
* Incomplete item
|
||||
|
||||
## Strikethrough
|
||||
|
||||
~~This text is strikethrough.~~
|
||||
|
||||
## Recursive Elements
|
||||
|
||||
### Recursive Links and Emphasis
|
||||
|
||||
**[Bold link](https://example.com)**
|
||||
|
||||
### Recursive Emphasis
|
||||
|
||||
***Bold and nested italic within bold.***
|
||||
|
||||
## Image
|
||||
|
||||
IMAGE\\_PLACEHOLDER
|
||||
|
||||
## Citation
|
||||
|
||||
CITATION\\_PLACEHOLDER
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### Empty Link
|
||||
|
||||
[Link](https://)
|
||||
|
||||
### Zotero Link
|
||||
|
||||
[Zotero Link](zotero://note/u/123456)
|
||||
|
||||
### Lone Asterisk
|
||||
|
||||
* This should not be italic.
|
||||
|
||||
### Broken Lists
|
||||
|
||||
* Item 1
|
||||
|
||||
* Item 2Continuation of item 2 without proper indentation.
|
||||
|
||||
### Long Text Wrapping
|
||||
|
||||
This is a very long paragraph that does not have any line breaks and is intended to test how the Markdown engine handles text wrapping when there are no explicit line breaks within the text.
|
||||
|
||||
***
|
||||
|
||||
## Conclusion
|
||||
|
||||
This document contains a wide range of Markdown elements, including headers, lists, blockquotes, inline and block code, tables, images, links, math, and special characters. It also tests recursive and edge cases to ensure the Markdown engine is robust.
|
||||
`;
|
||||
|
||||
// new ClipboardHelper()
|
||||
// .addText(parseTemplateString(content as string))
|
||||
// .copy();
|
||||
|
||||
assert.equal(content, expected);
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,16 @@
|
|||
export async function getTempDirectory() {
|
||||
let path = "";
|
||||
let attempts = 3;
|
||||
const zoteroTmpDirPath = Zotero.getTempDirectory().path;
|
||||
while (attempts--) {
|
||||
path = PathUtils.join(zoteroTmpDirPath, Zotero.Utilities.randomString());
|
||||
try {
|
||||
await IOUtils.makeDirectory(path, { ignoreExisting: false });
|
||||
break;
|
||||
} catch (e) {
|
||||
if (!attempts) throw e; // Throw on last attempt
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
export function getNoteContent() {
|
||||
return `<div data-schema-version="9"><h1>Markdown Test Document</h1>
|
||||
<h2>Headers</h2>
|
||||
<h1>H1 Header</h1>
|
||||
<h2>H2 Header</h2>
|
||||
<h3>H3 Header</h3>
|
||||
<h4>H4 Header</h4>
|
||||
<h5>H5 Header</h5>
|
||||
<h6>H6 Header</h6>
|
||||
<h2>Emphasis</h2>
|
||||
<p><em>This text is italicized.</em> <em>This text is also italicized.</em></p>
|
||||
<p><strong>This text is bold.</strong> <strong>This text is also bold.</strong></p>
|
||||
<p><strong><em>This text is bold and italicized.</em></strong> <strong><em>This text is also bold and italicized.</em></strong></p>
|
||||
<h2>Links</h2>
|
||||
<p><a href="https://example.com" title="Title" rel="noopener noreferrer nofollow">Link with title</a> <a href="https://example.com" rel="noopener noreferrer nofollow">Link without title</a></p>
|
||||
<h2>Images</h2>
|
||||
<p></p>
|
||||
<h2>Blockquotes</h2>
|
||||
<blockquote>
|
||||
<p>This is a blockquote.</p>
|
||||
<blockquote>
|
||||
<p>Nested blockquote.</p>
|
||||
</blockquote>
|
||||
<p>Back to the outer blockquote.</p>
|
||||
</blockquote>
|
||||
<h2>Lists</h2>
|
||||
<h3>Unordered List</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Item 1</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Subitem 1.1</p>
|
||||
<ul>
|
||||
<li>
|
||||
Subitem 1.1.1
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
Item 2
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ordered List</h3>
|
||||
<ol>
|
||||
<li>
|
||||
<p>First item</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Subitem 1.1</p>
|
||||
<ol>
|
||||
<li>
|
||||
Subitem 1.1.1
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
Second item
|
||||
</li>
|
||||
</ol>
|
||||
<h2>Code</h2>
|
||||
<h3>Inline Code</h3>
|
||||
<p>Here is some <code>inline code</code>.</p>
|
||||
<h3>Code Block</h3>
|
||||
<pre>def hello_world():
|
||||
print("Hello, world!")
|
||||
</pre>
|
||||
<h2>Horizontal Rules</h2>
|
||||
<hr>
|
||||
<p>This is text between horizontal rules</p>
|
||||
<hr>
|
||||
<h2>Tables</h2>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
<p>Header 1</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>Header 2</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>Header 3</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Row 1</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Data 1.2</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Data 1.3</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Row 2</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Data 2.2</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>Data 2.3</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Math</h2>
|
||||
<h3>Inline Math</h3>
|
||||
<p>This is an inline math equation: <span class="math">$E = mc^2$</span>.</p>
|
||||
<h3>Block Math</h3>
|
||||
<p>Below is a block math equation:</p>
|
||||
<pre class="math">$$\\\\int_a^b f(x) \\\\, dx = F(b) - F(a)$$</pre>
|
||||
<h3>Complex Math</h3>
|
||||
<p>Solve the quadratic equation:</p>
|
||||
<pre class="math">$$x = \\\\frac{-b \\\\pm \\\\sqrt{b^2 - 4ac}}{2a}$$</pre>
|
||||
<h2>Nested Elements</h2>
|
||||
<h3>Nested Code and Lists</h3>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Ordered list item</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Unordered subitem</p>
|
||||
<pre>console.log("Nested code block");
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>This is a nested math</p>
|
||||
<pre class="math">$$y=x^2$$</pre>
|
||||
</li>
|
||||
<li>
|
||||
This is a inline math<span class="math">$123$</span>
|
||||
</li>
|
||||
<li>
|
||||
<p>This is a line table</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p>1</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>2</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>3</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>4</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>5</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>6</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>7</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>8</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>9</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
</ol>
|
||||
<h2>Special Characters</h2>
|
||||
<p>Escape sequences for special characters: * _ \\\` [ ] ( ) # + - .</p>
|
||||
<h2>HTML in Markdown</h2>
|
||||
<p>This is a HTML block inside Markdown.</p>
|
||||
<h2>Highlight Text</h2>
|
||||
<p>Highlight <span style="background-color: rgba(255, 102, 102, 0.5)">text</span> is here</p>
|
||||
<h2>Colored Text</h2>
|
||||
<p>Colored <span style="color: rgb(255, 32, 32)">text</span> is here</p>
|
||||
<h2>Task Lists</h2>
|
||||
<ul>
|
||||
<li>
|
||||
Completed item
|
||||
</li>
|
||||
<li>
|
||||
Incomplete item
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Strikethrough</h2>
|
||||
<p><span style="text-decoration: line-through">This text is strikethrough.</span></p>
|
||||
<h2>Recursive Elements</h2>
|
||||
<h3>Recursive Links and Emphasis</h3>
|
||||
<p><strong><a href="https://example.com" rel="noopener noreferrer nofollow">Bold link</a></strong></p>
|
||||
<h3>Recursive Emphasis</h3>
|
||||
<p><strong><em>Bold and nested italic within bold.</em></strong></p>
|
||||
<h2>Image</h2>
|
||||
<p>IMAGE_PLACEHOLDER</p>
|
||||
<h2>Citation</h2>
|
||||
<p>CITATION_PLACEHOLDER</p>
|
||||
<h2>Edge Cases</h2>
|
||||
<h3>Empty Link</h3>
|
||||
<p><a href="https://" rel="noopener noreferrer nofollow">Link</a></p>
|
||||
<h3>Zotero Link</h3>
|
||||
<p><a href="zotero://note/u/123456" rel="noopener noreferrer nofollow">Zotero Link</a></p>
|
||||
<h3>Lone Asterisk</h3>
|
||||
<ul>
|
||||
<li>
|
||||
This should not be italic.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Broken Lists</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Item 1</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Item 2</p>
|
||||
<p>Continuation of item 2 without proper indentation.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Long Text Wrapping</h3>
|
||||
<p>This is a very long paragraph that does not have any line breaks and is intended to test how the Markdown engine handles text wrapping when there are no explicit line breaks within the text.</p>
|
||||
<hr>
|
||||
<h2>Conclusion</h2>
|
||||
<p>This document contains a wide range of Markdown elements, including headers, lists, blockquotes, inline and block code, tables, images, links, math, and special characters. It also tests recursive and edge cases to ensure the Markdown engine is robust.</p>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
export function parseTemplateString(input: string): string {
|
||||
return input
|
||||
.replace(/\\/g, "\\\\") // Escape backslashes
|
||||
.replace(/`/g, "\\`") // Escape backticks
|
||||
.replace(/\$/g, "\\$") // Escape dollar signs
|
||||
.replace(/{/g, "\\{") // Escape opening braces
|
||||
.replace(/}/g, "\\}"); // Escape closing braces
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Generated by zotero-plugin-scaffold
|
||||
/* prettier-ignore */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
// prettier-ignore
|
||||
declare namespace _ZoteroTypes {
|
||||
interface Prefs {
|
||||
PluginPrefsMap: {
|
||||
"syncNoteIds": string;
|
||||
"syncPeriodSeconds": number;
|
||||
"syncAttachmentFolder": string;
|
||||
"autoAnnotation": boolean;
|
||||
"insertLinkPosition": string;
|
||||
"workspace.outline.expandLevel": number;
|
||||
"workspace.outline.keepLinks": boolean;
|
||||
"editor.noteLinkPreviewType": string;
|
||||
"editor.useMagicKey": boolean;
|
||||
"editor.useMarkdownPaste": boolean;
|
||||
"openNote.takeover": boolean;
|
||||
"openNote.defaultAsWindow": boolean;
|
||||
"exportNotes.takeover": boolean;
|
||||
"annotationNote.enableTagSync": boolean;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -52,10 +52,9 @@ export default defineConfig({
|
|||
target: ["firefox115"],
|
||||
},
|
||||
],
|
||||
// prefs: {
|
||||
// prefix: pkg.config.prefsPrefix,
|
||||
// dts: false,
|
||||
// },
|
||||
prefs: {
|
||||
prefix: pkg.config.prefsPrefix,
|
||||
},
|
||||
hooks: {
|
||||
"build:bundle": (ctx) => {
|
||||
return replaceInFile({
|
||||
|
|
|
|||
Loading…
Reference in New Issue