Compare commits

..

No commits in common. "master" and "v1.1.4-beta.108" have entirely different histories.

172 changed files with 8584 additions and 8784 deletions

View File

@ -31,7 +31,7 @@ body:
id: bn_version
attributes:
label: Test on Better Notes version
description: Please provide the Better Notes version you are using here. You can find this in the Settings -> Better Notes.
description: Please provide the Better Notes version you are using here. You can find this in the menu -> Edit -> Settings -> Better Notes.
placeholder: e.g. 1.0.4
validations:
required: true
@ -43,6 +43,7 @@ body:
- Item
- Text
- QuickInsert
- QuickBackLink
- QuickImport
- QuickNote
- ExportMDFileName

4
.github/FUNDING.yml vendored
View File

@ -6,8 +6,8 @@ open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
liberapay: windingwind
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ["https://paypal.me/windingwind"]
custom: ["https://paypal.me/windingwind?country.x=C2&locale.x=zh_XC"]

View File

@ -1,12 +1,9 @@
name: CI
name: Release
on:
push:
tags:
- v**
pull_request:
branches:
- master
permissions:
contents: write
@ -14,33 +11,10 @@ permissions:
pull-requests: write
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install deps
run: npm install -f
- name: Test
run: npm test
# If it's triggered by a tag and the test job is successful, release the package
release:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && needs.test.result == 'success'
env:
# Allow triggering other workflows
GITHUB_TOKEN: ${{ secrets.PAT }}
GITHUB_TOKEN: ${{ secrets.GitHub_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@ -1,19 +0,0 @@
name: Notify Telegram on Release
on:
release:
types: [published]
jobs:
send_message:
runs-on: ubuntu-latest
steps:
- name: Send Telegram Message
run: |
msg_text='
📢 A new release of ${{ github.repository }} is published: ${{ github.event.release.tag_name }}
Release Name: ${{ github.event.release.name }}
Description: ${{ github.event.release.body }}
You can check updates in Zotero to get the latest version, or view on GitHub: ${{ github.event.release.html_url }}'
curl -s -X POST 'https://api.telegram.org/bot${{ secrets.TG_BOT_TOKEN }}/sendMessage' \
-d "chat_id=${{ secrets.TG_CHAT_ID }}&text=${msg_text}&reply_to_message_id=${{ secrets.TG_MSG_ID }}"

3
.gitignore vendored
View File

@ -5,5 +5,4 @@ pnpm-lock.yaml
yarn.lock
zotero-cmd.json
.DS_Store
.env
.scaffold
.env

23
.vscode/launch.json vendored
View File

@ -1,4 +1,7 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
@ -6,14 +9,28 @@
"request": "launch",
"name": "StartDev",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "start"]
"runtimeArgs": ["run", "start-watch"]
},
{
"type": "node",
"request": "launch",
"name": "Lint",
"name": "Restart",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "lint"]
"runtimeArgs": ["run", "restart"]
},
{
"type": "node",
"request": "launch",
"name": "Reload",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "reload"]
},
{
"type": "node",
"request": "launch",
"name": "Restart in Prod Mode",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "restart-prod"]
}
]
}

View File

@ -1,3 +0,0 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}

View File

@ -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}",
"});",
],
},
"});"
]
}
}

139
README.md
View File

@ -2,13 +2,12 @@
[![zotero target version](https://img.shields.io/badge/Zotero-7-green?style=flat-square&logo=zotero&logoColor=CC2936)](https://www.zotero.org)
[![Using Zotero Plugin Template](https://img.shields.io/badge/Using-Zotero%20Plugin%20Template-blue?style=flat-square&logo=github)](https://github.com/windingwind/zotero-plugin-template)
[![telegram group](https://img.shields.io/badge/Join%20Community-@bnzotero-blue?style=flat-square&logo=telegram)](https://t.me/boost/bnzotero)
<div align=center><img src="./docs/res/teaser.png" width="800px"></img></div>
Everything about note management. All in Zotero.
Join the community on Telegram: [@bnzotero](https://t.me/boost/bnzotero)
Better Notes Handbook (outdated, for version<=0.8.9): [中文 (provide translation)](https://zotero.yuque.com/staff-gkhviy/better-notes/biigg4?)
## 🧩 Outline
@ -23,7 +22,7 @@ Join the community on Telegram: [@bnzotero](https://t.me/boost/bnzotero)
<details style="text-indent: 2em">
<summary>More</summary>
[Getting Started by Opening a Note Tab](#getting-started-by-opening-a-note-tab)
[Getting Started with the _Workspace_](#getting-started-with-the-workspace)
[Note Editor](#note-editor)
@ -88,11 +87,13 @@ and:
## 👋 Install
- Download the plugin (.xpi file) from below.
- Download the plugin (.xpi file) from below. For Zotero 7 beta, please always use the latest beta version.
- [Latest Version: 2.2.5](https://github.com/windingwind/zotero-better-notes/releases/download/v2.2.5/better-notes-for-zotero.xpi)
- [Latest Version: 1.1.4-beta.108](https://github.com/windingwind/zotero-better-notes/releases/download/v1.1.4-beta.108/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)
- [v1.0.4](https://github.com/windingwind/zotero-better-notes/releases/tag/1.0.4) (last for Zotero 6)
- [v0.8.9](https://github.com/windingwind/zotero-better-notes/releases/tag/0.8.9) (last with auto-insert, tag-insert, math-ocr, for Zotero 6)
- [All Releases](https://github.com/windingwind/zotero-better-notes/releases) (including beta plugin for Zotero 7 beta)
_Note_: If you're using Firefox as your browser, right-click the `.xpi` and select "Save As.."
@ -108,66 +109,61 @@ BN offers a range of features that can be combined like Lego blocks to build you
Start taking notes in Zotero with BN in **5 minutes**!
### Getting Started by Opening a Note Tab
### Getting Started with the _Workspace_
> 💡 In the latest version, the workspace is no longer a thing. You can open an unlimited number of note tabs/windows, which is what we called `workspace` in the past.
> 💡 This section is outdated and will be removed. For the latest beta version, the workspace is no longer a thing. You can open unlimited number of note tab/window, which is what we call `workspace` in the past.
To open a note in a tab, double-click/press `Enter` on the item in the library, as you would do to open an attachment. Holding `shift` opens the note in a new window.
The _workspace_ serves as the **central hub** where input flows (papers and annotations) converge with output flows (summaries and comparisons).
<div align=center><img src="https://github.com/user-attachments/assets/0824293b-765d-47af-8815-66f009adab0e" width="800px"></img></div>
To open the _workspace_, click the <img src="addon/chrome/content/icons/favicon.png" alt="icon" width="20px"> button in the tabs bar.
> **Explore the Note Tab!**
<div align=center><img src="https://user-images.githubusercontent.com/33902321/236622132-5ed9bd23-3c0e-4775-b273-745824cc4b51.gif" width="800px"></img></div>
The _workspace_ contains a default note called the _workspace note_. You can create a new note as the _workspace note_ if prompted on opening _workspace_.
> 💡 How to set an existing note as the _workspace note_?
>
> 1. In the library: select a note item and right-click
> 2. In the note editor: click on the Tools button
>
> You can change the _workspace note_ at any time.
The _workspace_ allows you to take notes and write, just like you would in MS Word or a markdown editor (e.g., Obsidian).
> **Explore the _Workspace_!**
> 💡 The layout from left to right is:
>
> - Outline
> - Note editor
> - Context pane (tags, related, relation graph, in/outbound links)
> - _Workspace note_ editor (main editor)
> - Note link preview (hidden by default)
> - Reader notes pane (hidden by default)
>
> 💡 To toggle these panes, hover the _workspace_ tab and click corresponding buttons.
> 💡 To open the _workspace_ in a new window, drag the _workspace_ tab.
### Note Editor
> 💡 Where can I find the note editor?
The _workspace_ includes the note editor for the _workspace note_. You can use it to take notes and write summaries.
> 💡 How to open note editor?
>
> - In the note tab/window
> - In the library: click to open a note editor in the item pane
> - In the PDF reader: right-side context pane
> - In the library: click to open a note editor and double-click to open note editor in a standalone window.
> - In the PDF reader: right-side bar
>
> 💡 How to create a new note?
> Click the note icon in the library tools bar (the row under the tabs bar), or from the menu - File
> Click the note icon in the library tools bar (the row under the tabs bar).
<div align=center><img src="https://github.com/user-attachments/assets/ec2ba415-8ec9-450d-9d73-d24d177ccd13" width="400px"></img></div>
#### Magic Key
BN enhances the note editor with a _Magic Key_ command palette, which can be opened by typing `/` in the editor. You can type or use the arrow keys to navigate the commands, and press `Enter` to execute.
<div align=center><img src="https://github.com/user-attachments/assets/bdbe244e-c120-4d9b-aa28-5285a25a723a" width="800px"></img></div>
#### Note Link Preview
BN enhances the note editor with link preview. Hover+Ctrl/Cmd or click the link to preview the linked note without leaving the current note.
<div align=center><img width="400px" alt="image" src="https://github.com/user-attachments/assets/b29769a1-3436-42bd-8481-eee1c0b4896a"></div>
#### Direct Markdown Paste
BN supports direct markdown paste. You can paste markdown content into the note editor, and it will be converted to the rich text format automatically.
<div align=center><img src="https://user-images.githubusercontent.com/33902321/236622355-2b8b2c00-a640-41fa-bb82-372fa10ecc64.png" width="400px"></img></div>
### Note Link
To create a _note link_ between the note you are editing and another note, click the <img src="addon/chrome/content/icons/favicon.png" width="20px"></img> button in the title bar of the note editor.
To create a _note link_ between current note and the _workspace note_, simply click the <img src="addon/chrome/content/icons/favicon.png" width="20px"></img> button in the title bar of current note editor.
<div align=center><img src="https://github.com/user-attachments/assets/e37a694b-613e-4242-9c14-d83708a3d1e7" width="800px"></img></div>
> 💡 What's the difference between `Mention in` and `Link to`?
>
> `Mention in` will insert a link of the current note (from which you open the link creator) to another note (which you pick in the link creator), i.e. inbound link.
> `Link to` will insert links of picked notes to the current note, i.e. outbound link.
You can also manually copy the note link from the note editor menu.
<div align=center><img src="https://user-images.githubusercontent.com/33902321/236622693-f7c7c82f-7434-4dbf-baf3-d03a72eb51c5.png" width="800px"></img></div>
### Note Template
Are you spending a lot of time writing summaries and copy-pasting while taking notes? Say hello to _Note Template_!
Still spending a lot of time writing summaries or doing copy-pasting while taking notes? Say hello to _Note Template_!
_Note Template_ is designed for tasks like:
@ -177,13 +173,13 @@ _Note Template_ is designed for tasks like:
> 💡 Need help or looking for community templates? [See here →](https://github.com/windingwind/zotero-better-notes/discussions/categories/note-templates)
>
> 💡 Want to write/share your templates?
> 💡 Want to write/share your own templates?
>
> [How to write →](docs/about-note-template.md#write-note-template)
>
> [How to share →](docs/about-note-template.md#share-your-template)
<div align=center><img src="https://github.com/user-attachments/assets/62e1438f-7910-4f57-ad88-c6a41dd9addf" width="800px"></img></div>
<div align=center><img src="https://user-images.githubusercontent.com/33902321/236623159-8f67064b-1fab-4cf1-abf4-0c8243370a14.gif" width="800px"></img></div>
### Syncing: Note 🔄️ Markdown
@ -211,9 +207,15 @@ You can export your note to the following formats:
Simply click on the corresponding export button in the toolbar and follow the prompts.
### LLM Integration
### GPT Integration
The [Zotero-GPT](https://github.com/MuiseDestiny/zotero-gpt) plugin provides GPT Integration. If you also have Better Notes installed, you can wake up its chatting pane in the note editor and insert/modify content in the note.
The [Zotero-GPT](https://github.com/MuiseDestiny/zotero-gpt) plugin provides GPT Integration. If you also have Better Notes installed, you can wake up GPT pane in the _workspace_ note editor with `space` key.
You can:
- Ask GPT questions about current note
- Summarize/fix spelling and grammar/translate/polish the selection
- Accept suggestions/modifications from GPT with `enter` key.
### Action Workflow
@ -226,7 +228,7 @@ The [Actions & Tags](https://github.com/windingwind/zotero-actions-tags) plugin
### Other Features
- Quick Note: convert annotation to note with one click.
- Resize images with a right-click menu.
- Resize images with right-click menu.
- Preview images with double-click/ctrl-click.
## 🧲 API
@ -239,24 +241,13 @@ BN provides APIs for other plugin developers in `Zotero.BetterNotes.api.${API_MO
- `template`: Manipulate note templates
- `$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.
- `editor`: Note editor APIs. Give your script the full control of contents in the note editor.
## 🔧 Development
This plugin is built based on the [Zotero Plugin Template](https://github.com/windingwind/zotero-plugin-template). See the setup and debug details there.
To start, run
To startup, run
```bash
git clone https://github.com/windingwind/zotero-better-notes.git
@ -267,31 +258,15 @@ 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): 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.
- [Translate for Zotero](https://github.com/windingwind/zotero-pdf-translate): PDF translation for Zotero
- [zotero-pdf-preview](https://github.com/windingwind/zotero-tag): PDF preview for Zotero
- [zotero-tag](https://github.com/windingwind/zotero-tag): Automatically tag items/Batch tagging
## 🙌 Sponsors

2
addon/bootstrap.js vendored
View File

@ -37,7 +37,7 @@ async function startup({ id, version, resourceURI, rootURI }, reason) {
`${rootURI}/chrome/content/scripts/__addonRef__.js`,
ctx,
);
await Zotero.__addonInstance__.hooks.onStartup();
Zotero.__addonInstance__.hooks.onStartup();
}
function onMainWindowLoad({ window: win }) {

View File

@ -1,102 +0,0 @@
<?xml version="1.0"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://zotero-platform/content/zotero.css" type="text/css"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://__addonRef__/content/styles/exportNotes.css" type="text/css"?>
<!-- prettier-ignore -->
<!DOCTYPE window>
<window
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
id="bn-export-notes"
data-l10n-id="title"
windowtype="__addonRef__-export-notes"
persist="screenX screenY width height sizemode"
style="min-width: 10em"
drawintitlebar-platforms="mac"
>
<xul:linkset>
<html:link rel="localization" href="browser/menubar.ftl" />
<html:link rel="localization" href="browser/browserSets.ftl" />
<html:link rel="localization" href="toolkit/global/textActions.ftl" />
<html:link rel="localization" href="zotero.ftl" />
<html:link rel="localization" href="__addonRef__-exportNotes.ftl" />
</xul:linkset>
<xul:commandset id="mainCommandSet">
<xul:command id="cmd_close" oncommand="window.close();" />
</xul:commandset>
<xul:keyset id="mainKeyset">
<xul:key
id="key_close"
data-l10n-id="close-shortcut"
command="cmd_close"
modifiers="accel"
reserved="true"
/>
</xul:keyset>
<script src="chrome://zotero/content/include.js"></script>
<script src="chrome://zotero/content/titlebar.js"></script>
<script src="chrome://zotero/content/customElements.js"></script>
<script src="chrome://__addonRef__/content/scripts/exportNotes.js"></script>
<dialog
buttons="accept, cancel, extra1"
buttonlabelextra1="Use System Export..."
>
<vbox>
<hbox>
<label id="target" data-l10n-id="target"></label>
</hbox>
<hbox align="center">
<label data-l10n-id="format" for="format"></label>
<menulist id="format" native="true">
<menupopup>
<menuitem
value="markdown"
data-l10n-id="format-markdown"
></menuitem>
<menuitem value="msword" data-l10n-id="format-msword"></menuitem>
<menuitem value="pdf" data-l10n-id="format-pdf"></menuitem>
<menuitem
value="freemind"
data-l10n-id="format-freemind"
></menuitem>
<menuitem value="note" data-l10n-id="format-note"></menuitem>
</menupopup>
</menulist>
</hbox>
<vbox>
<radiogroup id="linkMode" orient="vertical">
<radio value="keep" data-l10n-id="links-keep"></radio>
<radio value="embed" data-l10n-id="links-embed"></radio>
<radio value="standalone" data-l10n-id="links-standalone"></radio>
<!-- <radio value="remove" data-l10n-id="links-remove"></radio> -->
</radiogroup>
</vbox>
<vbox id="markdown-options">
<checkbox
id="markdown-autoSync"
data-l10n-id="markdown-autoSync"
native="true"
></checkbox>
<checkbox
id="markdown-withYAMLHeader"
data-l10n-id="markdown-withYAMLHeader"
native="true"
></checkbox>
<checkbox
id="markdown-autoFilename"
data-l10n-id="markdown-autoFilename"
native="true"
></checkbox>
</vbox>
</vbox>
</dialog>
</window>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="a" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<polygon
points="3.43 9.96 3.43 16.46 6.78 16.46 6.78 15.21 4.68 15.21 4.68 4.79 6.78 4.79 6.78 3.54 3.43 3.54 3.43 9.96"
style="stroke-width: 0px;" fill="currentColor" />
<polygon
points="16.57 10.04 16.57 3.54 13.22 3.54 13.22 4.79 15.32 4.79 15.32 15.21 13.22 15.21 13.22 16.46 16.57 16.46 16.57 10.04"
style="stroke-width: 0px;" fill="currentColor" />
<path
d="m6.23,12.33c0-.38.12-.69.36-.9.24-.22.5-.32.8-.32.21,0,.4.07.55.2.15.13.23.31.23.54,0,.51-.27.87-.81,1.07.2.17.42.26.65.26.4,0,.72-.24.96-.73.15-.27.39-1.07.71-2.4.33-1.34.49-2.13.49-2.37,0-.28-.08-.48-.24-.6-.16-.12-.35-.18-.56-.18-.4,0-.78.17-1.16.5-.38.33-.66.75-.84,1.25-.06.19-.12.31-.17.36-.05.05-.15.08-.3.09h-.08c-.28,0-.41-.08-.41-.25,0-.13.06-.33.19-.59.13-.26.31-.54.54-.84.23-.3.56-.56.98-.78.42-.22.86-.33,1.34-.33.88,0,1.53.29,1.97.87.55-.58,1.1-.87,1.65-.87.46,0,.86.13,1.21.38.35.26.53.61.53,1.05,0,.39-.12.69-.36.91s-.5.33-.8.33c-.22,0-.41-.07-.56-.21-.15-.14-.22-.32-.22-.54,0-.51.27-.87.82-1.07-.2-.17-.42-.26-.66-.26-.15,0-.29.03-.42.09s-.25.18-.35.35c-.11.17-.2.33-.27.49-.08.15-.16.39-.25.7-.09.31-.16.57-.21.79-.05.21-.13.53-.23.96-.1.43-.18.76-.25,1.01-.13.51-.2.88-.2,1.12,0,.28.08.48.25.6.17.12.36.19.57.19.4,0,.78-.17,1.16-.5.38-.33.66-.74.84-1.23.01-.02.02-.05.03-.1.01-.04.02-.07.03-.09s.02-.04.03-.07.02-.05.02-.06c0,0,.02-.03.03-.05s.03-.04.05-.04c.02,0,.04-.01.06-.02.02,0,.05-.02.07-.02h.2c.28,0,.41.08.41.24,0,.4-.29.92-.88,1.56-.59.65-1.31.97-2.16.97-.93,0-1.59-.29-2-.87h-.02c-.47.58-1.01.87-1.63.87-.45,0-.85-.13-1.2-.38-.35-.25-.53-.6-.53-1.05Z"
style="stroke-width: 0px;" fill="currentColor" />
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,6 +0,0 @@
<svg t="1728768259016" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4687"
width="20" height="20">
<path
d="M181.333333 509.866667v332.8H352.64v-64H245.333333V245.333333h107.306667v-64H181.333333v328.533334z m672.597334 4.266666v-332.8H682.666667v64h107.306666v533.333334H682.666667v64H853.930667v-328.533334z m-397.568 223.061334l85.930666-214.826667 84.736-211.84-59.434666-23.765333-84.693334 211.84-85.930666 214.826666 59.392 23.765334z"
fill="currentColor" p-id="4688"></path>
</svg>

Before

Width:  |  Height:  |  Size: 559 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 8V4.5V2H7.5H12C13.933 2 15.5 3.567 15.5 5.5C15.5 7.433 13.933 9 12 9C14.2091 9 16 10.7909 16 13C16 15.2091 14.2091 17 12 17H7.5H4V14.5V10.5V8ZM7.5 10.5V14.5H10.5C11.6046 14.5 12.5 13.6046 12.5 12.5C12.5 11.3954 11.6046 10.5 10.5 10.5H7.5ZM7.5 8V4.5H10.25C11.2165 4.5 12 5.2835 12 6.25C12 7.2165 11.2165 8 10.25 8H7.5Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 496 B

View File

@ -1,6 +0,0 @@
<svg t="1728768172242" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4279"
width="20" height="20">
<path
d="M256 426.666667a85.333333 85.333333 0 1 0 0-170.666667 85.333333 85.333333 0 0 0 0 170.666667z m597.333333-53.333334h-379.264v-64H853.333333v64z m0 298.666667h-379.264v-64H853.333333v64zM341.333333 640a85.333333 85.333333 0 1 1-170.666666 0 85.333333 85.333333 0 0 1 170.666666 0z"
fill="currentColor" p-id="4280"></path>
</svg>

Before

Width:  |  Height:  |  Size: 506 B

View File

@ -1,6 +0,0 @@
<svg t="1728768054402" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3427"
width="20" height="20">
<path
d="M170.666667 170.666667h682.666666v64H170.666667V170.666667z m597.333333 234.666666H256a21.333333 21.333333 0 0 0-21.333333 21.333334v170.666666a21.333333 21.333333 0 0 0 21.333333 21.333334h512a21.333333 21.333333 0 0 0 21.333333-21.333334v-170.666666a21.333333 21.333333 0 0 0-21.333333-21.333334zM256 341.333333h512a85.333333 85.333333 0 0 1 85.333333 85.333334v170.666666a85.333333 85.333333 0 0 1-85.333333 85.333334H256a85.333333 85.333333 0 0 1-85.333333-85.333334v-170.666666a85.333333 85.333333 0 0 1 85.333333-85.333334z m597.333333 448H170.666667V853.333333h682.666666v-64z"
fill="currentColor" p-id="3428"></path>
</svg>

Before

Width:  |  Height:  |  Size: 809 B

View File

@ -1,6 +0,0 @@
<svg t="1728768084775" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3633"
width="20" height="20">
<path
d="M469.333333 298.666667h85.333334v426.666666h-85.333334v-170.666666H298.666667v170.666666H213.333333V298.666667h85.333334v170.666666h170.666666V298.666667z m281.6 0c-25.6 38.4-64 72.533333-110.933333 85.333333v42.666667h85.333333v298.666666h85.333334V298.666667h-59.733334z"
fill="currentColor" p-id="3634"></path>
</svg>

Before

Width:  |  Height:  |  Size: 498 B

View File

@ -1,6 +0,0 @@
<svg t="1728768115138" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3879"
width="20" height="20">
<path
d="M384 302.933333h85.333333v426.666667H384v-170.666667H213.333333v170.666667H128v-426.666667h85.333333v170.666667h170.666667v-170.666667z m341.333333 341.333334c21.333333-17.066667 25.6-25.6 46.933334-46.933334 17.066667-17.066667 34.133333-34.133333 51.2-55.466666 12.8-17.066667 25.6-34.133333 38.4-55.466667 8.533333-17.066667 12.8-34.133333 12.8-55.466667 0-17.066667-4.266667-38.4-12.8-55.466666-8.533333-17.066667-17.066667-29.866667-34.133334-42.666667-12.8-12.8-29.866667-21.333333-51.2-25.6-21.333333-8.533333-42.666667-8.533333-64-8.533333-17.066667 0-29.866667 0-46.933333 4.266666-12.8 4.266667-29.866667 8.533333-42.666667 12.8-12.8 4.266667-25.6 12.8-38.4 21.333334-12.8 8.533333-25.6 17.066667-34.133333 29.866666l51.2 51.2c12.8-12.8 25.6-21.333333 42.666667-29.866666 17.066667-8.533333 29.866667-12.8 51.2-12.8s38.4 4.266667 55.466666 17.066666c12.8 12.8 21.333333 29.866667 21.333334 46.933334 0 17.066667-4.266667 34.133333-17.066667 46.933333-12.8 21.333333-25.6 38.4-42.666667 51.2-17.066667 17.066667-42.666667 38.4-68.266666 59.733333-25.6 21.333333-59.733333 46.933333-93.866667 68.266667v64h341.333333v-85.333333H725.333333z"
fill="currentColor" p-id="3880"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,6 +0,0 @@
<svg t="1728768147139" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4077"
width="20" height="20">
<path
d="M601.6 605.866667c17.066667 12.8 34.133333 21.333333 51.2 29.866666 17.066667 8.533333 38.4 12.8 59.733333 12.8 21.333333 0 42.666667-4.266667 59.733334-12.8 12.8-4.266667 21.333333-21.333333 21.333333-34.133333 0-8.533333 0-17.066667-4.266667-25.6-4.266667-8.533333-12.8-12.8-21.333333-17.066667-12.8-4.266667-29.866667-8.533333-42.666667-12.8-21.333333-4.266667-42.666667-4.266667-64-4.266666v-68.266667c29.866667 4.266667 64-4.266667 93.866667-17.066667 17.066667-8.533333 25.6-21.333333 25.6-38.4 0-12.8-4.266667-25.6-17.066667-34.133333-12.8-8.533333-29.866667-12.8-46.933333-12.8-17.066667 0-34.133333 4.266667-46.933333 12.8-17.066667 8.533333-29.866667 17.066667-46.933334 25.6l-51.2-59.733333c21.333333-17.066667 46.933333-29.866667 68.266667-38.4 21.333333-8.533333 51.2-12.8 76.8-12.8 21.333333 0 42.666667 4.266667 68.266667 8.533333 17.066667 4.266667 34.133333 12.8 51.2 21.333333 12.8 8.533333 25.6 21.333333 34.133333 34.133334 8.533333 12.8 12.8 29.866667 12.8 46.933333 0 21.333333-8.533333 38.4-21.333333 55.466667-17.066667 17.066667-38.4 29.866667-64 38.4v4.266666c25.6 4.266667 51.2 17.066667 68.266666 34.133334 17.066667 17.066667 29.866667 38.4 29.866667 64 0 17.066667-4.266667 34.133333-12.8 51.2-8.533333 17.066667-21.333333 29.866667-38.4 38.4-17.066667 12.8-38.4 17.066667-55.466667 21.333333-21.333333 4.266667-42.666667 8.533333-68.266666 8.533333-34.133333 0-68.266667-4.266667-98.133334-17.066666-25.6-8.533333-46.933333-25.6-68.266666-42.666667l46.933333-59.733333zM384 469.333333H213.333333V298.666667H128v426.666666h85.333333v-170.666666h170.666667v170.666666h85.333333V298.666667H384v170.666666z"
fill="currentColor" p-id="4078"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="a" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<path d="m6.12,16l.88-.88L1.88,10l5.12-5.12-.88-.88L.12,10l6,6Zm7.77,0l-.88-.88,5.12-5.12-5.12-5.12.88-.88,6,6-6,6Z"
style="fill-rule: evenodd; stroke-width: 0px;" fill="currentColor" />
<path
d="m6.23,12.33c0-.39.12-.69.36-.9s.5-.32.8-.32c.21,0,.4.07.55.2s.23.31.23.54c0,.51-.27.87-.81,1.07.2.17.42.26.65.26.4,0,.72-.25.96-.73.15-.27.39-1.07.71-2.4s.49-2.13.49-2.37c0-.28-.08-.48-.24-.6s-.34-.18-.56-.18c-.4,0-.78.17-1.16.5s-.66.75-.84,1.25c-.06.19-.12.31-.17.36s-.15.08-.3.09h-.08c-.28,0-.41-.08-.41-.25,0-.13.06-.33.19-.59s.31-.54.54-.84.56-.56.98-.78.86-.33,1.34-.33c.88,0,1.53.29,1.97.87.55-.58,1.1-.87,1.65-.87.46,0,.86.13,1.21.38s.53.61.53,1.05c0,.39-.12.69-.36.91s-.5.33-.8.33c-.22,0-.41-.07-.56-.21s-.22-.32-.22-.54c0-.51.27-.87.82-1.07-.2-.17-.42-.26-.66-.26-.15,0-.29.03-.42.09s-.25.18-.35.35-.2.33-.27.49-.16.39-.25.7-.16.57-.21.79-.13.53-.23.96-.18.76-.25,1.01c-.13.51-.2.88-.2,1.12,0,.28.08.48.25.6s.36.19.57.19c.4,0,.78-.17,1.16-.5s.66-.74.84-1.23c.01-.02.02-.05.03-.1s.02-.07.03-.09.02-.04.03-.07.02-.05.02-.06.02-.03.03-.05.03-.04.05-.04.04-.01.06-.02.05-.02.07-.02h.2c.28,0,.41.08.41.24,0,.4-.29.92-.88,1.56s-1.31.97-2.16.97c-.93,0-1.59-.29-2-.87h-.02c-.47.58-1.01.87-1.63.87-.45,0-.85-.13-1.2-.38-.35-.25-.53-.6-.53-1.05Z"
style="stroke-width: 0px;" fill="currentColor" />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="a" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<path d="m6.12,16l.88-.88L1.88,10l5.12-5.12-.88-.88L.12,10l6,6Zm7.77,0l-.88-.88,5.12-5.12-5.12-5.12.88-.88,6,6-6,6Z"
style="fill-rule: evenodd; stroke-width: 0px;" fill="currentColor" />
<polygon points="8.91 14.4 10.59 10.2 12.25 6.07 11.09 5.6 9.43 9.74 7.75 13.93 8.91 14.4" style="stroke-width: 0px;"
fill="currentColor" />
</svg>

Before

Width:  |  Height:  |  Size: 476 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 2H15V4H12.0164L11.9839 4.17889L10.0164 15H13V17H5V15H7.98361L8.01613 14.8211L9.98361 4H7V2Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 270 B

View File

@ -1,10 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1132_37385)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 8.125C0 5.70875 1.95875 3.75 4.375 3.75H9.625C12.0412 3.75 14 5.70875 14 8.125C14 10.5412 12.0412 12.5 9.625 12.5H8.60669C8.5376 12.3045 8.5 12.0941 8.5 11.875C8.5 11.6559 8.5376 11.4455 8.60669 11.25H9.625C11.3509 11.25 12.75 9.85089 12.75 8.125C12.75 6.39911 11.3509 5 9.625 5H4.375C2.64911 5 1.25 6.39911 1.25 8.125C1.25 9.85089 2.64911 11.25 4.375 11.25H4.78433C4.76165 11.4552 4.75 11.6637 4.75 11.875C4.75 12.0863 4.76165 12.2948 4.78433 12.5H4.375C1.95875 12.5 0 10.5412 0 8.125ZM10.3751 7.49999H11.3934C11.4625 7.69547 11.5001 7.90584 11.5001 8.12499C11.5001 8.34413 11.4625 8.5545 11.3934 8.74999H10.3751C8.64919 8.74999 7.25008 10.1491 7.25008 11.875C7.25008 13.6009 8.64919 15 10.3751 15H15.6251C17.351 15 18.7501 13.6009 18.7501 11.875C18.7501 10.1491 17.351 8.74999 15.6251 8.74999H15.2157C15.2384 8.54478 15.2501 8.33624 15.2501 8.12499C15.2501 7.91373 15.2384 7.7052 15.2157 7.49999H15.6251C18.0413 7.49999 20.0001 9.45874 20.0001 11.875C20.0001 14.2912 18.0413 16.25 15.6251 16.25H10.3751C7.95883 16.25 6.00008 14.2912 6.00008 11.875C6.00008 9.45874 7.95883 7.49999 10.3751 7.49999Z" fill="currentColor"/>
</g>
<defs>
<clipPath id="clip0_1132_37385">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,10 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6179_36208)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.0971 9L11.0138 9.50002L9.99326 15.6224C9.62633 17.8241 7.5441 19.3114 5.34247 18.9444C4.24166 18.761 3.31942 18.1487 2.71826 17.307L4.34573 16.1446C4.64939 16.5697 5.11523 16.879 5.67127 16.9716C6.78335 17.157 7.83513 16.4057 8.02048 15.2936L8.98619 9.50002L9.06953 9H4.99999V7H9.40286L10.0066 3.37761C10.3735 1.17599 12.4558 -0.311319 14.6574 0.055618C15.7582 0.239087 16.6804 0.851379 17.2816 1.69301L15.6541 2.85548C15.3505 2.43036 14.8846 2.12108 14.3286 2.02841C13.2165 1.84306 12.1647 2.59433 11.9794 3.70641L11.4305 7H16V9H11.0971Z" fill="currentColor"/>
</g>
<defs>
<clipPath id="clip0_6179_36208">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 866 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.11621 16L7.00009 15.1161L1.88398 10L7.00009 4.88388L6.11621 4L0.116211 10L6.11621 16ZM13.884 16L13.0001 15.1161L18.1162 10L13.0001 4.88388L13.884 4L19.884 10L13.884 16Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 347 B

View File

@ -1,6 +0,0 @@
<svg t="1728768200791" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4481"
width="20" height="20">
<path
d="M256 226.389333V426.666667H213.333333V285.610667l-35.925333 11.946666-13.482667-40.448 64-21.333333 28.074667-9.386667zM853.333333 373.333333h-379.264v-64H853.333333v64z m0 298.666667h-379.264v-64H853.333333v64zM194.730667 530.688c20.565333-6.101333 52.437333-10.410667 72.618666 15.658667 10.794667 13.952 12.202667 31.829333 9.984 46.506666-3.242667 21.418667-17.194667 47.914667-28.928 70.186667-3.712 7.082667-7.253333 13.738667-10.069333 19.626667H277.333333v42.666666H162.816c10.794667-18.645333 20.778667-35.712 30.592-52.522666l31.274667-53.802667c5.376-9.386667 15.786667-33.450667 6.826666-45.013333-3.84-4.949333-13.994667-10.325333-28.501333-5.973334-13.141333 3.84-24.874667 14.378667-33.024 21.674667l-0.298667 0.256-5.546666-46.165333c8.96-4.864 19.626667-9.813333 30.592-13.098667z"
fill="currentColor" p-id="4482"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1023 B

View File

@ -1,6 +0,0 @@
<svg t="1728767929805" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3225"
width="20" height="20">
<path
d="M170.666667 373.333333h682.666666v-64H170.666667v64z m341.333333 298.666667h341.333333v-64h-341.333333v64z m-342.613333 105.386667l126.72-126.72-126.72-126.72 45.226666-45.226667 149.333334 149.333333 22.613333 22.613334-22.613333 22.613333-149.333334 149.333333-45.226666-45.226666z"
fill="currentColor" p-id="3226"></path>
</svg>

Before

Width:  |  Height:  |  Size: 509 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C8.85166 2 7.64614 2.28406 6.6953 2.91795C5.71482 3.5716 5 4.61209 5 6C5 6.77149 5.16552 7.44802 5.49725 8.02784C5.71987 8.41695 6.00217 8.73606 6.31739 9H2V10.25H9.10026C9.38748 10.3245 9.66916 10.3907 9.93645 10.4535L9.93646 10.4536L10.021 10.4734C11.1302 10.7344 12.0126 10.9532 12.6404 11.3471C12.9309 11.5294 13.1326 11.7308 13.2668 11.9653C13.3999 12.198 13.5 12.5215 13.5 13C13.5 13.9401 13.1463 14.4997 12.6183 14.8653C12.0364 15.2682 11.1404 15.5 10 15.5C7.79256 15.5 6.5 14.2197 6.5 13H4.5C4.5 15.7803 7.20744 17.5 10 17.5C11.3596 17.5 12.7136 17.2318 13.7567 16.5097C14.8537 15.7503 15.5 14.5599 15.5 13C15.5 12.2285 15.3345 11.552 15.0028 10.9722C14.8462 10.6985 14.6602 10.4595 14.4539 10.25H18V9H12.2582C11.6828 8.80946 11.0947 8.67127 10.5635 8.54645L10.5635 8.54645L10.479 8.52658C9.36982 8.26559 8.48741 8.04685 7.85962 7.65294C7.56905 7.47062 7.36738 7.26916 7.23322 7.03466C7.1001 6.80198 7 6.47851 7 6C7 5.38791 7.28518 4.9284 7.8047 4.58205C8.35386 4.21594 9.14834 4 10 4C10.8517 4 11.6461 4.21594 12.1953 4.58205C12.7148 4.9284 13 5.38791 13 6H15C15 4.61209 14.2852 3.5716 13.3047 2.91795C12.3539 2.28406 11.1483 2 10 2Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.809 9.5L1.95605 2H4.33823L8.00008 7.65923L11.6619 2H14.0441L9.19117 9.5L14.0441 17H11.6619L8.00008 11.3408L4.33823 17H1.95605L6.809 9.5ZM17.4697 15.2197L15 17.6893V19H15.5H20V17.5H17.3107L18.5303 16.2803C19.3008 15.5099 20 14.5711 20 13.5C20 12.9749 19.8289 12.3634 19.4242 11.8688C19.0004 11.3508 18.3498 11 17.5 11C16.6502 11 15.9996 11.3508 15.5758 11.8688C15.1711 12.3634 15 12.9749 15 13.5H16.5C16.5 13.2751 16.5789 13.0116 16.7367 12.8187C16.8754 12.6492 17.0998 12.5 17.5 12.5C17.9002 12.5 18.1246 12.6492 18.2633 12.8187C18.4211 13.0116 18.5 13.2751 18.5 13.5C18.5 13.9289 18.1992 14.4901 17.4697 15.2197Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 792 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.4697 4.21967L15 6.68934V8H15.5H20V6.5H17.3107L18.5303 5.28033C19.3008 4.50988 20 3.57109 20 2.5C20 1.97495 19.8289 1.36341 19.4242 0.868822C19.0004 0.350834 18.3498 0 17.5 0C16.6502 0 15.9996 0.350834 15.5758 0.868822C15.1711 1.36341 15 1.97495 15 2.5H16.5C16.5 2.27505 16.5789 2.01159 16.7367 1.81868C16.8754 1.64917 17.0998 1.5 17.5 1.5C17.9002 1.5 18.1246 1.64917 18.2633 1.81868C18.4211 2.01159 18.5 2.27505 18.5 2.5C18.5 2.92891 18.1992 3.49012 17.4697 4.21967ZM6.809 9.5L1.95605 2H4.33823L8.00008 7.65923L11.6619 2H14.0441L9.19117 9.5L14.0441 17H11.6619L8.00008 11.3408L4.33823 17H1.95605L6.809 9.5Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 785 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.75 3.25V6.75H3.25V3.25H16.75ZM3.25 8H7V11.75H3.25V8ZM8.25 11.75V8H11.75V11.75H8.25ZM11.75 13H8.25V16.75H11.75V13ZM13 16.75V13H16.75V16.75H13ZM13 11.75V8H16.75V11.75H13ZM3.25 13H7V16.75H3.25V13ZM18 2H2V18H18V2Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 389 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 14L11 2H9L4 14H6.16667L7.41667 11H12.5833L13.8333 14H16ZM10 4.8L8.04167 9.5H11.9583L10 4.8ZM2.25 17.75V16.25H17.75V17.75H2.25ZM1 15H2.25H17.75H19V16.25V17.75V19H17.75H2.25H1V17.75V16.25V15Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 369 B

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 2H4V11C4 14.5836 6.71815 17 10 17C13.2819 17 16 14.5836 16 11V2H14V11C14 13.4164 12.241 15 10 15C7.75901 15 6 13.4164 6 11V2ZM4 19V17.75H16V19H4Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 324 B

View File

@ -43,7 +43,7 @@
align-items: center;
}
</style>
<link rel="stylesheet" href="./styles/toolbutton.css" />
<link rel="stylesheet" href="./toolbutton.css" />
<script>
window.addEventListener("DOMContentLoaded", (e) => {
document.querySelector(".container").style["line-height"] = `${

View File

@ -560,10 +560,10 @@
margin-bottom: 0 !important;
}
/* .markdown-body a:not([href]) {
.markdown-body a:not([href]) {
color: inherit;
text-decoration: none;
} */
}
.markdown-body .absent {
color: var(--color-danger-fg);

View File

@ -2,6 +2,7 @@
* 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"
);

View File

@ -44,7 +44,7 @@
</xul:keyset>
<script src="chrome://zotero/content/include.js"></script>
<script src="chrome://zotero/content/titlebar.js"></script>
<script src="chrome://zotero/content/title.js"></script>
<script src="chrome://zotero/content/customElements.js"></script>
<script src="chrome://__addonRef__/content/scripts/customElements.js"></script>
<script src="chrome://__addonRef__/content/scripts/linkCreator.js"></script>

View File

@ -16,11 +16,6 @@
native="true"
preference="__prefsPrefix__.openNote.defaultAsWindow"
/>
<checkbox
data-l10n-id="basic-exportNotes-takeover"
native="true"
preference="__prefsPrefix__.exportNotes.takeover"
/>
</groupbox>
<groupbox>
<label><html:h2 data-l10n-id="editor-title"></html:h2></label>
@ -43,31 +38,10 @@
native="true"
preference="__prefsPrefix__.workspace.outline.keepLinks"
/>
<hbox align="center">
<html:label
data-l10n-id="editor-noteLinkPreviewType"
for="__addonRef__-editor-noteLinkPreviewType"
></html:label>
<radiogroup
id="__addonRef__-editor-noteLinkPreviewType"
preference="__prefsPrefix__.editor.noteLinkPreviewType"
orient="horizontal"
oncommand="Zotero.__addonInstance__.api.utils.requireRestart();"
>
<radio data-l10n-id="editor-noteLinkPreview-hover" value="hover" />
<radio data-l10n-id="editor-noteLinkPreview-ctrl" value="ctrl" />
<radio data-l10n-id="editor-noteLinkPreview-disable" value="disable" />
</radiogroup>
</hbox>
<checkbox
data-l10n-id="editor-useMagicKey"
data-l10n-id="editor-noteLinkPreview"
native="true"
preference="__prefsPrefix__.editor.useMagicKey"
/>
<checkbox
data-l10n-id="editor-useMarkdownPaste"
native="true"
preference="__prefsPrefix__.editor.useMarkdownPaste"
preference="__prefsPrefix__.editor.noteLinkPreview"
/>
</groupbox>
<groupbox>
@ -85,7 +59,6 @@
placeholder="-1 for disable"
id="__addonRef__-sync-period"
preference="__prefsPrefix__.syncPeriodSeconds"
onchange="Zotero.__addonInstance__.api.utils.requireRestart();"
></html:input>
</hbox>
<hbox align="center">
@ -114,14 +87,6 @@
></button>
</hbox>
</groupbox>
<groupbox>
<label><html:h2 data-l10n-id="annotationNote-title"></html:h2></label>
<checkbox
data-l10n-id="annotationNote-enableTagSync"
native="true"
preference="__prefsPrefix__.annotationNote.enableTagSync"
/>
</groupbox>
<groupbox>
<label><html:h2 data-l10n-id="about-title"></html:h2></label>

View File

@ -23,10 +23,6 @@
var parser = new DOMParser();
var serializer = new XMLSerializer();
var htmlString = e.data.html;
const styleString = e.data.style;
const style = document.createElement("style");
style.innerHTML = styleString;
document.head.appendChild(style);
var htmlDoc = parser.parseFromString(htmlString, "text/html");
var xhtmlString = serializer.serializeToString(htmlDoc);
document.querySelector(".markdown-body").innerHTML = xhtmlString;

View File

@ -21,6 +21,9 @@
</style>
<script>
var browser;
var { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm",
);
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm",
);

View File

@ -1,8 +0,0 @@
dialog {
-moz-window-dragging: drag;
}
#markdown-autoSync {
margin-inline-start: 18px;
margin-block-end: 24px;
}

View File

@ -8,14 +8,6 @@
overflow: auto;
}
window {
-moz-window-dragging: drag;
}
#top-container {
-moz-window-dragging: no-drag;
}
/* TODO: remove fx115 workaround */
tab {
color: unset !important;

View File

@ -24,21 +24,10 @@ bn-note-picker {
#collections-items-container {
margin-bottom: 0;
}
#zotero-items-pane-content {
min-height: 100%;
}
}
#bn-select-opened-notes-container {
min-width: 200px;
max-height: 50%;
}
.bn-note-list-container {
width: 100%;
}
#bn-select-recent-notes-content {
border-left: var(--material-border-quarternary);
}
}

View File

@ -1,133 +0,0 @@
html,
body {
min-width: 600px;
min-height: 400px;
}
html,
body,
.viewport {
padding: 0;
margin: 0;
height: 100%;
word-wrap: break-word;
}
.viewport {
flex-grow: 1;
flex-shrink: 1;
margin: 0 5px 0 5px;
overflow-x: hidden;
overflow-y: auto;
}
.viewport-container {
padding: 0;
margin: 0;
height: calc(100% - 50px);
width: 100%;
display: flex;
flex-direction: row;
overflow: hidden;
border-bottom: var(--material-border);
background: var(--material-background);
}
.footer-container {
padding: 5px;
}
.list-viewport {
width: calc(30% - 10px);
height: 100%;
overflow: hidden;
}
#table-container {
height: 100%;
width: 100%;
overflow: auto;
}
#templates-table {
height: 100%;
}
.editor-viewport {
display: flex;
flex-direction: column;
width: calc(40% - 10px);
padding: 5px;
}
.preview-viewport {
display: flex;
flex-direction: column;
width: calc(30% - 10px);
padding: 5px;
}
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 0px;
}
.help-button {
appearance: auto;
-moz-default-appearance: -moz-mac-help-button;
min-width: 0;
}
.editor-button-container {
display: flex;
flex-wrap: wrap;
gap: 4px;
padding: 4px;
}
.editor-button-container[hidden] {
display: none;
}
.format {
width: 28px;
height: 28px;
border-radius: 5px;
flex-grow: 0;
flex-shrink: 0;
margin: 0;
background-repeat: no-repeat;
background-position: center;
}
.format:hover {
background-color: var(--fill-quinary);
}
.format:active {
background-color: var(--fill-quarternary);
}
.snippet {
border: var(--material-panedivider);
border-radius: 4px;
cursor: pointer;
font-size: 0.916666667em;
line-height: 1.272727273;
overflow: hidden;
padding: 1px 4px;
text-overflow: ellipsis;
white-space: pre;
box-sizing: border-box;
color: var(--fill-primary);
}
.snippet.syntax {
background-color: color-mix(
in srgb,
var(--accent-yellow) 50%,
transparent 50%
);
}
.snippet.expression {
background-color: color-mix(
in srgb,
var(--accent-green) 50%,
transparent 50%
);
}
.snippet.variable {
background-color: color-mix(
in srgb,
var(--accent-azure) 50%,
transparent 50%
);
}
.snippet:hover {
background-color: var(--fill-quinary);
}

View File

@ -1,24 +0,0 @@
dialog {
-moz-window-dragging: drag;
max-height: 700px;
}
.viewport-container {
-moz-window-dragging: no-drag;
height: 100%;
}
.viewport {
width: 100%;
}
#table-container {
width: 100%;
height: 100%;
overflow: auto;
background: var(--material-background);
}
.virtualized-table {
height: 100%;
}

View File

@ -8,7 +8,10 @@
type="text/css"
href="chrome://__addonRef__/content/lib/css/dx.light.compact.css"
/>
<link rel="stylesheet" href="./styles/toolbutton.css" />
<link
rel="stylesheet"
href="chrome://__addonRef__/content/toolbutton.css"
/>
<link
rel="stylesheet"
type="text/css"
@ -70,7 +73,6 @@
}
.footer-container {
padding: 5px;
gap: 8px;
margin: 0;
height: 60px;
width: 100%;

View File

@ -44,6 +44,10 @@
</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,
@ -103,7 +107,7 @@
</div>
<div
class="footer-container"
style="justify-content: flex-start; padding: 10px; gap: 8px"
style="justify-content: flex-start; padding: 10px"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
<button id="refresh" data-l10n-id="refresh"></button>

View File

@ -45,6 +45,10 @@
</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,
@ -57,18 +61,79 @@
window.arguments[0]._initPromise.resolve();
});
</script>
<style>
html,
body {
min-width: 600px;
min-height: 400px;
}
html,
body,
.viewport {
padding: 0;
margin: 0;
height: 100%;
word-wrap: break-word;
}
.viewport {
flex-grow: 1;
flex-shrink: 1;
margin: 0 5px 0 5px;
overflow-x: hidden;
overflow-y: auto;
}
.viewport-container {
padding: 0;
margin: 0;
height: calc(100% - 50px);
width: 100%;
display: flex;
flex-direction: row;
overflow: hidden;
border-bottom: var(--material-border);
background: var(--material-background);
}
.footer-container {
padding: 5px;
}
.list-viewport {
width: calc(20% - 10px);
height: 100%;
overflow: hidden;
}
#table-container {
height: 100%;
width: 100%;
overflow: auto;
}
#templates-table {
height: 100%;
}
.editor-viewport {
display: flex;
flex-direction: column;
width: calc(40% - 10px);
padding: 5px;
}
.preview-viewport {
display: flex;
flex-direction: column;
width: calc(40% - 10px);
padding: 5px;
}
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 0px;
}
</style>
<link
rel="stylesheet"
type="text/css"
href="chrome://__addonRef__/content/lib/css/github-markdown.css"
/>
<link
rel="stylesheet"
href="chrome://__addonRef__/content/lib/css/katex.min.css"
/>
<link
rel="stylesheet"
href="chrome://__addonRef__/content/styles/templateEditor.css"
/>
</head>
<body class="zotero-window">
<div class="viewport-container">
@ -81,40 +146,10 @@
orient="horizontal"
></xul:splitter>
<xul:hbox class="viewport editor-viewport">
<xul:hbox align="center">
<div style="flex-shrink: 0" data-l10n-id="templateType"></div>
<xul:menulist id="editor-type" native="true">
<xul:menupopup>
<xul:menuitem
data-l10n-id="templateType-unknown"
value="unknown"
></xul:menuitem>
<xul:menuitem
data-l10n-id="templateType-system"
value="system"
hidden="true"
></xul:menuitem>
<xul:menuitem
data-l10n-id="templateType-item"
value="item"
></xul:menuitem>
<xul:menuitem
data-l10n-id="templateType-text"
value="text"
></xul:menuitem>
</xul:menupopup>
</xul:menulist>
<xul:button
id="templateType-help"
data-l10n-id="templateType-help"
class="help-button"
></xul:button>
</xul:hbox>
<xul:hbox align="center">
<div style="display: flex; align-items: center">
<div style="flex-shrink: 0" data-l10n-id="templateName"></div>
<input id="editor-name" type="text" style="width: 100%" />
</xul:hbox>
<div id="formats-container" class="editor-button-container"></div>
</div>
<div style="display: flex; flex-direction: column; height: 100%">
<iframe
id="editor"
@ -123,7 +158,6 @@
onmousedown="this.focus()"
></iframe>
</div>
<div id="snippets-container" class="editor-button-container"></div>
</xul:hbox>
<xul:splitter
state="open"
@ -139,14 +173,13 @@
</div>
<div
class="footer-container"
style="justify-content: flex-start; padding: 10px; gap: 8px"
style="justify-content: flex-start; padding: 10px"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
<button id="create" data-l10n-id="create"></button>
<button id="save" data-l10n-id="save"></button>
<button id="delete" data-l10n-id="delete"></button>
<button id="reset" data-l10n-id="reset"></button>
<button id="share" data-l10n-id="share"></button>
<button id="more" data-l10n-id="more"></button>
<button
id="options"
@ -162,6 +195,8 @@
></menuitem>
<menuitem id="importNote" data-l10n-id="importNote"></menuitem>
<menuseparator />
<menuitem id="share" data-l10n-id="share"></menuitem>
<menuseparator />
<menuitem id="backup" data-l10n-id="backup"></menuitem>
<menuitem id="restore" data-l10n-id="restore"></menuitem>
<menuseparator />

View File

@ -1,58 +0,0 @@
<?xml version="1.0"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://zotero-platform/content/zotero.css" type="text/css"?>
<!-- prettier-ignore -->
<?xml-stylesheet href="chrome://__addonRef__/content/styles/templatePicker.css" type="text/css"?>
<!-- prettier-ignore -->
<!DOCTYPE window>
<window
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
id="bn-note-picker"
data-l10n-id="title"
windowtype="__addonRef__-templatePicker"
persist="screenX screenY width height sizemode"
style="min-width: 20em"
drawintitlebar-platforms="mac"
>
<xul:linkset>
<html:link rel="localization" href="browser/menubar.ftl" />
<html:link rel="localization" href="browser/browserSets.ftl" />
<html:link rel="localization" href="toolkit/global/textActions.ftl" />
<html:link rel="localization" href="zotero.ftl" />
<html:link rel="localization" href="__addonRef__-templatePicker.ftl" />
</xul:linkset>
<xul:commandset id="mainCommandSet">
<xul:command id="cmd_close" oncommand="window.close();" />
</xul:commandset>
<xul:keyset id="mainKeyset">
<xul:key
id="key_close"
data-l10n-id="close-shortcut"
command="cmd_close"
modifiers="accel"
reserved="true"
/>
</xul:keyset>
<script src="chrome://zotero/content/include.js"></script>
<script src="chrome://zotero/content/titlebar.js"></script>
<script src="resource://zotero/require.js"></script>
<script src="chrome://zotero/content/customElements.js"></script>
<script src="chrome://__addonRef__/content/scripts/customElements.js"></script>
<script src="chrome://__addonRef__/content/scripts/templatePicker.js"></script>
<dialog buttons="accept, cancel">
<hbox class="viewport-container">
<hbox id="list-container" class="viewport list-viewport">
<html:div id="table-container"></html:div>
</hbox>
</hbox>
</dialog>
</window>

View File

@ -412,7 +412,7 @@
? expandedStatus[node.model.name]
: node.model.level < expandLevel,
parentId:
node.parent.model.id !== -1
node.parent.model.id > 0
? String(node.parent.model.id)
: undefined,
});

View File

@ -1,5 +1,7 @@
pref-title = Better Notes
menuItem-exportNote = Export Note
menuEdit-exportTemplate = Export Template to File...
menuEdit-templateEditor = Template Editor
menuEdit-importTemplate = New Template from Clipboard
@ -16,27 +18,7 @@ menuEditor-resizeImage = Resize Image
menuHelp-openUserGuide = Open Better Notes User Guide
templateEditor-templateType = Type
templateEditor-templateName = Name
templateEditor-templateDisplayName =
.QuickInsertV2 = Quick Insert (Link)
.QuickImportV2 = Quick Import (Embed)
.QuickNoteV5 = Quick Note (From Annotation)
.ExportMDFileNameV2 = Export MD File Name
.ExportMDFileHeaderV2 = Export MD File Header
.ExportMDFileContent = Export MD File Content
templateEditor-templateDisplayType =
.system = Builtin
.item = Item
.text = Text
.unknown = ?
templateEditor-templateHelp =
.system = For specific purposes, e.g., generating note link.
.item = Can generate note fragments from one or more selected items as input.
.text = Can generate note fragments. It doesn't require any input.
templateEditor-templateName = Template Name
editor-resizeImage-title = Resize Image
editor-resizeImage-prompt = Resize image width to:
@ -83,7 +65,7 @@ editor-toolbar-settings-openAsTab = Open as tab
editor-toolbar-settings-openAsWindow = Open as window
editor-toolbar-settings-showInLibrary = Show in Library
editor-toolbar-settings-insertTemplate = Insert template
editor-toolbar-settings-refreshTemplates = Update content from templates
editor-toolbar-settings-refreshTemplates = Update content from templates (Beta)
editor-toolbar-settings-copyLink = Copy link (L{ $line })
editor-toolbar-settings-copyLinkAtSection = Copy link (Sec. { $section })
editor-toolbar-settings-openParent = Open Attachment
@ -101,7 +83,6 @@ alert-notValidParentItemError = No valid parent item.
alert-syncImportedNotes = Keep imported notes in sync with MarkDown files?
alert-linkCreator-emptyNote = Cannot create link from/to an empty note.
alert-templateEditor-shouldImport = Seems like you are trying to directly save a note template share code. Do you want to import it as a template?
alert-templateEditor-unsaved = You have unsaved changes in the template editor. Do you want to save them?
userGuide-start-title = Welcome to Better Notes!
userGuide-start-desc = Better Notes is a powerful note-taking tool that helps you organize your thoughts and ideas while reading papers. This guide will help you get started with Better Notes and show you how to make the most of its features.

View File

@ -0,0 +1,25 @@
title = Export Notes
options-linkMode = Linked Notes Mode
options-MD = MarkDown(.md)
options-Docx = MS Word(.docx)
options-PDF = PDF(.pdf)
options-mm = Mind Map
options-note = Zotero Note
embedLink = All Embedded in One Export
standaloneLink = Each Converted to Standalone Exports
keepLink = Keep Zotero Links(zotero://note/)
exportMD = Export MD File(s)
setAutoSync = Set Auto-Sync
.title = Auto-Sync is available for "Each Converted to Standalone Exports" mode.
withYAMLHeader = With YAML Header
autoMDFileName = Auto Generate MD File Name
exportDocx = Export Docx File
exportPDF = Export PDF File
exportFreeMind = Export FreeMind File
exportNote = Export to New Zotero Note Item
confirm = Export
cancel = Close
target = Target: {$title}{ $left ->
[0]{ "" }
*[other] { " " }and {$left} more.
}

View File

@ -1,37 +0,0 @@
title =
.title = Export Notes with Better Notes
target =
.value = Target: {$title}{ $left ->
[0]{ "" }
*[other] { " " }and {$left} more.
}
format =
.value = Format:
format-markdown =
.label = MarkDown(.md)
format-msword =
.label = MS Word(.docx)
format-pdf =
.label = PDF(.pdf)
format-freemind =
.label = Mind Map
format-note =
.label = Zotero Note
links-keep =
.label = Keep note links(zotero://note/)
links-embed =
.label = Embed linked notes in the content
links-standalone =
.label = Convert linked notes to standalone exports
links-remove =
.label = Remove note links
markdown-autoSync =
.label = Set auto-sync for each note
.title = Auto-sync is available for "Convert linked notes to standalone exports" mode.
markdown-withYAMLHeader =
.label = With YAML header
markdown-autoFilename =
.label = Auto generate file name

View File

@ -3,27 +3,13 @@ basic-openNote-takeover =
.label = Take over opening note
basic-openNote-defaultAsWindow =
.label = Open note as window by default
basic-exportNotes-takeover =
.label = Take over exporting notes
editor-title = Note Editor
editor-expandLevel-label = Outline expand to heading level
editor-keepLinks =
.label = Show note links in outline
editor-noteLinkPreviewType = Show preview for note link when:
editor-noteLinkPreview-hover =
.label = Hover
editor-noteLinkPreview-ctrl =
.label = Press { PLATFORM() ->
[macos] ⌘
*[other] Ctrl
}
editor-noteLinkPreview-disable =
.label = Never
editor-useMagicKey =
.label = Use magic key "/" to show command palette
editor-useMarkdownPaste =
.label = Use enhanced markdown paste
editor-noteLinkPreview =
.label = Show note link preview on hover
sync-title = Sync
sync-period-label = Auto-sync period (seconds)
@ -37,10 +23,6 @@ annotation-title = PDF Annotation
annotation-autoAnnotation =
.label = Automatically add new annotations to workspace note
annotationNote-title = Note from Annotation
annotationNote-enableTagSync =
.label = Keep tags of note from annotation in sync with the original annotation
about-title = About
help =
.value = { $name } VERSION { $version } Build { $time }

View File

@ -1,19 +1,5 @@
title = Template Editor
templateType = Template Type
templateType-item =
.label = Item
templateType-text =
.label = Text
templateType-system =
.label = Builtin
templateType-unknown =
.label = ?
templateType-help =
.label = ?
.title = Detailed explanation of template types
templateName = Template Name
previewContainer =
@ -26,9 +12,6 @@ delete =
.label = Delete
reset =
.label = Reset
share =
.label = Share
.tooltiptext = Copy template share code to clipboard
more =
.label = More Templates
.title = Get more templates online
@ -39,134 +22,11 @@ importClipboard =
.label = Import template: from template share code in clipboard
importNote =
.label = Import template: from existing note
share =
.label = Copy template share code to clipboard
backup =
.label = Export backup file
restore =
.label = Restore from backup file
help =
.label = Help
format-bold =
.title = Bold
format-italic =
.title = Italic
format-strikethrough =
.title = Strike-through
format-underline =
.title = Underline
format-superscript =
.title = Superscript
format-subscript =
.title = Subscript
format-textColor =
.title = Text color
format-link =
.title = Link
format-quote =
.title = Quote
format-monospaced =
.title = Monospace
format-code =
.title = Code block
format-table =
.title = Table
format-h1 =
.title = Level 1 heading
format-h2 =
.title = Level 2 heading
format-h3 =
.title = Level 3 heading
format-bullet =
.title = Bullet list
format-numbered =
.title = Numbered list
format-inlineMath =
.title = Inline math formula
format-blockMath =
.title = Multi-line math formula
format-inlineScript =
.title = Add an inline JS script, the result of which will be embedded in the note
format-blockScript =
.title = Add a multi-line async JS script, the return value of which will be embedded in the note
snippet-useMarkdown = use markdown
.title = Parse the template as markdown
snippet-useRefresh = use refresh
.title = Allow the content generated by the template to be refreshed
snippet-dryRunFlag = dry run flag
.title = Check if the template is running in dry run mode, e.g. for preview. In dry run mode, the script should not have side effects.
snippet-itemBeforeLoop = before loop
.title = Content to be rendered before the loop of items
snippet-itemInLoop = in loop
.title = Content to be rendered for each item in the loop
snippet-itemAfterLoop = after loop
.title = Content to be rendered after the loop of items
-variable-type = Type
-variable-item = Zotero.Item
-variable-note = Zotero.NoteItem
-variable-annotation = Zotero.AnnotationItem
-variable-string = string
-variable-object = object
-variable-function = function
snippet-itemItems = items
.title = { -variable-type }: { -variable-item }[]. The array of items to be rendered, available in beforeLoop and afterLoop stage
snippet-itemItem = item
.title = { -variable-type }: { -variable-item }. The current item to be rendered, available in inLoop stage
snippet-itemTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `item`, available in inLoop stage
snippet-itemTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached, available in any stage
snippet-itemCopyNoteImage = copy note image
.title = { -variable-type }: { -variable-function }. Copy the image of the note to the clipboard, available in any stage
snippet-itemSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data across different stages
snippet-itemFieldTitle = title
.title = { -variable-type }: { -variable-string }. The title of the top item
snippet-itemFieldAbstract = abstract
.title = { -variable-type }: { -variable-string }. The abstract of the top item
snippet-itemFieldCitKey = citation key
.title = { -variable-type }: { -variable-string }. The citation key of the top item
snippet-itemFieldDate = date
.title = { -variable-type }: { -variable-string }. The publication date of the top item
snippet-itemFieldDOI = DOI
.title = { -variable-type }: { -variable-string }. The DOI of the top item
snippet-itemFieldDOIURL = DOI or URL
.title = { -variable-type }: { -variable-string }. The DOI or URL of the top item
snippet-itemFieldAuthors = authors
.title = { -variable-type }: { -variable-string }. The authors of the top item
snippet-itemFieldJournal = journal
.title = { -variable-type }: { -variable-string }. The journal of the top item
snippet-itemFieldTitleTranslation = title translation
.title = { -variable-type }: { -variable-string }. The title translation of the top item
snippet-textTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-textSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data
snippet-quickInsertLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be linked
snippet-quickInsertLinkText = link text
.title = { -variable-type }: { -variable-string }. The default label of the link
snippet-quickInsertSubNoteItem = linked note
.title = { -variable-type }: { -variable-note }. The note item to be linked to
snippet-quickInsertNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickImportLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be imported
snippet-quickImportNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickNoteAnnotationItem = annotation
.title = { -variable-type }: { -variable-annotation }. The annotation item to be converted to a note
snippet-quickNoteTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `annotationItem`
snippet-quickNoteNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-exportMDFileNameNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileHeaderNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentMDContent = markdown content
.title = { -variable-type }: { -variable-string }. The markdown content to be exported

View File

@ -1,5 +1,7 @@
pref-title = Better Notes
menuItem-exportNote = Esporta nota
menuEdit-exportTemplate = Esporta il template su file...
menuEdit-templateEditor = Editor dei template
menuEdit-importTemplate = Nuovo template dagli appunti
@ -14,29 +16,9 @@ menuAddReaderNote-newTemplateNote = Nuova nota dell'elemento da template
menuEditor-resizeImage = Ridimensiona immagine
menuHelp-openUserGuide = Apri la guida utente di Better Notes
menuHelp-openUserGuide = Open Better Notes User Guide
templateEditor-templateType = Tipo
templateEditor-templateName = Nome
templateEditor-templateDisplayName =
.QuickInsertV2 = Inserimento rapido (Link)
.QuickImportV2 = Importazione rapida (Inserisci)
.QuickNoteV5 = Nota rapida (Da annotazione)
.ExportMDFileNameV2 = Esporta il nome del file MD
.ExportMDFileHeaderV2 = Esporta l'intestazione del file MD
.ExportMDFileContent = Esporta il contenuto del file MD
templateEditor-templateDisplayType =
.system = Integrato
.item = Elemento
.text = Testo
.unknown = ?
templateEditor-templateHelp =
.system = Per scopi specifici, ad esempio generare link a una nota.
.item = Può generare una porzione di nota da uno o più elementi di origine.
.text = Può generare una porzione di nota. Non richiede alcun input.
templateEditor-templateName = Template Name
syncManager-noteName = Nome nota
syncManager-lastSync = Ultima sincronizzazione
@ -79,7 +61,7 @@ editor-toolbar-settings-openAsTab = Apri come scheda
editor-toolbar-settings-openAsWindow = Apri in nuova finestra
editor-toolbar-settings-showInLibrary = Mostra nella biblioteca
editor-toolbar-settings-insertTemplate = Inserisci template
editor-toolbar-settings-refreshTemplates = Aggiorna il contenuto dal template
editor-toolbar-settings-refreshTemplates = Aggiorna il contenuto dal template (Beta)
editor-toolbar-settings-copyLink = Copia link (L{ $line })
editor-toolbar-settings-copyLinkAtSection = Copia link (Sez. { $section })
editor-toolbar-settings-openParent = Apri allegato
@ -97,10 +79,9 @@ alert-notValidParentItemError = Nessun elemento genitore valido.
alert-syncImportedNotes = Si desidera sincronizzare le note importate con i file markdown?
alert-linkCreator-emptyNote = Non è possibile creare un link da/a una nota vuota.
alert-templateEditor-shouldImport = Sembra che tu stia cercando di salvare direttamente un codice di condivisione di un template di nota. Vuoi importarlo come template?
alert-templateEditor-unsaved = You have unsaved changes in the template editor. Do you want to save them?
userGuide-start-title = Questo è Better Notes!
userGuide-start-desc = Better Notes è un potente strumento di gestione delle note che ti può aiutare a organizzare pensieri e idee durante la lettura di articoli scientifici. Questa guida ti aiuterà a prendere confidenza con Better Notes e ti mostrerà come usare al meglio le sue funzioni.
userGuide-start-desc = Better Notes è un potente strumento di gestione delle note che ti può aiutare a organizzare pensieri e idee mentre leggi articoli. Questa guida ti aiuterà a prendere confidenza con Better Notes e ti mostrerà come usare al meglio le sue funzioni.
userGuide-start-close = Ricordami più tardi
userGuide-createNoteButton-title = Crea una nuova nota
userGuide-createNoteButton-desc = Puoi creare una nuova nota da qui: vuota o da un template.
@ -131,4 +112,4 @@ userGuide-workspaceNoteInfo-title = Informazioni della nota
userGuide-workspaceNoteInfo-desc = Puoi vedere, modificare e gestire i tag della nota, le relazioni e i link.
userGuide-finish-title = Fine del tutorial!
userGuide-finish-desc = Divertiti a usare Better Notes!
Puoi visualizzare nuovamente il tutorial dal menu aiuto.
You can always run this guide again from the Help menu.

View File

@ -0,0 +1,25 @@
title = Esporta note
options-linkMode = Modalità note collegate
options-MD = MarkDown(.md)
options-Docx = MS Word(.docx)
options-PDF = PDF(.pdf)
options-mm = Mappa mentale
options-note = Nota Zotero
embedLink = Tutte incorporate in un'unica esportazione
standaloneLink = Ciascuna convertita in esportazioni indipendenti
keepLink = Mantieni i link Zotero (zotero://note/)
exportMD = Esporta file MD
setAutoSync = Imposta sincronizzazione automatica
.title = Auto-Sync is available for "Each Converted to Standalone Exports" mode.
withYAMLHeader = Con header YAML
autoMDFileName = Genera automaticamente il nome del file MD
exportDocx = Esporta file Docx
exportPDF = Esporta file PDF
exportFreeMind = Esporta file FreeMind
exportNote = Esporta in una nuova nota dell'elemento Zotero
confirm = Esporta
cancel = Chiudi
target = Oggetto: {$title}{ $left ->
[0]{ "" }
*[other] { " " }e {$left} altri
}

View File

@ -1,37 +0,0 @@
title =
.title = Esporta Note con Better Notes
target =
.value = Destinazione: {$title}{ $left ->
[0]{ "" }
*[other] { " " }e {$left} in più.
}
format =
.value = Formato:
format-markdown =
.label = MarkDown(.md)
format-msword =
.label = MS Word(.docx)
format-pdf =
.label = PDF(.pdf)
format-freemind =
.label = Mappa Mentale
format-note =
.label = Nota Zotero
links-keep =
.label = Mantieni collegamenti alle note(zotero://note/)
links-embed =
.label = Incorpora note collegate nel contenuto
links-standalone =
.label = Converti note collegate in esportazioni autonome
links-remove =
.label = Rimuovi collegamenti alle note
markdown-autoSync =
.label = Imposta sincronizzazione automatica per ogni nota
.title = La sincronizzazione automatica è disponibile per la modalità "Converti note collegate in esportazioni autonome".
markdown-withYAMLHeader =
.label = Con intestazione YAML
markdown-autoFilename =
.label = Genera automaticamente il nome del file

View File

@ -3,27 +3,13 @@ basic-openNote-takeover =
.label = Gestisci l'apertura delle note
basic-openNote-defaultAsWindow =
.label = Apri note come finestra per impostazione predefinita
basic-exportNotes-takeover =
.label = Take over exporting notes
editor-title = Editor delle note
editor-expandLevel-label = Espansione dello schema al livello delle intestazioni
editor-keepLinks =
.label = Mostra i collegamenti delle note nello schema
editor-noteLinkPreviewType = Show preview for note link when:
editor-noteLinkPreview-hover =
.label = Hover
editor-noteLinkPreview-ctrl =
.label = Press { PLATFORM() ->
[macos] ⌘
*[other] Ctrl
}
editor-noteLinkPreview-disable =
.label = Never
editor-useMagicKey =
.label = Usa il tasto magico "/" per mostrare il pannello dei comandi
editor-useMarkdownPaste =
.label = Usa l'incolla markdown avanzato
editor-noteLinkPreview =
.label = Mostra l'anteprima del link alla nota al passaggio del mouse
sync-title = Sincronizzazione
sync-period-label = Intervallo della sincronizzazione automatica (secondi)
@ -37,10 +23,6 @@ annotation-title = Annotazione PDF
annotation-autoAnnotation =
.label = Aggiungi automaticamente le nuove annotazioni alla nota di lavoro
annotationNote-title = Note from Annotation
annotationNote-enableTagSync =
.label = Mantieni i tag di una nota derivata da un'annotazione sincronizzati con l'annotazione di origine
about-title = Informazioni su Better Notes
help =
.value = { $name } VERSION { $version } Build { $time }

View File

@ -1,19 +1,5 @@
title = Editor dei template
templateType = Tipo di Template
templateType-item =
.label = Elemento
templateType-text =
.label = Testo
templateType-system =
.label = Integrato
templateType-unknown =
.label = ?
templateType-help =
.label = ?
.title = Spiegazioni dettagliate sui tipi di template
templateName = Nome template
previewContainer =
@ -26,9 +12,6 @@ delete =
.label = Elimina
reset =
.label = Ripristina
share =
.label = Share
.tooltiptext = Copia codice di condivisione template negli appunti
more =
.label = Altri Template
.title = Ottieni altri template online
@ -39,196 +22,11 @@ importClipboard =
.label = Importa template: da il codice di condivisione template negli appunti
importNote =
.label = Importa template: da nota esistente
share =
.label = Copia codice di condivisione template negli appunti
backup =
.label = Esporta file di backup
restore =
.label = Ripristina da file di backup
help =
.label = Aiuto
format-bold =
.title = Grassetto
format-italic =
.title = Corsivo
format-strikethrough =
.title = Barrato
format-underline =
.title = Sottolineato
format-superscript =
.title = Apice
format-subscript =
.title = Pedice
format-textColor =
.title = Colore del testo
format-link =
.title = Link
format-quote =
.title = Citazione
format-monospaced =
.title = Testo monospaziato
format-code =
.title = Codice
format-table =
.title = Tabella
format-h1 =
.title = Intestazione di livello 1
format-h2 =
.title = Intestazione di livello 2
format-h3 =
.title = Intestazione di livello 3
format-bullet =
.title = Elenco puntato
format-numbered =
.title = Elenco numerato
format-inlineMath =
.title = Formula matematica in linea
format-blockMath =
.title = Formula matematica multilinea
format-inlineScript =
.title = Aggiungi uno script JS in-linea, e inserisci il risultato nella nota
format-blockScript =
.title = Aggiungi uno script JS multi-linea, e inserisci il valore risultante nella nota
snippet-useMarkdown = usa markdown
.title = Elabora il template come markdown
snippet-useRefresh = abilita aggiornamento
.title = Permetti al contenuto generato dal template di essere aggiornato
snippet-dryRunFlag = esecuzione simulata
.title = Verifica che il template sia in modalità simulata, ad esempio come anteprima. In modalità di esecuzione simulata, lo script non apporta modifiche e quindi non dovrebbe avere effetti indesiderati.
snippet-itemBeforeLoop = prima del loop
.title = Contenuto da renderizzare prima del loop degli elementi
snippet-itemInLoop = nel loop
.title = Contenuto da renderizzare per ogni elemento del loop
snippet-itemAfterLoop = dopo il loop
.title = Contenuto da renderizzare dopo il loop degli elementi
.title = Markdown link, type `[` at the beginning and `](url)` at the end of your text. Should be used in markdown mode
-variable-type = Type
-variable-item = Zotero.Item
-variable-note = Zotero.NoteItem
-variable-annotation = Zotero.AnnotationItem
-variable-string = string
-variable-object = object
-variable-function = function
snippet-itemItems = elementi
.title = { -variable-type }: { -variable-item }[]. L'array di elementi da renderizzare, disponibile negli stadi prima o dopo il loop
snippet-itemItem = elemento
.title = { -variable-type }: { -variable-item }. L'elemento da renderizzare, disponibile nello stadio nel loop
snippet-itemTopItem = elemento superiore
.title = { -variable-type }: { -variable-item }. Il genitore della variabile `elemento`, disponibile nello stadio nel loop
snippet-itemTargetNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota a cui è allegato il template, disponibile a qualsiasi stadio
snippet-itemCopyNoteImage = copia l'immagine della nota
.title = { -variable-type }: { -variable-function }. Copia l'immagine della nota negli appunti, disponibile a qualsiasi stadio
snippet-itemSharedObj = oggetto condiviso
.title = { -variable-type }: { -variable-object }. Un oggetto condiviso che può essere usato per memorizzare informazioni attraverso stadi differenti
snippet-itemFieldTitle = titolo
.title = { -variable-type }: { -variable-string }. Il titolo dell'elemento superiore
snippet-itemFieldAbstract = abstract
.title = { -variable-type }: { -variable-string }. L'abstract dell'elemento superiore
snippet-itemFieldCitKey = chiave di citazione
.title = { -variable-type }: { -variable-string }. La chiave di citazione dell'elemento superiore
snippet-itemFieldDate = data
.title = { -variable-type }: { -variable-string }. La data di pubblicazione dell'elemento superiore
snippet-itemFieldDOI = DOI
.title = { -variable-type }: { -variable-string }. Il DOI dell'elemento superiore
snippet-itemFieldDOIURL = DOI o URL
.title = { -variable-type }: { -variable-string }. Il DOI o l'URLdell'elemento superiore
snippet-itemFieldAuthors = autori
.title = { -variable-type }: { -variable-string }. Gli autori dell'elemento superiore
snippet-itemFieldJournal = rivista
.title = { -variable-type }: { -variable-string }. La rivista dell'elemento superiore
snippet-itemFieldTitleTranslation = traduzione del titolo
.title = { -variable-type }: { -variable-string }. La traduzione del titolo dell'elemento superiore
snippet-textTargetNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota bersaglio dell'elemento superiore
snippet-textSharedObj = oggetto condiviso
.title = { -variable-type }: { -variable-object }. Un oggetto condiviso che può essere usato per memorizzare informazioni
snippet-quickInsertLink = link della nota
.title = { -variable-type }: { -variable-string }. Il link della nota da collegare
snippet-quickInsertLinkText = testo del link
.title = { -variable-type }: { -variable-string }. L'etichetta predefinita del link
snippet-quickInsertSubNoteItem = nota collegata
.title = { -variable-type }: { -variable-note }. La nota a cui puntare il link
snippet-quickInsertNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota a cui allegare il template
snippet-quickImportLink = link della nota
.title = { -variable-type }: { -variable-string }. Il link della nota da importare
snippet-quickImportNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota a cui allegare il template
snippet-quickNoteAnnotationItem = annotazione
.title = { -variable-type }: { -variable-annotation }. L'annotazione da convertire in nota
snippet-quickNoteTopItem = elemento superiore
.title = { -variable-type }: { -variable-item }. L'elemento superiore della variabile `annotationItem`
snippet-quickNoteNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota a cui allegare il template
snippet-exportMDFileNameNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota da esportare
snippet-exportMDFileHeaderNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota da esportare
snippet-exportMDFileContentNoteItem = nota bersaglio
.title = { -variable-type }: { -variable-note }. La nota da esportare
snippet-exportMDFileContentMDContent = contenuto markdown
.title = { -variable-type }: { -variable-string }. Il contenuto markdown da esportare
snippet-itemItems = items
.title = { -variable-type }: { -variable-item }[]. The array of items to be rendered, available in beforeLoop and afterLoop stage
snippet-itemItem = item
.title = { -variable-type }: { -variable-item }. The current item to be rendered, available in inLoop stage
snippet-itemTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `item`, available in inLoop stage
snippet-itemTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached, available in any stage
snippet-itemCopyNoteImage = copy note image
.title = { -variable-type }: { -variable-function }. Copy the image of the note to the clipboard, available in any stage
snippet-itemSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data across different stages
snippet-itemFieldTitle = title
.title = { -variable-type }: { -variable-string }. The title of the top item
snippet-itemFieldAbstract = abstract
.title = { -variable-type }: { -variable-string }. The abstract of the top item
snippet-itemFieldCitKey = citation key
.title = { -variable-type }: { -variable-string }. The citation key of the top item
snippet-itemFieldDate = date
.title = { -variable-type }: { -variable-string }. The publication date of the top item
snippet-itemFieldDOI = DOI
.title = { -variable-type }: { -variable-string }. The DOI of the top item
snippet-itemFieldDOIURL = DOI or URL
.title = { -variable-type }: { -variable-string }. The DOI or URL of the top item
snippet-itemFieldAuthors = authors
.title = { -variable-type }: { -variable-string }. The authors of the top item
snippet-itemFieldJournal = journal
.title = { -variable-type }: { -variable-string }. The journal of the top item
snippet-itemFieldTitleTranslation = title translation
.title = { -variable-type }: { -variable-string }. The title translation of the top item
snippet-textTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-textSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data
snippet-quickInsertLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be linked
snippet-quickInsertLinkText = link text
.title = { -variable-type }: { -variable-string }. The default label of the link
snippet-quickInsertSubNoteItem = linked note
.title = { -variable-type }: { -variable-note }. The note item to be linked to
snippet-quickInsertNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickImportLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be imported
snippet-quickImportNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickNoteAnnotationItem = annotation
.title = { -variable-type }: { -variable-annotation }. The annotation item to be converted to a note
snippet-quickNoteTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `annotationItem`
snippet-quickNoteNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-exportMDFileNameNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileHeaderNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentMDContent = markdown content
.title = { -variable-type }: { -variable-string }. The markdown content to be exported

View File

@ -1,5 +1,7 @@
pref-title=Better Notes
menuItem-exportNote=Экспорт заметки
menuEdit-exportTemplate=Экспорт шаблона в файл...
menuEdit-templateEditor=Редактор шаблонов
menuEdit-importTemplate=Новый шаблон из буфера обмена
@ -16,27 +18,7 @@ menuEditor-resizeImage=Изменить размер изображения
menuHelp-openUserGuide = Open Better Notes User Guide
templateEditor-templateType = Type
templateEditor-templateName = Name
templateEditor-templateDisplayName =
.QuickInsertV2 = Quick Insert (Link)
.QuickImportV2 = Quick Import (Embed)
.QuickNoteV5 = Quick Note (From Annotation)
.ExportMDFileNameV2 = Export MD File Name
.ExportMDFileHeaderV2 = Export MD File Header
.ExportMDFileContent = Export MD File Content
templateEditor-templateDisplayType =
.system = Builtin
.item = Item
.text = Text
.unknown = ?
templateEditor-templateHelp =
.system = For specific purposes, e.g., generating note link.
.item = Can generate note fragments from one or more selected items as input.
.text = Can generate note fragments. It doesn't require any input.
templateEditor-templateName = Template Name
editor-resizeImage-title = Resize Image
editor-resizeImage-prompt = Resize image width to:
@ -83,7 +65,7 @@ editor-toolbar-settings-openAsTab = Open as tab
editor-toolbar-settings-openAsWindow = Open as window
editor-toolbar-settings-showInLibrary = Show in Library
editor-toolbar-settings-insertTemplate=Вставить шаблон
editor-toolbar-settings-refreshTemplates = Update content from templates
editor-toolbar-settings-refreshTemplates = Update content from templates (Beta)
editor-toolbar-settings-copyLink = Копировать Ссылку (L{ $line })
editor-toolbar-settings-copyLinkAtSection = Копировать Ссылку (Sec. { $section })
editor-toolbar-settings-openParent=Открыть вложение
@ -101,7 +83,6 @@ alert-notValidParentItemError=Нет валидного родительског
alert-syncImportedNotes = Синхронизировать импортированные заметки с файлами MarkDown?
alert-linkCreator-emptyNote = Cannot create link from/to an empty note.
alert-templateEditor-shouldImport = Вы пытаетесь сохранить код шаблона заметки. Хотите импортировать его как шаблон?
alert-templateEditor-unsaved = You have unsaved changes in the template editor. Do you want to save them?
userGuide-start-title = Welcome to Better Notes!
userGuide-start-desc = Better Notes is a powerful note-taking tool that helps you organize your thoughts and ideas while reading papers. This guide will help you get started with Better Notes and show you how to make the most of its features.

View File

@ -1,37 +0,0 @@
title =
.title = Экспорт заметок с Better Notes
target =
.value = Цель: {$title}{ $left ->
[0]{ "" }
*[other] { " " }и еще {$left}.
}
format =
.value = Формат:
format-markdown =
.label = MarkDown(.md)
format-msword =
.label = MS Word(.docx)
format-pdf =
.label = PDF(.pdf)
format-freemind =
.label = Карта разума
format-note =
.label = Заметка Zotero
links-keep =
.label = Сохранить ссылки на заметки(zotero://note/)
links-embed =
.label = Встроить связанные заметки в содержимое
links-standalone =
.label = Преобразовать связанные заметки в автономные экспорты
links-remove =
.label = Удалить ссылки на заметки
markdown-autoSync =
.label = Установить авто-синхронизацию для каждой заметки
.title = Авто-синхронизация доступна в режиме "Преобразовать связанные заметки в автономные экспорты".
markdown-withYAMLHeader =
.label = С YAML заголовком
markdown-autoFilename =
.label = Автоматически генерировать имя файла

View File

@ -3,27 +3,13 @@ basic-openNote-takeover =
.label = Take over opening note
basic-openNote-defaultAsWindow =
.label = Open note as window by default
basic-exportNotes-takeover =
.label = Take over exporting notes
editor-title = Note Editor
editor-expandLevel-label = Outline расширить до уровня заголовка
editor-keepLinks =
.label = Сохранить ссылки
editor-noteLinkPreviewType = Show preview for note link when:
editor-noteLinkPreview-hover =
.label = Hover
editor-noteLinkPreview-ctrl =
.label = Press { PLATFORM() ->
[macos] ⌘
*[other] Ctrl
}
editor-noteLinkPreview-disable =
.label = Never
editor-useMagicKey =
.label = Использовать магическую клавишу "/" для отображения панели команд
editor-useMarkdownPaste =
.label = Использовать расширенное вставление Markdown
editor-noteLinkPreview =
.label = Show note link preview on hover
sync-title = Синк
sync-period-label = Авто-синк период (сек)
@ -37,10 +23,6 @@ annotation-title = PDF Аннотация
annotation-autoAnnotation =
.label = Автодобавлять новые аннотации к заметкам раб.пространства
annotationNote-title = Note from Annotation
annotationNote-enableTagSync =
.label = Keep tags of note from annotation in sync with the original annotation
about-title = About
help =
.value = { $name } VERSION { $version } Build { $time }

View File

@ -1,19 +1,5 @@
title = Редактор шаблонов
templateType = Template Type
templateType-item =
.label = Item
templateType-text =
.label = Text
templateType-system =
.label = Builtin
templateType-unknown =
.label = ?
templateType-help =
.label = ?
.title = Detailed explanation of template types
templateName = Имя шаблона
previewContainer =
@ -26,9 +12,6 @@ delete =
.label = Удалить
reset =
.label = Сброс
share =
.label = Share
.tooltiptext = Copy template share code to clipboard
more =
.label = Больше шаблонов
.title = Get more templates online
@ -39,134 +22,11 @@ importClipboard =
.label = Import template: from template share code in clipboard
importNote =
.label = Import template: from existing note
share =
.label = Copy template share code to clipboard
backup =
.label = Export backup file
restore =
.label = Restore from backup file
help =
.label = Помощь
format-bold =
.title = Bold
format-italic =
.title = Italic
format-strikethrough =
.title = Strike-through
format-underline =
.title = Underline
format-superscript =
.title = Superscript
format-subscript =
.title = Subscript
format-textColor =
.title = Text color
format-link =
.title = Link
format-quote =
.title = Quote
format-monospaced =
.title = Monospace
format-code =
.title = Code block
format-table =
.title = Table
format-h1 =
.title = Level 1 heading
format-h2 =
.title = Level 2 heading
format-h3 =
.title = Level 3 heading
format-bullet =
.title = Bullet list
format-numbered =
.title = Numbered list
format-inlineMath =
.title = Inline math formula
format-blockMath =
.title = Multi-line math formula
format-inlineScript =
.title = Add an inline JS script, the result of which will be embedded in the note
format-blockScript =
.title = Add a multi-line async JS script, the return value of which will be embedded in the note
snippet-useMarkdown = use markdown
.title = Parse the template as markdown
snippet-useRefresh = use refresh
.title = Allow the content generated by the template to be refreshed
snippet-dryRunFlag = dry run flag
.title = Check if the template is running in dry run mode, e.g. for preview. In dry run mode, the script should not have side effects.
snippet-itemBeforeLoop = before loop
.title = Content to be rendered before the loop of items
snippet-itemInLoop = in loop
.title = Content to be rendered for each item in the loop
snippet-itemAfterLoop = after loop
.title = Content to be rendered after the loop of items
-variable-type = Type
-variable-item = Zotero.Item
-variable-note = Zotero.NoteItem
-variable-annotation = Zotero.AnnotationItem
-variable-string = string
-variable-object = object
-variable-function = function
snippet-itemItems = items
.title = { -variable-type }: { -variable-item }[]. The array of items to be rendered, available in beforeLoop and afterLoop stage
snippet-itemItem = item
.title = { -variable-type }: { -variable-item }. The current item to be rendered, available in inLoop stage
snippet-itemTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `item`, available in inLoop stage
snippet-itemTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached, available in any stage
snippet-itemCopyNoteImage = copy note image
.title = { -variable-type }: { -variable-function }. Copy the image of the note to the clipboard, available in any stage
snippet-itemSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data across different stages
snippet-itemFieldTitle = title
.title = { -variable-type }: { -variable-string }. The title of the top item
snippet-itemFieldAbstract = abstract
.title = { -variable-type }: { -variable-string }. The abstract of the top item
snippet-itemFieldCitKey = citation key
.title = { -variable-type }: { -variable-string }. The citation key of the top item
snippet-itemFieldDate = date
.title = { -variable-type }: { -variable-string }. The publication date of the top item
snippet-itemFieldDOI = DOI
.title = { -variable-type }: { -variable-string }. The DOI of the top item
snippet-itemFieldDOIURL = DOI or URL
.title = { -variable-type }: { -variable-string }. The DOI or URL of the top item
snippet-itemFieldAuthors = authors
.title = { -variable-type }: { -variable-string }. The authors of the top item
snippet-itemFieldJournal = journal
.title = { -variable-type }: { -variable-string }. The journal of the top item
snippet-itemFieldTitleTranslation = title translation
.title = { -variable-type }: { -variable-string }. The title translation of the top item
snippet-textTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-textSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data
snippet-quickInsertLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be linked
snippet-quickInsertLinkText = link text
.title = { -variable-type }: { -variable-string }. The default label of the link
snippet-quickInsertSubNoteItem = linked note
.title = { -variable-type }: { -variable-note }. The note item to be linked to
snippet-quickInsertNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickImportLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be imported
snippet-quickImportNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickNoteAnnotationItem = annotation
.title = { -variable-type }: { -variable-annotation }. The annotation item to be converted to a note
snippet-quickNoteTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `annotationItem`
snippet-quickNoteNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-exportMDFileNameNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileHeaderNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentMDContent = markdown content
.title = { -variable-type }: { -variable-string }. The markdown content to be exported

View File

@ -1,5 +1,7 @@
pref-title = Better Notes
menuItem-exportNote = Notu Dışa Aktar
menuEdit-exportTemplate = Şablonu Dosya Olarak Dışa Aktar...
menuEdit-templateEditor = Şablon Düzenleyici
menuEdit-importTemplate = Panodan Yeni Şablon Al
@ -16,27 +18,7 @@ menuEditor-resizeImage = Resmi Boyutlandır
menuHelp-openUserGuide = Better Notes Kullanıcı Rehberini Aç
templateEditor-templateType = Type
templateEditor-templateName = Name
templateEditor-templateDisplayName =
.QuickInsertV2 = Quick Insert (Link)
.QuickImportV2 = Quick Import (Embed)
.QuickNoteV5 = Quick Note (From Annotation)
.ExportMDFileNameV2 = Export MD File Name
.ExportMDFileHeaderV2 = Export MD File Header
.ExportMDFileContent = Export MD File Content
templateEditor-templateDisplayType =
.system = Builtin
.item = Item
.text = Text
.unknown = ?
templateEditor-templateHelp =
.system = For specific purposes, e.g., generating note link.
.item = Can generate note fragments from one or more selected items as input.
.text = Can generate note fragments. It doesn't require any input.
templateEditor-templateName = Şablon Adı
editor-resizeImage-title = Resmi Boyutlandır
editor-resizeImage-prompt = Resmi Şuna Boyutlandır:
@ -83,7 +65,7 @@ editor-toolbar-settings-openAsTab = Sekme Olarak Aç
editor-toolbar-settings-openAsWindow = Pencere Olarak Aç
editor-toolbar-settings-showInLibrary = Kitaplıkta Göster
editor-toolbar-settings-insertTemplate = Şablon Uygula
editor-toolbar-settings-refreshTemplates = İçeriği Şablona Göre Güncelle
editor-toolbar-settings-refreshTemplates = İçeriği Şablona Göre Güncelle (Beta)
editor-toolbar-settings-copyLink = Bağlantıyı Kopyala (Satır { $line })
editor-toolbar-settings-copyLinkAtSection = Bağlantıyı Kopyala (Başlık { $section })
editor-toolbar-settings-openParent = Eki Aç
@ -101,7 +83,6 @@ alert-notValidParentItemError = Geçerli ana eser yok.
alert-syncImportedNotes = İçe aktarılmış notları Markdown dosyalarıyla eşitlemede tutmak ister misiniz?
alert-linkCreator-emptyNote = Boş bir nota/nottan bağlantı oluşturulamaz. note.
alert-templateEditor-shouldImport = Şablon kodunu doğrudan kaydetmeye çalışıyorsunuz gibi görünüyor. Şablon olarak içe aktarmak ister misiniz?
alert-templateEditor-unsaved = You have unsaved changes in the template editor. Do you want to save them?
userGuide-start-title = Better Notes'a hoş geldiniz!
userGuide-start-desc = Better Notes düşüncelerinizi ve tasarılarınızı düzenlemenize yardımcı olan güçlü bir not alma aracıdır. Kullanımı kolay ve yalın biçimde tasarlanmış olsa da karmaşık not alma işlerini görebilecek kadar da esnektir. Bu rehber size Better Notes'u kullanmaya başlamanıza ve ileri düzey işlevleri verimli kullanmanıza yardımcı olacaktır.

View File

@ -0,0 +1,25 @@
title = Notları Dışa Aktar
options-linkMode = Bağlantılı Notlar Modu
options-MD = MarkDown(.md)
options-Docx = MS Word(.docx)
options-PDF = PDF(.pdf)
options-mm = Zihin Haritası
options-note = Zotero Notu
embedLink = Hepsi Tek Bir Dışarı Aktarma İçerisinde
standaloneLink = Her Biri Bağımsız Olarak Dışa Aktarıldı
keepLink = Zotero Linkleri Kalsın (zotero://note/)
exportMD = MD Dosya(lar)sını Dışa Aktar
setAutoSync = Otomatik Eşitlemeye Ayarla
.title = Otomatik Eşitleme "Her Birini Bağımsız Dışa Aktar" seçeneği için kullanılabilir.
withYAMLHeader = YAML Başlığı İle
autoMDFileName = MD Dosya Adını Otomatik Oluştur
exportDocx = Docx Dosyası Olarak Dışa Aktar
exportPDF = PDF Dosyası Olarak Dışa Aktar
exportFreeMind = FreeMind Dosyası Olarak Dışa Aktar
exportNote = Yeni Zotero Notuna Aktar
confirm = Dışa Aktar
cancel = Kapat
target = Hedef: {$title}{ $left ->
[0]{ "" }
*[other] { " " }and {$left} more
}

View File

@ -1,37 +0,0 @@
title =
.title = Notları Better Notes ile Dışa Aktar
target =
.value = Hedef: {$title}{ $left ->
[0]{ "" }
*[other] { " " }ve {$left} daha.
}
format =
.value = Biçim:
format-markdown =
.label = MarkDown(.md)
format-msword =
.label = MS Word(.docx)
format-pdf =
.label = PDF(.pdf)
format-freemind =
.label = Zihin Haritası
format-note =
.label = Zotero Notu
links-keep =
.label = Not bağlantılarını koru(zotero://note/)
links-embed =
.label = Bağlantılı notları içeriğe göm
links-standalone =
.label = Bağlantılı notları bağımsız dışa aktarımlara dönüştür
links-remove =
.label = Not bağlantılarını kaldır
markdown-autoSync =
.label = Her not için otomatik senkronizasyon ayarla
.title = Otomatik senkronizasyon "Bağlantılı notları bağımsız dışa aktarımlara dönüştür" modu için kullanılabilir.
markdown-withYAMLHeader =
.label = YAML başlığı ile
markdown-autoFilename =
.label = Dosya adını otomatik oluştur

View File

@ -3,27 +3,13 @@ basic-openNote-takeover =
.label = Notları açmayı devral
basic-openNote-defaultAsWindow =
.label = Notları her zaman pencere olarak aç
basic-exportNotes-takeover =
.label = Take over exporting notes
editor-title = Not Düzenleyici
editor-expandLevel-label = Anahatta gösterilecek başlık düzeyleri
editor-keepLinks =
.label = Not bağlantılarını anahatta göster
editor-noteLinkPreviewType = Show preview for note link when:
editor-noteLinkPreview-hover =
.label = Hover
editor-noteLinkPreview-ctrl =
.label = Press { PLATFORM() ->
[macos] ⌘
*[other] Ctrl
}
editor-noteLinkPreview-disable =
.label = Never
editor-useMagicKey =
.label = Komut panelini göstermek için sihirli tuş "/" kullan
editor-useMarkdownPaste =
.label = Gelişmiş markdown yapıştırma kullan
editor-noteLinkPreview =
.label = İmleci bağlantının üzerine getirdiğinde ön izlemeyi göster
sync-title = Eşitle
sync-period-label = Otomatik Eşitleme Sıklığı (saniye)
@ -37,10 +23,6 @@ annotation-title = PDF Ek Açıklamaları
annotation-autoAnnotation =
.label = Çalışma alanı notuna otomatik olarak yeni ek açıklamaları ekle
annotationNote-title = Note from Annotation
annotationNote-enableTagSync =
.label = Keep tags of note from annotation in sync with the original annotation
about-title = Hakkında
help =
.value = { $name } Sürüm { $version } Yapı Numarası { $time }

View File

@ -1,19 +1,5 @@
title = Şablon Düzenleyici
templateType = Template Type
templateType-item =
.label = Item
templateType-text =
.label = Text
templateType-system =
.label = Builtin
templateType-unknown =
.label = ?
templateType-help =
.label = ?
.title = Detailed explanation of template types
templateName = Şablon Adı
previewContainer =
@ -26,9 +12,6 @@ delete =
.label = Sil
reset =
.label = Sıfırla
share =
.label = Share
.tooltiptext = Şablon paylaşım kodunu panoya kopyala
more =
.label = Daha Fazla Şablon
.title = Daha Fazla Çevrimiçi Şablon Bul
@ -39,134 +22,11 @@ importClipboard =
.label = Şablonu İçe Aktar: panodaki şablon paylaşım kodu ile
importNote =
.label = Şablonu İçe Aktar: var olan bir nottan
share =
.label = Şablon paylaşım kodunu panoya kopyala
backup =
.label = Yedek dosyasını dışa aktar
restore =
.label = Yedek dosyasından geri yükle
help =
.label = Yardım
format-bold =
.title = Bold
format-italic =
.title = Italic
format-strikethrough =
.title = Strike-through
format-underline =
.title = Underline
format-superscript =
.title = Superscript
format-subscript =
.title = Subscript
format-textColor =
.title = Text color
format-link =
.title = Link
format-quote =
.title = Quote
format-monospaced =
.title = Monospace
format-code =
.title = Code block
format-table =
.title = Table
format-h1 =
.title = Level 1 heading
format-h2 =
.title = Level 2 heading
format-h3 =
.title = Level 3 heading
format-bullet =
.title = Bullet list
format-numbered =
.title = Numbered list
format-inlineMath =
.title = Inline math formula
format-blockMath =
.title = Multi-line math formula
format-inlineScript =
.title = Add an inline JS script, the result of which will be embedded in the note
format-blockScript =
.title = Add a multi-line async JS script, the return value of which will be embedded in the note
snippet-useMarkdown = use markdown
.title = Parse the template as markdown
snippet-useRefresh = use refresh
.title = Allow the content generated by the template to be refreshed
snippet-dryRunFlag = dry run flag
.title = Check if the template is running in dry run mode, e.g. for preview. In dry run mode, the script should not have side effects.
snippet-itemBeforeLoop = before loop
.title = Content to be rendered before the loop of items
snippet-itemInLoop = in loop
.title = Content to be rendered for each item in the loop
snippet-itemAfterLoop = after loop
.title = Content to be rendered after the loop of items
-variable-type = Type
-variable-item = Zotero.Item
-variable-note = Zotero.NoteItem
-variable-annotation = Zotero.AnnotationItem
-variable-string = string
-variable-object = object
-variable-function = function
snippet-itemItems = items
.title = { -variable-type }: { -variable-item }[]. The array of items to be rendered, available in beforeLoop and afterLoop stage
snippet-itemItem = item
.title = { -variable-type }: { -variable-item }. The current item to be rendered, available in inLoop stage
snippet-itemTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `item`, available in inLoop stage
snippet-itemTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached, available in any stage
snippet-itemCopyNoteImage = copy note image
.title = { -variable-type }: { -variable-function }. Copy the image of the note to the clipboard, available in any stage
snippet-itemSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data across different stages
snippet-itemFieldTitle = title
.title = { -variable-type }: { -variable-string }. The title of the top item
snippet-itemFieldAbstract = abstract
.title = { -variable-type }: { -variable-string }. The abstract of the top item
snippet-itemFieldCitKey = citation key
.title = { -variable-type }: { -variable-string }. The citation key of the top item
snippet-itemFieldDate = date
.title = { -variable-type }: { -variable-string }. The publication date of the top item
snippet-itemFieldDOI = DOI
.title = { -variable-type }: { -variable-string }. The DOI of the top item
snippet-itemFieldDOIURL = DOI or URL
.title = { -variable-type }: { -variable-string }. The DOI or URL of the top item
snippet-itemFieldAuthors = authors
.title = { -variable-type }: { -variable-string }. The authors of the top item
snippet-itemFieldJournal = journal
.title = { -variable-type }: { -variable-string }. The journal of the top item
snippet-itemFieldTitleTranslation = title translation
.title = { -variable-type }: { -variable-string }. The title translation of the top item
snippet-textTargetNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-textSharedObj = shared object
.title = { -variable-type }: { -variable-object }. A shared object that can be used to store data
snippet-quickInsertLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be linked
snippet-quickInsertLinkText = link text
.title = { -variable-type }: { -variable-string }. The default label of the link
snippet-quickInsertSubNoteItem = linked note
.title = { -variable-type }: { -variable-note }. The note item to be linked to
snippet-quickInsertNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickImportLink = note link
.title = { -variable-type }: { -variable-string }. The link of the note item to be imported
snippet-quickImportNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-quickNoteAnnotationItem = annotation
.title = { -variable-type }: { -variable-annotation }. The annotation item to be converted to a note
snippet-quickNoteTopItem = top item
.title = { -variable-type }: { -variable-item }. The top-level parent of the variable `annotationItem`
snippet-quickNoteNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to which the template is attached
snippet-exportMDFileNameNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileHeaderNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentNoteItem = target note
.title = { -variable-type }: { -variable-note }. The note item to be exported
snippet-exportMDFileContentMDContent = markdown content
.title = { -variable-type }: { -variable-string }. The markdown content to be exported

View File

@ -1,5 +1,7 @@
pref-title=Better Notes
menuItem-exportNote=导出笔记
menuEdit-exportTemplate=运行模板并导出为文件...
menuEdit-templateEditor=模板编辑器
menuEdit-importTemplate=从剪贴板导入笔记模板
@ -16,27 +18,7 @@ menuEditor-resizeImage=缩放图片
menuHelp-openUserGuide = 打开Better Notes用户指南
templateEditor-templateType = 类型
templateEditor-templateName = 名称
templateEditor-templateDisplayName =
.QuickInsertV2 = Quick Insert (插入链接)
.QuickImportV2 = Quick Import (嵌入链接笔记)
.QuickNoteV5 = Quick Note (从批注创建笔记)
.ExportMDFileNameV2 = Export MD File Name (导出MD文件名)
.ExportMDFileHeaderV2 = Export MD File Header (导出MD头)
.ExportMDFileContent = Export MD File Content (导出MD正文)
templateEditor-templateDisplayType =
.system = 内置
.item = 条目
.text = 文本
.unknown = ?
templateEditor-templateHelp =
.system = 用于特定目的,例如生成笔记链接。
.item = 可以从一个或多个选定的条目生成笔记片段。
.text = 可以生成笔记片段。不需要任何输入。
templateEditor-templateName = 模板名称
editor-resizeImage-title = 缩放图片
editor-resizeImage-prompt = 缩放图片宽度为:
@ -83,7 +65,7 @@ editor-toolbar-settings-openAsTab = 在标签页中打开
editor-toolbar-settings-openAsWindow = 在窗口中打开
editor-toolbar-settings-showInLibrary = 在文库中显示
editor-toolbar-settings-insertTemplate=插入模板
editor-toolbar-settings-refreshTemplates = 更新模板生成内容
editor-toolbar-settings-refreshTemplates = 更新模板生成内容 (Beta)
editor-toolbar-settings-copyLink=复制行(L{ $line })
editor-toolbar-settings-copyLinkAtSection=复制节(Sec. { $section })
editor-toolbar-settings-openParent=打开附件
@ -101,7 +83,6 @@ alert-notValidParentItemError=无效的父条目。
alert-syncImportedNotes = 保持导入的笔记与 MarkDown 文件同步?
alert-linkCreator-emptyNote = 无法从/向空笔记创建链接。
alert-templateEditor-shouldImport = 似乎您正在尝试直接保存一个笔记模板分享代码。您想要将其导入为模板吗?
alert-templateEditor-unsaved = 您在模板编辑器中有未保存的更改。您想要保存它们吗?
userGuide-start-title = 欢迎使用Better Notes
userGuide-start-desc = Better Notes是一个强大的笔记工具帮助您组织阅读论文时的概念和想法。本指南将帮助您开始使用Better Notes并向您展示如何充分利用其功能。

View File

@ -0,0 +1,25 @@
title=导出笔记
options-linkMode=链接笔记模式
options-MD=MarkDown(.md)
options-Docx=MS Word(.docx)
options-PDF=PDF(.pdf)
options-mm=思维导图
options-note=Zotero笔记
embedLink=全部嵌入为一个导出
standaloneLink=分别单独导出
keepLink=保留Zotero链接(zotero://note/)
exportMD=导出MD文件
setAutoSync=设置自动同步
.title=自动同步仅能在"分别单独导出模式"使用
withYAMLHeader=带有YAML头
autoMDFileName=自动生成MD文件名
exportDocx=导出Word文件
exportPDF=导出PDF文件
exportFreeMind=导出FreeMind文件
exportNote=导出为Zotero笔记条目
confirm=导出
cancel=关闭
target=目标: {$title}{ $left ->
[0]{ "" }
*[other] { " " }和其他{$left}个
}

View File

@ -1,37 +0,0 @@
title =
.title = 使用 Better Notes 导出笔记
target =
.value = 目标: {$title}{ $left ->
[0]{ "" }
*[other] { " " } 以及其他 {$left} 个。
}
format =
.value = 格式:
format-markdown =
.label = MarkDown(.md)
format-msword =
.label = MS Word(.docx)
format-pdf =
.label = PDF(.pdf)
format-freemind =
.label = 思维导图
format-note =
.label = Zotero 笔记
links-keep =
.label = 保留笔记链接(zotero://note/)
links-embed =
.label = 嵌入链接的笔记内容
links-standalone =
.label = 将链接的笔记分别导出
links-remove =
.label = 移除笔记链接
markdown-autoSync =
.label = 为每个笔记设置自动同步
.title = 自动同步适用于“将链接的笔记分别导出”模式。
markdown-withYAMLHeader =
.label = 包含 YAML 头
markdown-autoFilename =
.label = 自动生成文件名

View File

@ -3,27 +3,13 @@ basic-openNote-takeover =
.label = 接管打开笔记
basic-openNote-defaultAsWindow =
.label = 默认在窗口打开笔记
basic-exportNotes-takeover =
.label = 接管导出笔记
editor-title = 笔记编辑器
editor-expandLevel-label = 大纲展开至标题层级
editor-keepLinks =
.label = 在大纲中显示笔记链接
editor-noteLinkPreviewType = 笔记链接预览触发方式:
editor-noteLinkPreview-hover =
.label = 鼠标悬停
editor-noteLinkPreview-ctrl =
.label = 按下 { PLATFORM() ->
[macos] ⌘
*[other] Ctrl
}
editor-noteLinkPreview-disable =
.label = 从不
editor-useMagicKey =
.label = 使用魔法键 "/" 显示命令面板
editor-useMarkdownPaste =
.label = 使用增强的Markdown粘贴
editor-noteLinkPreview =
.label = 鼠标悬停时显示笔记链接预览
sync-title = 同步
sync-period-label = 自动同步周期 (秒)
@ -37,10 +23,6 @@ annotation-title = PDF批注
annotation-autoAnnotation =
.label = 自动添加新批注到工作区笔记
annotationNote-title = 从注释生成笔记
annotationNote-enableTagSync =
.label = 保持注释生成的笔记的标签与原始注释同步
about-title = 关于
help =
.value = { $name } 版本 { $version } 构建 { $time }

View File

@ -1,19 +1,5 @@
title = 模板编辑器
templateType = 模板{ -variable-type }
templateType-item =
.label = 条目
templateType-text =
.label = 文本
templateType-system =
.label = 内置
templateType-unknown =
.label = ?
templateType-help =
.label = ?
.title = 模板{ -variable-type }的详细解释
templateName = 模板名称
previewContainer =
@ -26,9 +12,6 @@ delete =
.label = 删除
reset =
.label = 重置
share =
.label = 分享
.tooltiptext = 复制模板分享代码到剪贴板
more =
.label = 更多模板
@ -38,134 +21,11 @@ importClipboard =
.label = 导入笔记模板: 剪贴板中的模板分享代码
importNote =
.label = 导入笔记模板: 从现有笔记
share =
.label = 复制模板分享代码到剪贴板
backup =
.label = 导出模板备份文件
restore =
.label = 从备份文件恢复
help =
.label = 帮助
format-bold =
.title = 加粗
format-italic =
.title = 斜体
format-strikethrough =
.title = 删除线
format-underline =
.title = 下划线
format-superscript =
.title = 上标
format-subscript =
.title = 下标
format-textColor =
.title = 文本颜色
format-link =
.title = 添加链接
format-quote =
.title = 引用文本
format-monospaced =
.title = 单行
format-code =
.title = 多行代码
format-table =
.title = 添加表格
format-h1 =
.title = 一级标题
format-h2 =
.title = 二级标题
format-h3 =
.title = 三级标题
format-bullet =
.title = 无序列表
format-numbered =
.title = 有序列表
format-inlineMath =
.title = 行内数学公式
format-blockMath =
.title = 多行数学公式
format-inlineScript =
.title = 添加行内JS脚本结果将嵌入到笔记中
format-blockScript =
.title = 添加多行异步JS脚本返回值将嵌入到笔记中
snippet-useMarkdown = 使用 markdown
.title = 将模板解析为 markdown
snippet-useRefresh = 允许内容刷新
.title = 允许模板生成的内容刷新
snippet-dryRunFlag = dry run标志
.title = 检查模板是否在dry run模式下运行例如用于预览。在dry run模式下脚本不应有副作用。
snippet-itemBeforeLoop = 循环前
.title = 在条目循环之前渲染的内容
snippet-itemInLoop = 循环中
.title = 为循环中的每个条目渲染的内容
snippet-itemAfterLoop = 循环后
.title = 在条目循环之后渲染的内容
-variable-type = 类型
-variable-item = Zotero.Item
-variable-note = Zotero.NoteItem
-variable-annotation = Zotero.AnnotationItem
-variable-string = 字符串
-variable-object = 对象
-variable-function = 函数
snippet-itemItems = 所有条目
.title = { -variable-type }{ -variable-item }[]。要渲染的条目数组,可在 beforeLoop 和 afterLoop 阶段使用
snippet-itemItem = 当前条目
.title = { -variable-type }{ -variable-item }。要渲染的当前条目,可在 inLoop 阶段使用
snippet-itemTopItem = 顶级条目
.title = { -variable-type }{ -variable-item }。变量 `item` 的顶级父级,可在 inLoop 阶段使用
snippet-itemTargetNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。模板插入到的笔记条目,可在任何阶段使用
snippet-itemCopyNoteImage = 复制笔记图片
.title = { -variable-type }{ -variable-function }。将笔记的图片复制到剪贴板,可在任何阶段使用
snippet-itemSharedObj = 共享对象
.title = { -variable-type }{ -variable-object }。可用于在不同阶段存储数据的共享对象
snippet-itemFieldTitle = 标题
.title = { -variable-type }{ -variable-string }。顶级条目的标题。可在 inLoop 阶段使用
snippet-itemFieldAbstract = 摘要
.title = { -variable-type }{ -variable-string }。顶级条目的摘要。可在 inLoop 阶段使用
snippet-itemFieldCitKey = citation key
.title = { -variable-type }{ -variable-string }。顶级条目的 citation key。可在 inLoop 阶段使用
snippet-itemFieldDate = 日期
.title = { -variable-type }{ -variable-string }。顶级条目的发布日期。可在 inLoop 阶段使用
snippet-itemFieldDOI = DOI
.title = { -variable-type }{ -variable-string }。顶级条目的DOI。可在 inLoop 阶段使用
snippet-itemFieldDOIURL = DOI或URL
.title = { -variable-type }{ -variable-string }。顶级条目的DOI或URL。可在 inLoop 阶段使用
snippet-itemFieldAuthors = 作者
.title = { -variable-type }{ -variable-string }。顶级条目的作者。可在 inLoop 阶段使用
snippet-itemFieldJournal = 期刊
.title = { -variable-type }{ -variable-string }。顶级条目的期刊。可在 inLoop 阶段使用
snippet-itemFieldTitleTranslation = 标题翻译
.title = { -variable-type }{ -variable-string }。顶级条目的标题翻译*需要Translate for Zotero插件。可在 inLoop 阶段使用
snippet-textTargetNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。模板插入到的笔记条目
snippet-textSharedObj = 共享对象
.title = { -variable-type }{ -variable-object }。可用于存储数据的共享对象
snippet-quickInsertLink = 笔记链接
.title = { -variable-type }{ -variable-string }。要链接的笔记条目的链接
snippet-quickInsertLinkText = 链接文本
.title = { -variable-type }{ -variable-string }。链接的默认标签
snippet-quickInsertSubNoteItem = 链接的笔记
.title = { -variable-type }{ -variable-note }。要链接到的笔记条目
snippet-quickInsertNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。模板插入到的笔记条目
snippet-quickImportLink = 笔记链接
.title = { -variable-type }{ -variable-string }。要导入的笔记条目的链接
snippet-quickImportNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。模板插入到的笔记条目
snippet-quickNoteAnnotationItem = 注释
.title = { -variable-type }{ -variable-annotation }。要转换为笔记的注释条目
snippet-quickNoteTopItem = 顶级条目
.title = { -variable-type }{ -variable-item }。变量 `annotationItem` 的顶级父级
snippet-quickNoteNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。模板插入到的笔记条目
snippet-exportMDFileNameNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。要导出的笔记条目
snippet-exportMDFileHeaderNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。要导出的笔记条目
snippet-exportMDFileContentNoteItem = 目标笔记
.title = { -variable-type }{ -variable-note }。要导出的笔记条目
snippet-exportMDFileContentMDContent = markdown 内容
.title = { -variable-type }{ -variable-string }。要导出的 markdown 内容

View File

@ -14,7 +14,7 @@
"id": "__addonID__",
"update_url": "__updateURL__",
"strict_min_version": "7.0.0-beta.70",
"strict_max_version": "7.1.*"
"strict_max_version": "7.0.*"
}
}
}

View File

@ -6,15 +6,22 @@ pref("__prefsPrefix__.autoAnnotation", false);
pref("__prefsPrefix__.insertLinkPosition", "end");
pref("__prefsPrefix__.embedLink", true);
pref("__prefsPrefix__.standaloneLink", false);
pref("__prefsPrefix__.keepLink", true);
pref("__prefsPrefix__.exportMD", true);
pref("__prefsPrefix__.setAutoSync", false);
pref("__prefsPrefix__.withYAMLHeader", false);
pref("__prefsPrefix__.autoMDFileName", false);
pref("__prefsPrefix__.exportDocx", false);
pref("__prefsPrefix__.exportPDF", false);
pref("__prefsPrefix__.exportFreeMind", false);
pref("__prefsPrefix__.exportNote", false);
pref("__prefsPrefix__.workspace.outline.expandLevel", 2);
pref("__prefsPrefix__.workspace.outline.keepLinks", true);
pref("__prefsPrefix__.editor.noteLinkPreviewType", "hover");
pref("__prefsPrefix__.editor.useMagicKey", true);
pref("__prefsPrefix__.editor.useMarkdownPaste", true);
pref("__prefsPrefix__.editor.noteLinkPreview", true);
pref("__prefsPrefix__.openNote.takeover", true);
pref("__prefsPrefix__.openNote.defaultAsWindow", false);
pref("__prefsPrefix__.exportNotes.takeover", true);
pref("__prefsPrefix__.annotationNote.enableTagSync", true);

View File

@ -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 Tools->New Template from Clipboard.
# goto Zotero menu bar, click Edit->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 `Tools`->`New Template from Clipboard`.
2. Goto Zotero menubar, click `Edit`->`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.
@ -83,14 +83,13 @@ Pragmas are lines start with `// @`. They have special effect and will not be re
Let the compiler know you are using markdown. Otherwise the template will be processed as HTML.
### `// @use-refresh`
### `// @use-update`
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.
This is a beta feature and can be changed/removed in the future.
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).
> The template with this pragma should not contain any separator (`---` or `<hr>`) in the content.
### `// @author`
@ -150,7 +149,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 Tools->New Template from Clipboard.
# goto Zotero menu bar, click Edit->New Template from Clipboard.
# Do not copy-paste this to better notes template editor directly.
name: "[Item] Example Item Template"
content: |-
@ -216,6 +215,7 @@ 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 |
@ -305,10 +305,10 @@ ${{
}
key = att.key;
if (att.libraryID === 1) {
return `zotero://open/library/items/${key}`;
return `zotero://open-pdf/library/items/${key}`;
} else {
groupID = Zotero.Libraries.get(att.libraryID).id;
return `zotero://open/groups/${groupID}/items/${key}`;
return `zotero://open-pdf/groups/${groupID}/items/${key}`;
}
}
sharedObj.getPDFLink = getPDFLink;
@ -409,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 Tools->New Template from Clipboard.
# goto Zotero menu bar, click Edit->New Template from Clipboard.
# Do not copy-paste this to better notes template editor directly.
name: "[TYPE] TEMPLATE NAME"
content: |-

8605
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "zotero-better-notes",
"version": "2.2.5",
"version": "1.1.4-beta.108",
"description": "Everything about note management. All in Zotero.",
"config": {
"addonName": "Better Notes for Zotero",
@ -14,11 +14,9 @@
"scripts": {
"start": "zotero-plugin serve",
"build": "tsc --noEmit && zotero-plugin build",
"build-dev": "tsc --noEmit && zotero-plugin build --dev && cd build/addon && zip -r ../zotero-better-notes-dev.xpi .",
"release": "zotero-plugin release",
"lint": "prettier --write . && eslint . --ext .ts --fix",
"test": "zotero-plugin test --abort-on-fail --exit-on-finish",
"test-dev": "zotero-plugin test --abort-on-fail",
"test": "echo \"Error: no test specified\" && exit 1",
"update-deps": "npm update --save"
},
"repository": {
@ -32,16 +30,16 @@
},
"homepage": "https://github.com/windingwind/zotero-better-notes#readme",
"dependencies": {
"asciidoctor": "^3.0.4",
"dexie": "^4.0.11",
"diff": "^5.2.0",
"hast-util-to-html": "^9.0.4",
"asciidoctor": "^3.0.2",
"dexie": "^4.0.4",
"diff": "^5.1.0",
"hast-util-to-html": "^9.0.0",
"hast-util-to-mdast": "^8.4.1",
"hast-util-to-text": "^4.0.2",
"hast-util-to-text": "^4.0.0",
"hastscript": "^8.0.0",
"html-docx-js": "^0.3.1",
"html-docx-js-typescript": "^0.1.5",
"katex": "^0.16.21",
"katex": "^0.16.9",
"path-browserify": "^1.0.1",
"rehype-format": "^4.0.1",
"rehype-parse": "^8.0.5",
@ -58,38 +56,36 @@
"unist-util-visit": "^5.0.0",
"unist-util-visit-parents": "^6.0.1",
"yamljs": "^0.3.0",
"zotero-plugin-toolkit": "^4.1.1"
"zotero-plugin-toolkit": "^2.3.37"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@prettier/plugin-xml": "^3.4.1",
"@prettier/plugin-xml": "^3.2.2",
"@types/browser-or-node": "^1.3.2",
"@types/chai": "^5.0.1",
"@types/diff": "^5.2.3",
"@types/diff": "^5.0.9",
"@types/html-docx-js": "^0.3.4",
"@types/katex": "^0.16.7",
"@types/mocha": "^10.0.10",
"@types/node": "^20.17.14",
"@types/path-browserify": "^1.0.3",
"@types/node": "^20.10.4",
"@types/path-browserify": "^1.0.2",
"@types/seedrandom": "^3.0.8",
"@types/yamljs": "^0.2.34",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"chokidar-cli": "^3.0.0",
"concurrently": "^8.2.2",
"cross-env": "^7.0.3",
"eslint": "^8.57.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"prettier": "^3.4.2",
"prosemirror-model": "^1.24.1",
"prettier": "^3.1.1",
"prosemirror-model": "^1.19.4",
"prosemirror-state": "^1.4.3",
"prosemirror-transform": "^1.10.2",
"prosemirror-view": "^1.37.1",
"prosemirror-transform": "^1.8.0",
"prosemirror-view": "^1.32.6",
"replace-in-file": "^7.2.0",
"typescript": "^5.7.3",
"xslt3": "^2.7.0",
"zotero-plugin-scaffold": "^0.2.0-beta.20",
"zotero-types": "^3.1.6"
"typescript": "^5.3.3",
"xslt3": "^2.6.0",
"zotero-plugin-scaffold": "^0.0.32",
"zotero-types": "^2.0.1"
},
"eslintConfig": {
"env": {

View File

@ -1,20 +1,23 @@
import { VirtualizedTableHelper } from "zotero-plugin-toolkit";
import { LargePrefHelper } from "zotero-plugin-toolkit";
import { Prompt } from "zotero-plugin-toolkit/dist/managers/prompt";
import {
ColumnOptions,
VirtualizedTableHelper,
} from "zotero-plugin-toolkit/dist/helpers/virtualizedTable";
import { LargePrefHelper } from "zotero-plugin-toolkit/dist/helpers/largePref";
import ToolkitGlobal from "zotero-plugin-toolkit/dist/managers/toolkitGlobal";
import { getPref, setPref } from "./utils/prefs";
import { SyncDataType } from "./modules/sync/managerWindow";
import hooks from "./hooks";
import api from "./api";
import { createZToolkit } from "./utils/ztoolkit";
import { MessageHelper } from "zotero-plugin-toolkit/dist/helpers/message";
import type { handlers as parsingHandlers } from "./extras/parsingWorker";
import type { handlers as relationHandlers } from "./extras/relationWorker";
class Addon {
public data: {
uid: string;
alive: boolean;
env: "development" | "production" | "test";
initialized?: boolean;
// Env type, see build.js
env: "development" | "production";
ztoolkit: ZToolkit;
// ztoolkit: ZoteroToolkit;
locale?: {
@ -24,7 +27,7 @@ class Addon {
window: Window;
};
export: {
pdf: { promise?: _ZoteroTypes.Promise.PromiseObject };
pdf: { promise?: _ZoteroTypes.PromiseObject };
};
sync: {
data?: LargePrefHelper;
@ -62,22 +65,18 @@ class Addon {
window?: Window;
tableHelper?: VirtualizedTableHelper;
editor?: any;
monaco?: any;
templates: string[];
};
picker: {
mode: "insert" | "create" | "export" | "pick";
mode: "insert" | "create" | "export";
data: Record<string, any>;
};
};
relation: {
worker?: Worker;
server?: MessageHelper<typeof relationHandlers>;
};
parsing: {
server?: MessageHelper<typeof parsingHandlers>;
};
imageCache: Record<number, string>;
readonly prompt?: Prompt;
hint: {
silent: boolean;
};
@ -124,8 +123,10 @@ class Addon {
},
},
relation: {},
parsing: {},
imageCache: {},
get prompt() {
return ToolkitGlobal.getInstance().prompt.instance;
},
hint: {
silent: false,
},

View File

@ -34,7 +34,6 @@ import {
runTemplate,
runTextTemplate,
runItemTemplate,
runQuickInsertTemplate,
} from "./modules/template/api";
import {
getTemplateKeys,
@ -82,8 +81,6 @@ import {
updateNoteLinkRelation,
} from "./utils/relation";
import { getWorkspaceByTabID, getWorkspaceByUID } from "./utils/workspace";
import { getString } from "./utils/locale";
import { showRestartHint } from "./utils/hint";
const workspace = {
getWorkspaceByTabID,
@ -125,7 +122,6 @@ const template = {
runTemplate,
runTextTemplate,
runItemTemplate,
runQuickInsertTemplate,
getTemplateKeys,
getTemplateText,
setTemplate,
@ -182,11 +178,6 @@ const relation = {
getAnnotationByLinkTarget,
};
const utils = {
getString,
requireRestart: showRestartHint,
};
export default {
workspace,
sync,
@ -197,5 +188,4 @@ export default {
editor,
note,
relation,
utils,
};

View File

@ -5,7 +5,6 @@ export class PluginCEBase extends XULElementBase {
useShadowRoot = false;
connectedCallback(): void {
// @ts-ignore - plugin instance
this._addon = Zotero[config.addonInstance];
Zotero.UIProperties.registerRoot(this);
if (!this.useShadowRoot) {
@ -52,7 +51,7 @@ export class PluginCEBase extends XULElementBase {
const selector = `#${this._wrapID(key)}`;
return (this.querySelector(selector) ||
this.shadowRoot?.querySelector(selector)) as
| XULElement
| XUL.Element
| HTMLElement
| null;
}

View File

@ -66,10 +66,10 @@ export class InboundCreator extends PluginCEBase {
async accept(io: any) {
if (!this.targetNote) return;
this.notePicker.saveRecentNotes();
const content = await this.getContentToInsert();
io.targetNoteID = this.targetNote.id;
io.sourceNoteIDs = [this.currentNote!.id];
io.content = content;
io.lineIndex = this.getIndexToInsert();
}
@ -79,7 +79,7 @@ export class InboundCreator extends PluginCEBase {
await this.notePicker.load();
this.notePicker.addEventListener("selectionchange", (event: any) => {
this.targetNote = event.detail.selectedNotes[0];
this.targetNote = event.detail.selectedNote;
this.updatePickerTitle(this.targetNote);
this.noteOutline.item = this.targetNote;
this.noteOutline.render();
@ -215,11 +215,21 @@ export class InboundCreator extends PluginCEBase {
async getContentToInsert() {
if (!this.currentNote || !this.targetNote) return "";
return await this._addon.api.template.runQuickInsertTemplate(
this.currentNote,
this.targetNote,
{ dryRun: true },
const forwardLink = this._addon.api.convert.note2link(this.currentNote, {});
const content = await this._addon.api.template.runTemplate(
"[QuickInsertV2]",
"link, linkText, subNoteItem, noteItem",
[
forwardLink,
this.currentNote.getNoteTitle().trim() || forwardLink,
this.currentNote,
this.targetNote,
],
{
dryRun: true,
},
);
return content;
}
getIndexToInsert() {

View File

@ -1,8 +1,7 @@
import { config } from "../../../package.json";
import { VirtualizedTableHelper } from "zotero-plugin-toolkit";
import { VirtualizedTableHelper } from "zotero-plugin-toolkit/dist/helpers/virtualizedTable";
import { PluginCEBase } from "../base";
import {
getPref,
getPrefJSON,
registerPrefObserver,
setPref,
@ -20,26 +19,17 @@ export class NotePicker extends PluginCEBase {
itemsView!: _ZoteroTypes.ItemTree;
collectionsView!: _ZoteroTypes.CollectionTree;
openedNotesView!: VirtualizedTableHelper;
recentNotesView!: VirtualizedTableHelper;
_collectionsList!: XULBoxElement;
_collectionsList!: XUL.Box;
openedNotes: Zotero.Item[] = [];
recentNotes: Zotero.Item[] = [];
activeSelectionType: "library" | "tabs" | "recent" | "none" = "none";
activeSelectionType: "library" | "tabs" | "none" = "none";
uid = Zotero.Utilities.randomString(8);
_prefObserverID!: symbol;
_cachedLibraryIDs: number[] = [];
_cachedSelectedNoteIDs: number[] = [];
_disableSelectionChange = false;
get content() {
return MozXULElement.parseXULToFragment(`
<linkset>
@ -72,20 +62,14 @@ export class NotePicker extends PluginCEBase {
<html:div id="zotero-items-tree"></html:div>
</hbox>
</hbox>
<hbox id="bn-select-opened-notes-container" class="container">
<vbox id="bn-select-opened-notes-container" class="container">
<vbox
id="bn-select-opened-notes-content"
class="container virtualized-table-container bn-note-list-container"
class="container virtualized-table-container"
>
<html:div id="bn-select-opened-notes-tree-${this.uid}"></html:div>
</vbox>
<vbox
id="bn-select-recent-notes-content"
class="container virtualized-table-container bn-note-list-container"
>
<html:div id="bn-select-recent-notes-tree-${this.uid}"></html:div>
</vbox>
</hbox>
</vbox>
</vbox>
</vbox>
</vbox>
@ -107,7 +91,7 @@ export class NotePicker extends PluginCEBase {
this._collectionsList = this.querySelector(
"#zotero-collections-tree-container",
) as XULBoxElement;
) as XUL.Box;
this._restoreState();
@ -125,8 +109,8 @@ export class NotePicker extends PluginCEBase {
}
destroy(): void {
this.collectionsView?.unregister();
this.itemsView?.unregister();
this.collectionsView.unregister();
if (this.itemsView) this.itemsView.unregister();
unregisterPrefObserver(this._prefObserverID);
}
@ -134,10 +118,6 @@ export class NotePicker extends PluginCEBase {
await this.loadLibraryNotes();
this.loadQuickSearch();
await this.loadOpenedNotes();
this.recentNotes = this.getRecentNotes();
await this.loadRecentNotes();
}
async loadLibraryNotes() {
@ -270,78 +250,6 @@ export class NotePicker extends PluginCEBase {
// }
}
async loadRecentNotes() {
const renderLock = Zotero.Promise.defer();
this.recentNotesView = new VirtualizedTableHelper(window)
.setContainerId(`bn-select-recent-notes-tree-${this.uid}`)
.setProp({
id: `bn-select-recent-notes-table-${this.uid}`,
columns: [
{
dataKey: "title",
label: "Recent Notes",
flex: 1,
},
],
showHeader: true,
multiSelect: false,
staticColumns: true,
disableFontSizeScaling: true,
})
.setProp("getRowCount", () => this.recentNotes.length || 0)
.setProp("getRowData", (index) => {
const note = this.recentNotes[index];
return {
title: note.getNoteTitle(),
};
})
.setProp("onSelectionChange", (selection) => {
this.onRecentNoteSelected(selection);
})
// For find-as-you-type
.setProp(
"getRowString",
(index) => this.recentNotes[index].getNoteTitle() || "",
)
.setProp("renderItem", (index, selection, oldElem, columns) => {
let div;
if (oldElem) {
div = oldElem;
div.innerHTML = "";
} else {
div = document.createElement("div");
div.className = "row";
}
div.classList.toggle("selected", selection.isSelected(index));
div.classList.toggle("focused", selection.focused == index);
const rowData = this.recentNotes[index];
for (const column of columns) {
const span = document.createElement("span");
// @ts-ignore
span.className = `cell ${column?.className}`;
span.textContent = rowData.getNoteTitle();
const icon = getCSSItemTypeIcon("note");
icon.classList.add("cell-icon");
span.prepend(icon);
div.append(span);
}
return div;
})
.render(-1, () => {
renderLock.resolve();
});
await renderLock.promise;
if (this.recentNotes.length > 0) {
setTimeout(() => {
this.recentNotesView.treeInstance.selection.select(0);
this.onRecentNoteSelected(this.recentNotesView.treeInstance.selection);
}, 200);
}
}
onSearch() {
if (this.itemsView) {
const searchVal = (
@ -399,98 +307,23 @@ export class NotePicker extends PluginCEBase {
}
onItemSelected() {
if (this._disableSelectionChange) {
return;
}
this.activeSelectionType = "library";
const selectedIDs = this.itemsView.getSelectedItems(true) as number[];
// Compare the selected IDs with the cached IDs
// Since the library selection change can be triggered multiple times or with no change
if (arraysEqual(this._cachedLibraryIDs, selectedIDs)) {
return;
}
this.deselectOtherPanes();
this.dispatchSelectionChange();
}
onOpenedNoteSelected(selection: { selected: Set<number> }) {
if (this._disableSelectionChange) {
return;
}
this.activeSelectionType = "tabs";
this.deselectOtherPanes();
this.dispatchSelectionChange(selection);
}
onRecentNoteSelected(selection: { selected: Set<number> }) {
if (this._disableSelectionChange) {
return;
}
this.activeSelectionType = "recent";
this.deselectOtherPanes();
this.dispatchSelectionChange(selection);
}
deselectItemsPane() {
this.itemsView?.selection?.clearSelection();
}
deselectOpenedNotePane() {
this.openedNotesView?.treeInstance?.selection?.clearSelection();
}
deselectRecentNotePane() {
this.recentNotesView?.treeInstance?.selection?.clearSelection();
}
deselectOtherPanes() {
this._disableSelectionChange = true;
if (this.activeSelectionType !== "library") this.deselectItemsPane();
if (this.activeSelectionType !== "tabs") this.deselectOpenedNotePane();
if (this.activeSelectionType !== "recent") this.deselectRecentNotePane();
this._disableSelectionChange = false;
}
getRecentNotes() {
return ((getPref("linkCreator.recentNotes") as string) || "")
.split(",")
.map((id) => Zotero.Items.get(parseInt(id)))
.filter((item) => item && item.isNote());
}
saveRecentNotes() {
const selectedNotes = this.getSelectedNotes();
if (!selectedNotes.length) {
return;
}
const recentNotes: number[] = [...selectedNotes.map((note) => note.id)];
for (const note of this.recentNotes) {
if (!recentNotes.includes(note.id)) {
recentNotes.push(note.id);
}
}
// Save only 10 recent notes
setPref("linkCreator.recentNotes", recentNotes.slice(0, 10).join(","));
}
dispatchSelectionChange(selection?: { selected: Set<number> }) {
if (this._disableSelectionChange) {
return false;
}
const selectedNotes = this.getSelectedNotes(selection);
const selectedNoteIDs = selectedNotes.map((n) => n.id);
if (arraysEqual(this._cachedSelectedNoteIDs, selectedNoteIDs)) {
return false;
}
this._cachedSelectedNoteIDs = selectedNoteIDs;
this.dispatchEvent(
new CustomEvent("selectionchange", {
detail: {
selectedNotes,
selectedNote: this.getSelectedNotes(selection)[0],
},
}),
);
return true;
}
getSelectedNotes(selection?: { selected: Set<number> }): Zotero.Item[] {
@ -498,22 +331,16 @@ export class NotePicker extends PluginCEBase {
return [];
} else if (this.activeSelectionType == "library") {
return this.itemsView.getSelectedItems();
} else if (this.activeSelectionType == "tabs") {
return Array.from(
(selection || this.openedNotesView.treeInstance.selection).selected,
).map((index) => this.openedNotes[index]);
} else if (this.activeSelectionType == "recent") {
return Array.from(
(selection || this.recentNotesView.treeInstance.selection).selected,
).map((index) => this.recentNotes[index]);
}
return [];
return Array.from(
(selection || this.openedNotesView.treeInstance.selection).selected,
).map((index) => this.openedNotes[index]);
}
_persistState() {
let state = getPrefJSON(persistKey);
const collectionsListWidth = getComputedStyle(this._collectionsList)?.width;
const collectionsListWidth = getComputedStyle(this._collectionsList).width;
if (state?.collectionsListWidth === collectionsListWidth) {
return;
}
@ -531,24 +358,9 @@ export class NotePicker extends PluginCEBase {
if (
typeof state.collectionsListWidth === "string" &&
state.collectionsListWidth !==
Number(getComputedStyle(this._collectionsList)?.width)
Number(getComputedStyle(this._collectionsList).width)
) {
this._collectionsList.style.width = state.collectionsListWidth;
}
}
}
function arraysEqual(arr1: number[], arr2: number[]): boolean {
if (arr1.length !== arr2.length) return false;
const set1 = new Set(arr1);
const set2 = new Set(arr2);
if (set1.size !== set2.size) return false;
for (const item of set1) {
if (!set2.has(item)) return false;
}
return true;
}

View File

@ -1,5 +1,5 @@
import { config } from "../../../package.json";
import { VirtualizedTableHelper } from "zotero-plugin-toolkit";
import { VirtualizedTableHelper } from "zotero-plugin-toolkit/dist/helpers/virtualizedTable";
import { PluginCEBase } from "../base";
import TreeModel = require("tree-model");
import { waitUtilAsync } from "../../utils/wait";

View File

@ -13,7 +13,7 @@ export class OutboundCreator extends PluginCEBase {
// Where the link is inserted to
currentNote: Zotero.Item | undefined;
// Where the link is generated from
targetNotes: Zotero.Item[] | undefined;
targetNote: Zotero.Item | undefined;
positionData: NoteNodeData | undefined;
@ -68,11 +68,10 @@ export class OutboundCreator extends PluginCEBase {
}
async accept(io: any) {
if (!this.targetNotes) return;
this.notePicker.saveRecentNotes();
if (!this.targetNote) return;
const content = await this.getContentToInsert();
io.targetNoteID = this.currentNote!.id;
io.sourceNoteIDs = this.targetNotes.map((item) => item.id).filter(Boolean);
io.content = content;
io.lineIndex = this.getIndexToInsert();
}
@ -83,10 +82,10 @@ export class OutboundCreator extends PluginCEBase {
await this.notePicker.load();
this.notePicker.addEventListener("selectionchange", (event: any) => {
this.targetNotes = this.notePicker.getSelectedNotes();
this.updatePickerTitle(this.targetNotes);
this.targetNote = event.detail.selectedNote;
this.updatePickerTitle(this.targetNote);
this.updateNotePreview();
if (this.targetNotes) this.scrollToSection("outline");
if (this.targetNote) this.scrollToSection("outline");
});
const content = document.createElement("span");
@ -166,22 +165,9 @@ export class OutboundCreator extends PluginCEBase {
?.append(content, fromTitle, middleTitle, toTitle);
}
getPickedNotesTitle(noteItems?: Zotero.Item[]) {
let title = "";
if (!noteItems?.length) {
title = "-";
}
if (noteItems?.length === 1) {
title = noteItems[0].getNoteTitle();
} else {
title = `${noteItems?.length} notes`;
}
return title;
}
updatePickerTitle(noteItems?: Zotero.Item[]) {
this.querySelector("#selected-note-title")!.textContent =
this.getPickedNotesTitle(noteItems);
updatePickerTitle(noteItem?: Zotero.Item) {
const title = noteItem ? noteItem.getNoteTitle() : "";
this.querySelector("#selected-note-title")!.textContent = title;
}
updateOutlineTitle() {
@ -196,7 +182,7 @@ export class OutboundCreator extends PluginCEBase {
this.querySelector("#preview-note-middle-title") as HTMLElement
).dataset.l10nArgs = `{"show": "true"}`;
this.querySelector("#preview-note-to-title")!.textContent =
this.getPickedNotesTitle(this.targetNotes);
this.targetNote?.getNoteTitle() || "No title";
}
async updateNotePreview() {
@ -237,17 +223,21 @@ export class OutboundCreator extends PluginCEBase {
}
async getContentToInsert() {
if (!this.currentNote || !this.targetNotes?.length) return "";
let content = "";
for (const note of this.targetNotes) {
content += await this._addon.api.template.runQuickInsertTemplate(
note,
if (!this.currentNote || !this.targetNote) return "";
const forwardLink = this._addon.api.convert.note2link(this.targetNote, {});
const content = await this._addon.api.template.runTemplate(
"[QuickInsertV2]",
"link, linkText, subNoteItem, noteItem",
[
forwardLink,
this.targetNote.getNoteTitle().trim() || forwardLink,
this.targetNote,
this.currentNote,
{ dryRun: true },
);
content += "\n";
}
],
{
dryRun: true,
},
);
return content;
}

View File

@ -1,5 +1,5 @@
import { config } from "../../../package.json";
import { VirtualizedTableHelper } from "zotero-plugin-toolkit";
import { VirtualizedTableHelper } from "zotero-plugin-toolkit/dist/helpers/virtualizedTable";
import { PluginCEBase } from "../base";
import TreeModel = require("tree-model");
@ -131,9 +131,7 @@ export class OutlinePicker extends PluginCEBase {
if (!this.item) {
return;
}
this.noteOutline = await this._addon.api.note.getNoteTreeFlattened(
this.item,
);
this.noteOutline = this._addon.api.note.getNoteTreeFlattened(this.item);
// Fake a cursor position
if (typeof this.lineIndex === "number") {
// @ts-ignore - formatValues is not in the types
@ -167,11 +165,10 @@ export class OutlinePicker extends PluginCEBase {
}
getSelectedSection(selection?: { selected: Set<number> }): NoteNodeData {
const selected = (
selection || this.noteOutlineView.treeInstance.selection
).selected
.values()
.next().value;
return this.noteOutline[selected!]?.model;
return this.noteOutline[
(selection || this.noteOutlineView.treeInstance.selection).selected
.values()
.next().value
]?.model;
}
}

View File

@ -1,4 +1,4 @@
import { FilePickerHelper } from "zotero-plugin-toolkit";
import { FilePickerHelper } from "zotero-plugin-toolkit/dist/helpers/filePicker";
import { config } from "../../../package.json";
import { formatPath } from "../../utils/str";
import { waitUtilAsync } from "../../utils/wait";
@ -148,7 +148,7 @@ export class OutlinePane extends PluginCEBase {
this._notifierID = Zotero.Notifier.registerObserver(
this,
["item"],
"bn-outline",
"attachmentsBox",
);
this._prefObserverID = registerPrefObserver(
@ -211,13 +211,12 @@ export class OutlinePane extends PluginCEBase {
"message",
this.messageHandler,
);
const nodes = await this._addon.api.note.getNoteTreeFlattened(this.item, {
keepLink: !!getPref("workspace.outline.keepLinks"),
});
this._outlineContainer.contentWindow?.postMessage(
{
type: "setMindMapData",
nodes,
nodes: this._addon.api.note.getNoteTreeFlattened(this.item, {
keepLink: !!getPref("workspace.outline.keepLinks"),
}),
expandLevel: getPref("workspace.outline.expandLevel"),
},
"*",
@ -236,7 +235,7 @@ export class OutlinePane extends PluginCEBase {
// Update set outline menu
this._queryID("setOutlinePopup")?.childNodes.forEach((elem) =>
(elem as XULMenuItemElement).removeAttribute("checked"),
(elem as XUL.MenuItem).removeAttribute("checked"),
);
this._queryID(
Object.keys(OutlinePane.outlineMenuIDs)[this.outlineType],
@ -268,7 +267,7 @@ export class OutlinePane extends PluginCEBase {
toolbarButtonCommandHandler = async (ev: Event) => {
if (!this.item) return;
const type = this._unwrapID((ev.target as XULToolBarButtonElement).id);
const type = this._unwrapID((ev.target as XUL.ToolBarButton).id);
switch (type) {
case "useTreeView":
case "useMindMap":
@ -317,13 +316,13 @@ export class OutlinePane extends PluginCEBase {
}
case "moveNode": {
if (!this.item) return;
const tree = await this._addon.api.note.getNoteTree(this.item);
const fromNode = await this._addon.api.note.getNoteTreeNodeById(
const tree = this._addon.api.note.getNoteTree(this.item);
const fromNode = this._addon.api.note.getNoteTreeNodeById(
this.item,
ev.data.fromID,
tree,
);
const toNode = await this._addon.api.note.getNoteTreeNodeById(
const toNode = this._addon.api.note.getNoteTreeNodeById(
this.item,
ev.data.toID,
tree,

View File

@ -21,11 +21,11 @@ export class Workspace extends PluginCEBase {
_editorElement!: EditorElement;
_outline!: OutlinePane;
_editorContainer!: XULBoxElement;
_editorContainer!: XUL.Box;
_context!: ContextPane;
_leftSplitter!: XULSplitterElement;
_rightSplitter!: XULSplitterElement;
_leftSplitter!: XUL.Splitter;
_rightSplitter!: XUL.Splitter;
resizeOb!: ResizeObserver;
@ -93,14 +93,14 @@ export class Workspace extends PluginCEBase {
this._outline = this._queryID("left-container") as unknown as OutlinePane;
this._editorContainer = this._queryID("center-container") as XULBoxElement;
this._editorContainer = this._queryID("center-container") as XUL.Box;
this._editorElement = this._queryID("editor-main") as EditorElement;
this._outline._editorElement = this._editorElement;
this._context = this._queryID("right-container") as unknown as ContextPane;
this._leftSplitter = this._queryID("left-splitter") as XULSplitterElement;
this._rightSplitter = this._queryID("right-splitter") as XULSplitterElement;
this._leftSplitter = this._queryID("left-splitter") as XUL.Splitter;
this._rightSplitter = this._queryID("right-splitter") as XUL.Splitter;
this._leftSplitter.addEventListener("mouseup", () => {
this._persistState();

View File

@ -1,91 +0,0 @@
import { insert } from "../../utils/editor";
export { formatMessage };
function formatMessage(message: string, locale: string) {
const stringObj = editorStrings[message as keyof typeof editorStrings];
if (!stringObj) {
return message;
}
return stringObj[locale as "en-US" | "zh-CN"] || message;
}
const editorStrings = {
insertTemplate: {
"en-US": "Insert Template",
"zh-CN": "插入模板",
},
outboundLink: {
"en-US": "Insert Outbound Link (Link to another note)",
"zh-CN": "插入出链 (链接到另一个笔记)",
},
inboundLink: {
"en-US": "Insert Inbound Link in another note (Link to this note)",
"zh-CN": "插入入链到另一笔记 (链接到本笔记)",
},
insertCitation: {
"en-US": "Insert Citation",
"zh-CN": "插入引用",
},
openAttachment: {
"en-US": "Open attachment of parent item",
"zh-CN": "打开父条目的附件",
},
copySectionLink: {
"en-US": "Copy Section Link",
"zh-CN": "复制章节链接",
},
copyLineLink: {
"en-US": "Copy Line Link",
"zh-CN": "复制行链接",
},
refreshTemplates: {
"en-US": "Update content from templates",
"zh-CN": "更新模板生成内容",
},
heading1: {
"en-US": "Heading 1",
"zh-CN": "一级标题",
},
heading2: {
"en-US": "Heading 2",
"zh-CN": "二级标题",
},
heading3: {
"en-US": "Heading 3",
"zh-CN": "三级标题",
},
paragraph: {
"en-US": "Paragraph",
"zh-CN": "段落",
},
monospaced: {
"en-US": "Monospaced",
"zh-CN": "等宽",
},
bulletList: {
"en-US": "Bullet List",
"zh-CN": "无序列表",
},
orderedList: {
"en-US": "Ordered List",
"zh-CN": "有序列表",
},
blockquote: {
"en-US": "Blockquote",
"zh-CN": "引用",
},
mathBlock: {
"en-US": "Math Block",
"zh-CN": "数学",
},
clearFormatting: {
"en-US": "Clear Format",
"zh-CN": "清除格式",
},
table: {
"en-US": "Table",
"zh-CN": "表格",
},
};

View File

@ -1,7 +1,7 @@
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
import { Popup } from "./popup";
export { initLinkPreviewPlugin, LinkPreviewOptions };
export { initLinkPreviewPlugin };
declare const _currentEditorInstance: {
_editorCore: EditorCore;
@ -14,11 +14,9 @@ interface LinkPreviewOptions {
) => void;
openURL: (url: string) => void;
previewType: "hover" | "ctrl" | "disable";
}
class PluginState {
class LinkPreviewState {
state: EditorState;
options: LinkPreviewOptions;
@ -40,10 +38,6 @@ class PluginState {
update(state: EditorState, prevState?: EditorState) {
this.state = state;
if (this.options.previewType === "disable") {
return;
}
if (
prevState &&
prevState.doc.eq(state.doc) &&
@ -62,10 +56,6 @@ class PluginState {
}
handleMouseMove = async (event: MouseEvent) => {
if (this.options.previewType === "disable") {
return;
}
const { target } = event;
let isValid = false;
@ -77,7 +67,7 @@ class PluginState {
this.node = target;
this.currentLink = href;
this.hasHover = true;
this.tryOpenPopupByHover();
this.tryOpenPopup();
}
}
}
@ -89,26 +79,7 @@ class PluginState {
}
};
handleKeydown = async (event: KeyboardEvent) => {
if (this.options.previewType !== "ctrl") {
return;
}
if (!this.hasHover || !this.currentLink) {
return;
}
const isMac =
typeof navigator != "undefined" ? /Mac/.test(navigator.platform) : false;
if ((isMac && event.metaKey) || (!isMac && event.ctrlKey)) {
this.tryTogglePopupByKey();
}
};
tryOpenPopupByHover() {
if (this.options.previewType !== "hover") {
return;
}
tryOpenPopup() {
const href = this.currentLink!;
setTimeout(() => {
if (this.currentLink === href) {
@ -117,14 +88,6 @@ class PluginState {
}, 300);
}
tryTogglePopupByKey() {
if (this._hasPopup()) {
this._closePopup();
} else {
this._openPopup();
}
}
_openPopup() {
console.log("Enter Link Preview", this.currentLink, this.options);
document.querySelectorAll(".link-preview").forEach((el) => el.remove());
@ -143,9 +106,6 @@ class PluginState {
max-width: 100%;
height: auto;
}
.link-preview .primary-editor li {
white-space: normal;
}
</style>`),
]);
this.popup.popup.classList.add("primary-editor");
@ -195,61 +155,41 @@ class PluginState {
document.querySelectorAll(".link-preview").forEach((el) => el.remove());
this.popup = null;
}
_hasPopup() {
return !!document.querySelector(".link-preview");
}
}
function initLinkPreviewPlugin(
plugins: readonly Plugin[],
options: LinkPreviewOptions,
) {
function initLinkPreviewPlugin(options: LinkPreviewOptions) {
const core = _currentEditorInstance._editorCore;
console.log("Init BN Link Preview Plugin");
const key = new PluginKey("linkPreviewPlugin");
return [
...plugins,
new Plugin({
key,
state: {
init(config, state) {
return new PluginState(state, options);
},
apply: (tr, pluginState, oldState, newState) => {
pluginState.update(newState, oldState);
return pluginState;
},
},
props: {
handleDOMEvents: {
mousemove: (view, event) => {
const pluginState = key.getState(view.state) as PluginState;
pluginState.update(view.state);
pluginState.handleMouseMove(event);
const newState = core.view.state.reconfigure({
plugins: [
...core.view.state.plugins,
new Plugin({
key,
state: {
init(config, state) {
return new LinkPreviewState(state, options);
},
keydown: (view, event) => {
const pluginState = key.getState(view.state) as PluginState;
pluginState.handleKeydown(event);
},
wheel: (view, event) => {
const pluginState = key.getState(view.state) as PluginState;
pluginState.popup?.layoutPopup(pluginState);
apply: (tr, pluginState, oldState, newState) => {
pluginState.update(newState, oldState);
return pluginState;
},
},
},
view: (editorView) => {
return {
update(view, prevState) {
const pluginState = key.getState(view.state) as PluginState;
pluginState.update(view.state, prevState);
props: {
handleDOMEvents: {
mousemove: (view, event) => {
const pluginState = key.getState(view.state) as LinkPreviewState;
pluginState.update(view.state);
pluginState.handleMouseMove(event);
},
wheel: (view, event) => {
const pluginState = key.getState(view.state) as LinkPreviewState;
pluginState.popup?.layoutPopup(pluginState);
},
},
destroy() {
const pluginState = key.getState(editorView.state) as PluginState;
pluginState.destroy();
},
};
},
}),
];
},
}),
],
});
core.view.updateState(newState);
}

View File

@ -1,643 +0,0 @@
import { EditorState, Plugin, PluginKey, Transaction } from "prosemirror-state";
import { Popup } from "./popup";
import { formatMessage } from "./editorStrings";
export { initMagicKeyPlugin, MagicKeyOptions };
declare const _currentEditorInstance: {
_editorCore: EditorCore;
};
interface MagicKeyOptions {
insertTemplate?: () => void;
refreshTemplates?: () => void;
insertLink?: (type: "inbound" | "outbound") => void;
copyLink?: (mode: "section" | "line") => void;
openAttachment?: () => void;
canOpenAttachment?: () => boolean;
enable?: boolean;
}
interface MagicCommand {
messageId?: string;
searchParts?: string[];
title?: string;
icon?: string;
command: (state: EditorState) => void | Transaction;
enabled?: (state: EditorState) => boolean;
}
class PluginState {
state: EditorState;
options: MagicKeyOptions;
_commands: MagicCommand[] = [
{
messageId: "insertTemplate",
searchParts: ["it", "insertTemplate"],
command: (state) => {
this.options.insertTemplate?.();
},
},
{
messageId: "outboundLink",
searchParts: ["ol", "obl", "outboundLink"],
command: (state) => {
this.options.insertLink?.("outbound");
},
},
{
messageId: "inboundLink",
searchParts: ["il", "ibl", "inboundLink"],
command: (state) => {
this.options.insertLink?.("inbound");
},
},
{
messageId: "insertCitation",
searchParts: ["ic", "insertCitation"],
command: (state) => {
getPlugin("citation")?.insertCitation();
},
},
{
messageId: "openAttachment",
searchParts: ["oa", "openAttachment"],
command: (state) => {
this.options.openAttachment?.();
},
enabled: (state) => {
return this.options.canOpenAttachment?.() || false;
},
},
{
messageId: "copySectionLink",
searchParts: ["csl", "copySectionLink"],
command: (state) => {
this.options.copyLink?.("section");
},
},
{
messageId: "copyLineLink",
searchParts: ["cll", "copyLineLink"],
command: (state) => {
this.options.copyLink?.("line");
},
},
{
messageId: "refreshTemplates",
searchParts: ["rt", "refreshTemplates"],
command: (state) => {
this.options.refreshTemplates?.();
},
},
{
messageId: "table",
searchParts: ["t", "tb", "table"],
command: (state) => {
const input = prompt(
"Enter the number of rows and columns, separated by a comma (e.g., 3,3)",
);
if (!input) {
return state.tr;
}
const splitter = input.includes("x")
? "x"
: input.includes(",")
? ","
: " ";
const [rows, cols] = input.split(splitter).map((n) => parseInt(n, 10));
if (isNaN(rows) || isNaN(cols)) {
return state.tr;
}
const { tr, selection } = state;
const { $from, $to } = selection;
const { pos } = $from;
const table = state.schema.nodes.table.createAndFill(
{},
Array.from(
{ length: rows },
() =>
state.schema.nodes.table_row.createAndFill(
{},
Array.from(
{ length: cols },
() => state.schema.nodes.table_cell.createAndFill()!,
),
)!,
),
)!;
tr.replaceWith(pos, pos, table);
_currentEditorInstance._editorCore.view.dispatch(tr);
},
},
{
messageId: "heading1",
searchParts: ["h1", "heading1"],
command: (state) => {
getPlugin()?.heading1.run();
},
},
{
messageId: "heading2",
searchParts: ["h2", "heading2"],
command: (state) => {
getPlugin()?.heading2.run();
},
},
{
messageId: "heading3",
searchParts: ["h3", "heading3"],
command: (state) => {
getPlugin()?.heading3.run();
},
},
{
messageId: "paragraph",
searchParts: ["p", "paragraph"],
command: (state) => {
getPlugin()?.paragraph.run();
},
},
{
messageId: "monospaced",
searchParts: ["m", "monospaced"],
command: (state) => {
getPlugin()?.codeBlock.run();
},
},
{
messageId: "bulletList",
searchParts: ["ul", "bulletList", "unorderedList"],
command: (state) => {
getPlugin()?.bulletList.run();
},
},
{
messageId: "orderedList",
searchParts: ["ol", "orderedList"],
command: (state) => {
getPlugin()?.orderedList.run();
},
},
{
messageId: "blockquote",
searchParts: ["bq", "blockquote"],
command: (state) => {
getPlugin()?.blockquote.run();
},
},
{
messageId: "mathBlock",
searchParts: ["mb", "mathBlock"],
command: (state) => {
getPlugin()?.math_display.run();
},
},
{
messageId: "clearFormatting",
searchParts: ["cf", "clearFormatting"],
command: (state) => {
getPlugin()?.clearFormatting.run();
},
},
];
get commands() {
return this._commands.filter((command) => {
if (command.enabled) {
return command.enabled(this.state);
}
return true;
});
}
popup: Popup | null = null;
selectedCommandIndex = 0;
get node() {
const node =
// @ts-ignore - private API
_currentEditorInstance._editorCore.view.domSelection().anchorNode;
if (node.nodeType === Node.TEXT_NODE) {
return node.parentElement;
}
return node;
}
popupClass = "command-palette";
constructor(state: EditorState, options: MagicKeyOptions) {
this.state = state;
this.options = options;
const locale = window.navigator.language || "en-US";
for (const key in this.commands) {
const command = this.commands[key];
if (command.messageId) {
command.title = formatMessage(command.messageId, locale);
}
}
this.update(state);
}
update(state: EditorState, prevState?: EditorState) {
this.state = state;
if (!prevState) {
return;
}
// Check if the selection has changed, then try to close the popup
if (!prevState.selection.eq(state.selection)) {
this._closePopup();
}
// If the document hasn't changed, we don't need to do anything
if (prevState.doc.eq(state.doc)) {
return;
}
// When `/` is pressed, we should open the command palette
const selectionText = state.doc.textBetween(
state.selection.from,
state.selection.to,
);
if (!selectionText) {
const { $from } = this.state.selection;
const { parent } = $from;
// Don't open the popup if we are in the document root
if (parent.type.name === "doc") {
return;
}
const text = parent.textContent;
if (text.endsWith("/") && !text.endsWith("//")) {
this._openPopup(state);
} else {
this._closePopup();
}
}
}
destroy() {
this.popup?.remove();
}
handleKeydown = async (event: KeyboardEvent) => {
if (!this._hasPopup()) {
return;
}
if (event.key === "Escape") {
this._closePopup();
}
};
_openPopup(state: EditorState) {
if (this._hasPopup()) {
return;
}
this.popup = new Popup(document, this.popupClass, [
document.createRange().createContextualFragment(`
<style>
.${this.popupClass} > .popup {
max-width: 360px;
max-height: 360px;
overflow: hidden;
}
.${this.popupClass} > .popup input {
padding: 0 7px;
background: var(--material-background);
border-radius: 5px;
border: var(--material-border-quinary);
width: 100%;
outline: none;
height: 28px;
flex-shrink: 0;
}
.${this.popupClass} > .popup input:focus {
outline: none;
border-color: rgba(0, 0, 0, 0);
box-shadow: 0 0 0 var(--width-focus-border) var(--color-focus-search);
}
.${this.popupClass} .popup-content {
display: flex;
flex-direction: column;
gap: 6px;
padding: 6px;
}
.${this.popupClass} .popup-list {
display: flex;
flex-direction: column;
gap: 4px;
overflow: hidden auto;
}
.${this.popupClass} .popup-item {
padding: 6px;
cursor: pointer;
border-radius: 5px;
}
.${this.popupClass} .popup-item:hover {
background-color: var(--fill-senary);
}
.${this.popupClass} .popup-item.selected {
background-color: var(--color-accent);
color: #fff;
}
</style>
<div class="popup-content">
<input type="text" class="popup-input" placeholder="Search commands" />
<div class="popup-list" tabindex="-1">
${Object.entries(this.commands)
.map(
([id, command]) => `
<div class="popup-item" data-command-id="${id}">
<div class="popup-item-icon">${command.icon || ""}</div>
<div class="popup-item-title">${command.title}</div>
</div>`,
)
.join("")}
</div>
</div>`),
]);
this.popup.layoutPopup(this);
// Focus the input
const input = this.popup.container.querySelector(
".popup-input",
) as HTMLInputElement;
input.focus();
// Handle input
input.addEventListener("input", (event) => {
const target = event.target as HTMLInputElement;
const value = target.value;
for (const [id, command] of Object.entries(this.commands)) {
const item = this.popup!.container.querySelector(
`.popup-item[data-command-id="${id}"]`,
) as HTMLElement;
if (!value) {
item.hidden = false;
continue;
}
const matchedIndex = command
.title!.toLowerCase()
.indexOf(value.toLowerCase());
if (
matchedIndex < 0 &&
// Try to match the search parts
!command.searchParts?.some((part) =>
part.toLowerCase().includes(value.toLowerCase()),
)
) {
item.hidden = true;
} else {
item.hidden = false;
}
if (matchedIndex >= 0) {
// Change the matched part to bold
const title = command.title!;
item.querySelector(".popup-item-title")!.innerHTML =
title.slice(0, matchedIndex) +
`<b>${title.slice(matchedIndex, matchedIndex + value.length)}</b>` +
title.slice(matchedIndex + value.length);
}
}
this._selectCommand();
});
input.addEventListener("keydown", (event) => {
if (event.key === "ArrowUp") {
this._selectCommand(this.selectedCommandIndex - 1, "up");
event.preventDefault();
} else if (event.key === "ArrowDown") {
this._selectCommand(this.selectedCommandIndex + 1, "down");
event.preventDefault();
} else if (event.key === "ArrowLeft") {
// Select the first command
this._selectCommand(this.commands.length, "up");
event.preventDefault();
} else if (event.key === "ArrowRight") {
// Select the last command
this._selectCommand(-1, "down");
event.preventDefault();
} else if (event.key === "Tab") {
// If has input, autocomplete the selected command to the first space
const command = this.commands[this.selectedCommandIndex];
if (!command) {
return;
}
if (!input.value) {
return;
}
const title = command.title!;
// Compute after the matched part
const matchedIndex = title
.toLowerCase()
.indexOf(input.value.toLowerCase());
const spaceIndex = title.indexOf(
" ",
matchedIndex + input.value.length,
);
if (spaceIndex >= 0) {
input.value = title.slice(0, spaceIndex);
} else {
input.value = title;
}
event.preventDefault();
} else if (event.key === "Enter") {
event.preventDefault();
const command = this.commands[this.selectedCommandIndex];
if (!command) {
this._closePopup();
return;
}
this._executeCommand(this.selectedCommandIndex, state);
} else if (event.key === "Escape") {
event.preventDefault();
this._closePopup();
} else if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
this._closePopup();
this.removeInputSlash(state);
}
});
this.popup.container.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
const target = event.target as HTMLElement;
// Find the command
const item = target.closest(".popup-item") as HTMLElement;
if (!item) {
return;
}
const index = parseInt(item.dataset.commandId || "-1", 10);
this._executeCommand(index, state);
});
this._selectCommand(0);
}
_closePopup() {
if (!this._hasPopup()) {
return;
}
document
.querySelectorAll(`.${this.popupClass}`)
.forEach((el) => el.remove());
this.popup = null;
window.BetterNotesEditorAPI.refocusEditor();
}
_hasPopup() {
return !!document.querySelector(`.${this.popupClass}`);
}
_selectCommand(index?: number, direction: "up" | "down" = "down") {
if (typeof index === "undefined") {
index = this.selectedCommandIndex;
}
// Unselect the previous command
this.popup!.container.querySelectorAll(".popup-item.selected").forEach(
(el) => {
el.classList.remove("selected");
},
);
if (!this._hasPopup()) {
return;
}
const items = this.popup!.container.querySelectorAll(
".popup-item",
) as NodeListOf<HTMLElement>;
if (items[index]?.hidden) {
// Will find the next visible item in the specified direction
if (direction === "up") {
for (let i = index - 1; i >= 0; i--) {
if (!items[i].hidden) {
index = i;
break;
}
}
} else if (direction === "down") {
for (let i = index + 1; i < items.length; i++) {
if (!items[i].hidden) {
index = i;
break;
}
}
}
}
if (index >= items.length) {
// Find the first visible item with :first-of-type
const item = this.popup!.container.querySelector(
".popup-item:not([hidden])",
) as HTMLElement;
index = parseInt(item?.dataset.commandId || "-1", 10);
} else if (index < 0) {
// Find the last visible item with :last-of-type
const visibleItems = this.popup!.container.querySelectorAll(
".popup-item:not([hidden])",
);
const item = visibleItems[visibleItems.length - 1] as HTMLElement;
index = parseInt(item?.dataset.commandId || "-1", 10);
}
if (index < 0) {
this.selectedCommandIndex = -1;
return;
}
this.selectedCommandIndex = index;
items[index].classList.add("selected");
// Record the scroll position of the top document
const scrollTop = document.querySelector(".editor-core")!.scrollTop;
items[index].scrollIntoView({
block: "center",
});
// Restore the scroll position
document.querySelector(".editor-core")!.scrollTop = scrollTop;
}
_executeCommand(index: number, state: EditorState) {
const command = this.commands[index];
if (!command) {
return;
}
// Remove the current input `/`
this.removeInputSlash(state);
const newState = _currentEditorInstance._editorCore.view.state;
// Apply the command
try {
const mightBeTr = command.command(newState);
if (mightBeTr) {
_currentEditorInstance._editorCore.view.dispatch(mightBeTr);
}
} catch (error) {
console.error("Error applying command", error);
}
this._closePopup();
}
removeInputSlash(state: EditorState) {
const { $from } = state.selection;
const { pos } = $from;
const tr = state.tr.delete(pos - 1, pos);
_currentEditorInstance._editorCore.view.dispatch(tr);
}
}
function initMagicKeyPlugin(
plugins: readonly Plugin[],
options: MagicKeyOptions,
) {
console.log("Init BN Magic Key Plugin");
const key = new PluginKey("linkPreviewPlugin");
return [
...plugins,
new Plugin({
key,
state: {
init(config, state) {
return new PluginState(state, options);
},
apply: (tr, pluginState, oldState, newState) => {
pluginState.update(newState, oldState);
return pluginState;
},
},
props: {
handleDOMEvents: {
keydown: (view, event) => {
const pluginState = key.getState(view.state) as PluginState;
pluginState.handleKeydown(event);
},
},
},
view: (editorView) => {
return {
update(view, prevState) {
const pluginState = key.getState(view.state) as PluginState;
pluginState.update(view.state, prevState);
},
destroy() {
const pluginState = key.getState(editorView.state) as PluginState;
pluginState.destroy();
},
};
},
}),
];
}
function getPlugin(key = "menu") {
return _currentEditorInstance._editorCore.pluginState[key] as any;
}

View File

@ -1,137 +0,0 @@
import { Plugin, PluginKey } from "prosemirror-state";
import { md2html } from "../../utils/convert";
export { initMarkdownPastePlugin, MarkdownPasteOptions };
declare const _currentEditorInstance: {
_editorCore: EditorCore;
};
interface MarkdownPasteOptions {
enable: boolean;
}
function initMarkdownPastePlugin(plugins: readonly Plugin[]) {
const core = _currentEditorInstance._editorCore;
console.log("Init BN Markdown Paste Plugin");
const key = new PluginKey("pasteDropPlugin");
const oldPastePluginIndex = plugins.findIndex(
(plugin) => plugin.props.handlePaste && plugin.props.handleDrop,
);
if (oldPastePluginIndex === -1) {
console.error("Paste plugin not found");
return plugins;
}
const oldPastePlugin = plugins[oldPastePluginIndex];
return [
...plugins.slice(0, oldPastePluginIndex),
new Plugin({
key,
props: {
handlePaste: (view, event, slice) => {
if (!event.clipboardData) {
return false;
}
const markdown = getMarkdown(event.clipboardData);
if (!markdown) {
// Try the old paste plugin
return oldPastePlugin.props.handlePaste?.apply(oldPastePlugin, [
view,
event,
slice,
]);
}
md2html(markdown).then((html: string) => {
const slice = window.BetterNotesEditorAPI.getSliceFromHTML(
view.state,
html,
);
const tr = view.state.tr.replaceSelection(slice);
view.dispatch(tr);
});
return true;
},
handleDrop: (view, event, slice, moved) => {
if (!event.dataTransfer) {
return false;
}
const markdown = getMarkdown(event.dataTransfer);
if (!markdown) {
// Try the old drop plugin first
return oldPastePlugin.props.handleDrop?.apply(oldPastePlugin, [
view,
event,
slice,
moved,
]);
}
md2html(markdown).then((html: string) => {
const slice = window.BetterNotesEditorAPI.getSliceFromHTML(
view.state,
html,
);
const pos = view.posAtCoords({
left: event.clientX,
top: event.clientY,
});
if (!pos) {
return;
}
// Insert the slice to the current position
const tr = view.state.tr.insert(pos.pos, slice);
view.dispatch(tr);
});
return true;
},
},
view: (editorView) => {
return {
destroy() {},
};
},
}),
...plugins.slice(oldPastePluginIndex + 1),
];
}
function getMarkdown(clipboardData: DataTransfer) {
// If the clipboard contains HTML, don't handle it
if (clipboardData.types.includes("text/html")) {
return false;
}
if (clipboardData.types.includes("text/markdown")) {
return clipboardData.getData("text/markdown");
}
// For Typora
if (clipboardData.types.includes("text/x-markdown")) {
return clipboardData.getData("text/x-markdown");
}
// Match markdown patterns
if (clipboardData.types.includes("text/plain")) {
const text = clipboardData.getData("text/plain");
const markdownPatterns = [
/^#/m, // Headers: Lines starting with #
/^\s*[-+*]\s/m, // Unordered lists: Lines starting with -, +, or *
/^\d+\.\s/m, // Ordered lists: Lines starting with numbers followed by a dot
/\[.*\]\(.*\)/, // Links: [text](url)
/`[^`]+`/, // Inline code: `code`
/^> /m, // Blockquotes: Lines starting with >
/```/, // Code blocks: Triple backticks
];
for (const pattern of markdownPatterns) {
if (pattern.test(text)) {
return text;
}
}
}
return false;
}

View File

@ -1,28 +0,0 @@
import { initLinkPreviewPlugin, LinkPreviewOptions } from "./linkPreview";
import { initMagicKeyPlugin, MagicKeyOptions } from "./magicKey";
import { initMarkdownPastePlugin, MarkdownPasteOptions } from "./markdownPaste";
export { initPlugins };
declare const _currentEditorInstance: {
_editorCore: EditorCore;
};
function initPlugins(options: {
linkPreview: LinkPreviewOptions;
magicKey: MagicKeyOptions;
markdownPaste: MarkdownPasteOptions;
}) {
const core = _currentEditorInstance._editorCore;
let plugins = core.view.state.plugins;
if (options.linkPreview.previewType !== "disable")
plugins = initLinkPreviewPlugin(plugins, options.linkPreview);
if (options.markdownPaste.enable) plugins = initMarkdownPastePlugin(plugins);
if (options.magicKey.enable)
plugins = initMagicKeyPlugin(plugins, options.magicKey);
// Collect all plugins and reconfigure the state only once
const newState = core.view.state.reconfigure({
plugins,
});
core.view.updateState(newState);
}

View File

@ -5,8 +5,6 @@ class Popup {
hasHover = false;
className: string;
get container() {
return this._popup;
}
@ -20,7 +18,6 @@ class Popup {
className?: string,
children: (HTMLElement | DocumentFragment)[] = [],
) {
this.className = className || "";
this._popup = doc.createElement("div");
this._popup.className = `popup-container ${className}`;
this._popup.innerHTML = `
@ -61,7 +58,7 @@ class Popup {
// Bottom
const otherPopupHeight = Array.from(
popupParent.querySelectorAll(
`.popup-container:not(.${this.className}) > .popup.popup-bottom`,
".popup-container:not(.link-preview) > .popup.popup-bottom",
),
).reduce((acc, el) => acc + (el as HTMLElement).offsetHeight, 0);
top =
@ -75,7 +72,7 @@ class Popup {
// Top
const otherPopupHeight = Array.from(
popupParent.querySelectorAll(
`.popup-container:not(.${this.className}) > .popup.popup-top`,
".popup-container:not(.link-preview) > .popup.popup-top",
),
).reduce((acc, el) => acc + (el as HTMLElement).offsetHeight, 0);
top =

View File

@ -11,7 +11,7 @@ import {
} from "prosemirror-model";
import { EditorState, TextSelection } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { initPlugins } from "./editor/plugins";
import { initLinkPreviewPlugin } from "./editor/linkPreview";
declare const _currentEditorInstance: {
_editorCore: EditorCore;
@ -377,7 +377,7 @@ export const BetterNotesEditorAPI = {
getSliceFromHTML,
getNodeFromHTML,
setSelection,
initPlugins,
initLinkPreviewPlugin,
};
// @ts-ignore

View File

@ -1,185 +0,0 @@
import { getPref, setPref } from "../utils/prefs";
let io: {
targetData: {
left: number;
title: string;
};
accepted: boolean;
useBuiltInExport: boolean;
deferred: _ZoteroTypes.Promise.DeferredPromise<void>;
embedLink: boolean;
standaloneLink: boolean;
exportNote: boolean;
exportMD: boolean;
setAutoSync: boolean;
autoMDFileName: boolean;
withYAMLHeader: boolean;
exportDocx: boolean;
exportPDF: boolean;
exportFreeMind: boolean;
};
window.onload = async function () {
if (document.readyState === "complete") {
setTimeout(init, 0);
return;
}
document.addEventListener("DOMContentLoaded", init, { once: true });
};
window.onunload = function () {
io.deferred && io.deferred.resolve();
};
function init() {
const dialog = document.querySelector("dialog")!;
Zotero.UIProperties.registerRoot(dialog);
io = window.arguments[0];
window.addEventListener("dialogaccept", doAccept);
window.addEventListener("dialogextra1", () => doUseBuiltInExport());
document
.querySelector("#format")!
.addEventListener("command", onFormatChange);
document
.querySelector("#linkMode")!
.addEventListener("command", updateMarkdownOptions);
document
.querySelector("#markdown-autoSync")!
.addEventListener("command", updateMarkdownOptions);
(document.querySelector("#target") as XULElement).dataset.l10nArgs =
JSON.stringify(io.targetData);
restore();
onFormatChange();
updateMarkdownOptions();
}
function restore() {
let format = getPref("export.format") as string;
if (!["markdown", "msword", "pdf", "freemind", "note"].includes(format)) {
format = "markdown";
}
(document.querySelector("#format") as XULMenuListElement).value = format;
let linkMode = getPref("export.linkMode") as string;
if (!["keep", "embed", "standalone", "remove"].includes(linkMode)) {
linkMode = "keep";
}
(document.querySelector("#linkMode") as XULRadioGroupElement).value =
linkMode;
const markdownPrefs = ["autoSync", "withYAMLHeader", "autoFilename"];
for (const pref of markdownPrefs) {
(
document.querySelector(`#markdown-${pref}`) as XULCheckboxElement
).checked = getPref(`export.markdown-${pref}`) as boolean;
}
}
function cache() {
setPref(
"export.format",
(document.querySelector("#format") as XULMenuListElement).value,
);
setPref(
"export.linkMode",
(document.querySelector("#linkMode") as XULRadioGroupElement).value,
);
const markdownPrefs = ["autoSync", "withYAMLHeader", "autoFilename"];
for (const pref of markdownPrefs) {
setPref(
`export.markdown-${pref}`,
(document.querySelector(`#markdown-${pref}`) as XULCheckboxElement)
.checked,
);
}
}
function onFormatChange() {
const format = (document.querySelector("#format") as XULMenuListElement)
.value;
const isMD = format === "markdown";
(document.querySelector("#markdown-options") as XULBoxElement).hidden = !isMD;
window.sizeToContent();
}
function updateMarkdownOptions() {
const linkModeRadio = document.querySelector(
"#linkMode",
) as XULRadioGroupElement;
const autoSyncRadio = document.querySelector(
"#markdown-autoSync",
) as XULCheckboxElement;
if (linkModeRadio.value !== "standalone") {
autoSyncRadio.checked = false;
autoSyncRadio.disabled = true;
} else {
autoSyncRadio.disabled = false;
}
const autoFilename = document.querySelector(
"#markdown-autoFilename",
) as XULCheckboxElement;
const withYAMLHeader = document.querySelector(
"#markdown-withYAMLHeader",
) as XULCheckboxElement;
if (autoSyncRadio.checked) {
autoFilename.checked = true;
autoFilename.disabled = true;
withYAMLHeader.checked = true;
withYAMLHeader.disabled = true;
} else {
autoFilename.disabled = false;
withYAMLHeader.disabled = false;
}
}
function doAccept() {
cache();
// Format
const format = (document.querySelector("#format") as XULMenuListElement)
.value;
io.exportMD = format === "markdown";
io.exportDocx = format === "msword";
io.exportPDF = format === "pdf";
io.exportFreeMind = format === "freemind";
io.exportNote = format === "note";
// Markdown options
io.autoMDFileName = (
document.querySelector("#markdown-autoFilename") as XULCheckboxElement
).checked;
io.withYAMLHeader = (
document.querySelector("#markdown-withYAMLHeader") as XULCheckboxElement
).checked;
io.setAutoSync = (
document.querySelector("#markdown-autoSync") as XULCheckboxElement
).checked;
// Link mode
const linkMode = (document.querySelector("#linkMode") as XULRadioGroupElement)
.value;
io.embedLink = linkMode === "embed";
io.standaloneLink = linkMode === "standalone";
io.accepted = true;
}
function doUseBuiltInExport() {
io.useBuiltInExport = true;
window.close();
}

View File

@ -2,7 +2,7 @@ import { getPref, setPref } from "../utils/prefs";
import { InboundCreator } from "../elements/linkCreator/inboundCreator";
import { OutboundCreator } from "../elements/linkCreator/outboundCreator";
let tabbox: XULTabBoxElement;
let tabbox: XUL.TabBox;
let inboundCreator: InboundCreator;
let outboundCreator: OutboundCreator;
@ -10,12 +10,11 @@ let io: {
currentNoteID: number;
currentLineIndex?: number;
openedNoteIDs?: number[];
deferred: _ZoteroTypes.Promise.DeferredPromise<void>;
deferred: _ZoteroTypes.DeferredPromise<void>;
targetNoteID?: number;
content?: string;
lineIndex?: number;
mode?: "inbound" | "outbound";
};
window.onload = async function () {
@ -40,7 +39,7 @@ window.onunload = function () {
function init() {
// Set font size from pref
const sbc = document.getElementById("top-container");
Zotero.UIProperties.registerRoot(sbc!);
Zotero.UIProperties.registerRoot(sbc);
setTimeout(() => {
const size = ((getPref("windows.linkCreator.size") as string) || "").split(
@ -51,20 +50,9 @@ function init() {
io = window.arguments[0];
if (!io.deferred) {
// @ts-ignore
io = io.wrappedJSObject;
}
tabbox = document.querySelector("#top-container")!;
if (io.mode) {
tabbox.selectedIndex = io.mode === "inbound" ? 0 : 1;
} else {
tabbox.selectedIndex =
(getPref("windows.linkCreator.tabIndex") as number) || 0;
}
tabbox.selectedIndex =
(getPref("windows.linkCreator.tabIndex") as number) || 0;
tabbox.addEventListener("select", loadSelectedPanel);
inboundCreator = document.querySelector(

View File

@ -1,112 +0,0 @@
import { MessageHelper } from "zotero-plugin-toolkit";
export { handlers };
function parseHTMLLines(html: string): string[] {
const randomString: string = `${Math.random()}`;
console.time(`parseHTMLLines-${randomString}`);
// Remove container with one of the attrs named data-schema-version if exists
if (html.includes("data-schema-version")) {
html = html.replace(/<div[^>]*data-schema-version[^>]*>/, "");
html = html.replace(/<\/div>/, "");
}
const noteLines = html.split("\n").filter((e) => e);
// A cache for temporarily stored lines
let previousLineCache = [];
let nextLineCache = [];
const forceInline = ["table", "blockquote", "pre", "ol", "ul"];
const selfInline: string[] = [];
const forceInlineStack = [];
let forceInlineFlag = false;
let selfInlineFlag = false;
const parsedLines = [];
for (const line of noteLines) {
// restore self inline flag
selfInlineFlag = false;
// For force inline tags, set flag to append lines to current line
for (const tag of forceInline) {
const startReg = `<${tag}`;
const isStart = line.includes(startReg);
const endReg = `</${tag}>`;
const isEnd = line.includes(endReg);
if (isStart && !isEnd) {
forceInlineStack.push(tag);
// console.log("push", tag, line, forceInlineStack);
forceInlineFlag = true;
break;
}
if (isEnd && !isStart) {
forceInlineStack.pop();
// console.log("pop", tag, line, forceInlineStack);
// Exit force inline mode if the stack is empty
if (forceInlineStack.length === 0) {
forceInlineFlag = false;
}
break;
}
}
if (forceInlineFlag) {
nextLineCache.push(line);
} else {
// For self inline tags, cache start as previous line and end as next line
for (const tag of selfInline) {
const isStart = line.includes(`<${tag}`);
const isEnd = line.includes(`</${tag}>`);
if (isStart && !isEnd) {
selfInlineFlag = true;
nextLineCache.push(line);
break;
}
if (!isStart && isEnd) {
selfInlineFlag = true;
previousLineCache.push(line);
break;
}
}
if (!selfInlineFlag) {
// Append cache to previous line
if (previousLineCache.length) {
parsedLines[parsedLines.length - 1] += `\n${previousLineCache.join(
"\n",
)}`;
previousLineCache = [];
}
let nextLine = "";
// Append cache to next line
if (nextLineCache.length) {
nextLine = nextLineCache.join("\n");
nextLineCache = [];
}
if (nextLine) {
nextLine += "\n";
}
nextLine += `${line}`;
parsedLines.push(nextLine);
}
}
}
console.timeEnd(`parseHTMLLines-${randomString}`);
return parsedLines;
}
const handlers = {
parseHTMLLines,
};
const messageServer = new MessageHelper({
canBeDestroyed: true,
dev: true,
name: "parsingWorker",
target: self,
handlers,
});
messageServer.start();

Some files were not shown because too many files have changed in this diff Show More