joplin-plugin-harper 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/package.json +62 -0
- package/publish/io.github.pmslava.harper.jpl +0 -0
- package/publish/io.github.pmslava.harper.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pmslava
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Harper for Joplin
|
|
2
|
+
|
|
3
|
+
Grammar and spell checking for [Joplin](https://joplinapp.org)'s Markdown editor, powered by
|
|
4
|
+
[Harper](https://writewithharper.com) — the fast, private grammar checker from Automattic.
|
|
5
|
+
|
|
6
|
+
Harper runs **entirely on your machine**. There is no cloud service, no account, and no network
|
|
7
|
+
request: your notes never leave your computer. The whole checker (a compiled WebAssembly engine)
|
|
8
|
+
ships inside the plugin, so it works fully offline.
|
|
9
|
+
|
|
10
|
+
As you type in the Markdown editor, Harper underlines spelling and grammar issues with a coloured
|
|
11
|
+
squiggle, and hovering over one opens a small card with the problem, one-click fixes, and follow-up
|
|
12
|
+
actions.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
Per-kind coloured underlines — a red spelling squiggle, an orange typo, a green word-choice
|
|
19
|
+
suggestion:
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Coloured underlines, one colour per issue type.** Harper sorts every finding into one of its
|
|
26
|
+
lint kinds — Spelling, Grammar, Punctuation, Word Choice, Repetition, Redundancy, Style, and more
|
|
27
|
+
(21 in all) — and each kind gets its own squiggle colour, so you can tell a misspelling from a
|
|
28
|
+
style nudge at a glance. The colours are Harper's own and work in both light and dark themes.
|
|
29
|
+
- **A suggestion card.** Hover over an underline to open a card that shows the issue type, Harper's
|
|
30
|
+
explanation with the flagged word highlighted, and the available fixes.
|
|
31
|
+
- **Apply a fix in one click.** Each suggestion is a pill; clicking it rewrites the text (replace,
|
|
32
|
+
remove, or insert) directly in the editor.
|
|
33
|
+
- **Add to dictionary.** Spelling cards include an add-to-dictionary button, so a name or term you
|
|
34
|
+
use often stops being flagged (see [External dictionary](#external-dictionary) below).
|
|
35
|
+
- **Ignore a single finding.** *Dismiss* hides just that one underline and remembers the choice
|
|
36
|
+
between sessions, without disabling the rule everywhere.
|
|
37
|
+
- **Disable a rule.** The toggle in the card header turns off the rule that produced the finding,
|
|
38
|
+
everywhere, from then on.
|
|
39
|
+
- **Dialects.** Check against American, British, Australian, or Canadian English.
|
|
40
|
+
|
|
41
|
+
## External dictionary
|
|
42
|
+
|
|
43
|
+
By default, words you add via *Add to dictionary* are stored in the plugin's own private word list.
|
|
44
|
+
|
|
45
|
+
You can instead point Harper at a **plain-text dictionary file of your own** — one word per line —
|
|
46
|
+
by setting **External dictionary file** to its absolute path. When that path is set:
|
|
47
|
+
|
|
48
|
+
- Every word in the file is treated as correctly spelled.
|
|
49
|
+
- *Add to dictionary* **appends** the new word to that same file (one word per line).
|
|
50
|
+
- The file is re-read automatically about every 60 seconds, so changes made outside Joplin are
|
|
51
|
+
picked up without a restart.
|
|
52
|
+
|
|
53
|
+
This is deliberately just a flat text file with no special format. That makes it easy to keep the
|
|
54
|
+
file wherever you like and sync it between machines with your own tooling (a synced folder, a
|
|
55
|
+
version-controlled dotfile, `rsync`/`rclone`, and so on) — or to share the same word list with
|
|
56
|
+
another tool that reads a plain word-per-line dictionary. Harper only ever reads and appends lines;
|
|
57
|
+
it never rewrites or reorders the file.
|
|
58
|
+
|
|
59
|
+
## Settings
|
|
60
|
+
|
|
61
|
+
Open **Tools → Options → Harper** (desktop).
|
|
62
|
+
|
|
63
|
+
| Setting | Default | What it does |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| **Enable Harper grammar checking** | On | Master switch. When off, no underlines are shown. |
|
|
66
|
+
| **English dialect** | American | Which English variety Harper checks against: American, British, Australian, or Canadian. |
|
|
67
|
+
| **Lint debounce (ms)** | `500` | How long the editor waits after you stop typing before re-checking, in milliseconds (0–10000). Reopen the note to apply a change to this value. |
|
|
68
|
+
| **External dictionary file** | *(empty)* | Absolute path to a plain-text dictionary (one word per line). Empty means the plugin uses its own private word list. See [External dictionary](#external-dictionary). |
|
|
69
|
+
| **Rule overrides (JSON)** | *(empty)* | *Advanced.* A JSON object of `{"RuleName": true \| false}` applied on top of the defaults, e.g. `{"SpelledNumbers": false}`. Invalid JSON is ignored. |
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
### From the Joplin plugin marketplace
|
|
74
|
+
|
|
75
|
+
Once the plugin is listed: in Joplin desktop, go to **Tools → Options → Plugins**, search for
|
|
76
|
+
**Harper**, and click **Install**. Restart Joplin when prompted.
|
|
77
|
+
|
|
78
|
+
### Manually (.jpl from GitHub releases)
|
|
79
|
+
|
|
80
|
+
1. Download `io.github.pmslava.harper.jpl` from the
|
|
81
|
+
[latest release](https://github.com/pmslava/joplin-plugin-harper/releases).
|
|
82
|
+
2. In Joplin desktop, go to **Tools → Options → Plugins**.
|
|
83
|
+
3. Under **Manage your plugins**, use the gear/⋮ menu → **Install from file**, and select the
|
|
84
|
+
downloaded `.jpl`.
|
|
85
|
+
4. Restart Joplin when prompted.
|
|
86
|
+
|
|
87
|
+
## Requirements and limits
|
|
88
|
+
|
|
89
|
+
- **Joplin desktop, version 3.1 or newer.** The plugin uses Joplin's CodeMirror 6 editor
|
|
90
|
+
integration, which requires 3.1+.
|
|
91
|
+
- **Markdown editor only.** Harper checks the Markdown (CodeMirror) editor. It does **not** work in
|
|
92
|
+
the Rich Text (WYSIWYG) editor, which offers no hook for this kind of decoration.
|
|
93
|
+
- **Desktop only.** There is no mobile build.
|
|
94
|
+
- **About 16 MB.** The plugin bundles Harper's WebAssembly engine so it can run offline, which makes
|
|
95
|
+
the `.jpl` roughly 16 MB — larger than a typical plugin, but that is the whole checker, downloaded
|
|
96
|
+
once.
|
|
97
|
+
- **Startup warm-up.** The first check after you open a note takes a second or two while the engine
|
|
98
|
+
loads and warms up. After that, re-checking a typical note is fast — on the order of ~50 ms for a
|
|
99
|
+
few kilobytes of text.
|
|
100
|
+
|
|
101
|
+
## Privacy
|
|
102
|
+
|
|
103
|
+
Harper runs locally and makes **no network calls**. Your note text is passed to the bundled
|
|
104
|
+
WebAssembly engine inside Joplin and nowhere else — nothing is uploaded, and there is no telemetry.
|
|
105
|
+
The external dictionary, if you use one, is a file on your own disk.
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm install
|
|
111
|
+
npm test # builds the plugin and runs the harness suite (incl. performance budgets)
|
|
112
|
+
npm run test:e2e # full end-to-end suite: launches a real Joplin desktop under Xvfb (Linux)
|
|
113
|
+
npm run dist # build only -> publish/io.github.pmslava.harper.jpl
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Architecture in one line:** the grammar checker (harper.js `LocalLinter`, WASM) runs in the
|
|
117
|
+
plugin main process, and a CodeMirror 6 content script draws the underlines and the suggestion card,
|
|
118
|
+
talking to it over Joplin's `postMessage` bridge.
|
|
119
|
+
|
|
120
|
+
For the full design, the WASM loading approach, the UI spec, and the research behind the plugin, see
|
|
121
|
+
[`docs/`](docs/) — in particular [`docs/SPEC.md`](docs/SPEC.md).
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
The plugin is licensed under the [MIT License](LICENSE).
|
|
126
|
+
|
|
127
|
+
It embeds and is powered by [Harper](https://github.com/automattic/harper) (via the
|
|
128
|
+
[`harper.js`](https://www.npmjs.com/package/harper.js) package), which is developed by **Automattic**
|
|
129
|
+
and licensed under the **Apache License 2.0**. All credit for the grammar-checking engine goes to the
|
|
130
|
+
Harper project — this plugin only integrates it into Joplin.
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "joplin-plugin-harper",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Fast, offline, private grammar and spelling checking for the Joplin desktop Markdown editor, powered by Harper.",
|
|
5
|
+
"author": "pmslava",
|
|
6
|
+
"homepage": "https://github.com/pmslava/joplin-plugin-harper#readme",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/pmslava/joplin-plugin-harper/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/pmslava/joplin-plugin-harper.git"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dist": "webpack --env joplin-plugin-config=buildMain && webpack --env joplin-plugin-config=buildExtraScripts && webpack --env joplin-plugin-config=createArchive",
|
|
19
|
+
"test": "npm run dist && node test/run.js",
|
|
20
|
+
"setup:e2e": "bash scripts/setup-e2e.sh",
|
|
21
|
+
"test:e2e": "npm run dist && npm run setup:e2e && xvfb-run -a --server-args=\"-screen 0 1920x1080x24\" playwright test",
|
|
22
|
+
"prepare": "npm run dist",
|
|
23
|
+
"update": "npm install -g generator-joplin && yo joplin --node-package-manager npm --update --force",
|
|
24
|
+
"updateVersion": "webpack --env joplin-plugin-config=updateVersion"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"joplin-plugin",
|
|
29
|
+
"joplin",
|
|
30
|
+
"harper",
|
|
31
|
+
"grammar",
|
|
32
|
+
"spelling",
|
|
33
|
+
"spell-check",
|
|
34
|
+
"linter",
|
|
35
|
+
"proofreading",
|
|
36
|
+
"writing"
|
|
37
|
+
],
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@codemirror/lint": "^6.8.0",
|
|
40
|
+
"@codemirror/state": "^6.4.0",
|
|
41
|
+
"@codemirror/view": "^6.26.0",
|
|
42
|
+
"@joplin/lib": "~2.9",
|
|
43
|
+
"@playwright/test": "^1.62.0",
|
|
44
|
+
"@types/node": "^18.7.13",
|
|
45
|
+
"chalk": "^4.1.0",
|
|
46
|
+
"copy-webpack-plugin": "^11.0.0",
|
|
47
|
+
"fs-extra": "^10.1.0",
|
|
48
|
+
"glob": "^8.0.3",
|
|
49
|
+
"playwright": "^1.62.0",
|
|
50
|
+
"tar": "^6.1.11",
|
|
51
|
+
"ts-loader": "^9.3.1",
|
|
52
|
+
"typescript": "^5.4.5",
|
|
53
|
+
"webpack": "^5.74.0",
|
|
54
|
+
"webpack-cli": "^4.10.0"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"harper.js": "2.7.0"
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"publish"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 1,
|
|
3
|
+
"id": "io.github.pmslava.harper",
|
|
4
|
+
"app_min_version": "3.1",
|
|
5
|
+
"platforms": [
|
|
6
|
+
"desktop"
|
|
7
|
+
],
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"name": "Harper",
|
|
10
|
+
"description": "Fast, offline, private grammar and spelling checking for the Joplin desktop Markdown editor, powered by Harper. Per-kind coloured underlines, a suggestion card with one-click fixes, add-to-dictionary, ignore and disable-rule, plus American, British, Australian and Canadian dialects.",
|
|
11
|
+
"author": "pmslava",
|
|
12
|
+
"homepage_url": "https://github.com/pmslava/joplin-plugin-harper",
|
|
13
|
+
"repository_url": "https://github.com/pmslava/joplin-plugin-harper",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"harper",
|
|
16
|
+
"grammar",
|
|
17
|
+
"spelling",
|
|
18
|
+
"spell-check",
|
|
19
|
+
"linter",
|
|
20
|
+
"proofreading",
|
|
21
|
+
"writing",
|
|
22
|
+
"editor"
|
|
23
|
+
],
|
|
24
|
+
"categories": [
|
|
25
|
+
"editor",
|
|
26
|
+
"productivity"
|
|
27
|
+
],
|
|
28
|
+
"screenshots": [
|
|
29
|
+
{
|
|
30
|
+
"src": "docs/screenshots/card-light.png",
|
|
31
|
+
"label": "The Harper suggestion card in the Markdown editor: the lint kind, the message with the flagged word, one-click suggestion pills, add-to-dictionary and dismiss, next to the coloured underlines in the text"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"src": "docs/screenshots/card-dark.png",
|
|
35
|
+
"label": "The same suggestion card in Joplin's dark theme, showing a spelling lint with correction pills and the add-to-dictionary action"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"src": "docs/screenshots/underlines-light.png",
|
|
39
|
+
"label": "Close-up of the per-kind coloured squiggly underlines: a red spelling underline and a green word-choice underline"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"_publish_hash": "sha256:99b54a0c8bd600ca46cc585fe9b030937e42e6f8b0366f0b9b5cd80bd1bea390",
|
|
43
|
+
"_publish_commit": "main:78fa2d759308fc08feef00f6895df5e4bf460bc7"
|
|
44
|
+
}
|