stilura 0.6.0 → 0.6.1
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/README.md +36 -151
- package/package.json +1 -1
- package/public/app.js +59 -59
package/README.md
CHANGED
|
@@ -2,112 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
# Stilura
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Local AI writing enhancer that writes with you. It highlights generic, AI-sounding phrases in your draft, names the pattern, and offers rewrites. Nothing changes until you pick one.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npx stilura
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|

|
|
12
|
+
## How it works
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
Stilura checks your draft against 20 named patterns in `style.md`: sales language, vague attribution, forced triples, filler openers, stacked qualifiers, and more. A second pass catches structural issues like buried points and broken paragraph promises.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
- **Options** — three rewrites for any finding. Hover to preview, click to apply.
|
|
17
|
+
- **Discuss** — chat about a passage or the whole draft.
|
|
18
|
+
- **Brief** (`/brief`) — tell it who reads this and what it should do. Rewrites aim at that reader; review stays unbiased.
|
|
19
|
+
- **Continuations** — short next-line suggestions appear when you pause. `Tab` to accept, `Escape` to dismiss.
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Click the count in the header for every remark in document order. `F8` and `Shift+F8` step between them. Disagree with one? `Keep as is` dismisses it for good.
|
|
20
|
-
|
|
21
|
-
## You decide every change
|
|
22
|
-
|
|
23
|
-
- `Options` on a finding gives three replace-in-place rewrites. Hover to preview, click to apply, `Try again` for three more.
|
|
24
|
-
- `Discuss` opens a compact chat about the passage or the whole draft.
|
|
25
|
-
- Short continuations appear below the line when you pause; `Tab` takes one, `Escape` drops it.
|
|
26
|
-
|
|
27
|
-
The model suggests. It never edits the document on its own.
|
|
28
|
-
|
|
29
|
-
## Rewrites that know the reader
|
|
30
|
-
|
|
31
|
-
Before polishing, `/brief` asks four questions, one at a time: who reads this, what it should make them do, what they already know, and how much ground it covers. The answers travel with every rewrite, chat reply, and `/idea` expansion. Review never sees them, so it judges the prose unbiased.
|
|
32
|
-
|
|
33
|
-
## Your text stays a file on your machine
|
|
34
|
-
|
|
35
|
-
Run Stilura in the folder that holds your writing. It edits `draft.md` there and reads `style.md` next to it if one exists. The sidebar opens any other Markdown or text file in the folder. Nothing leaves the machine except what a model request sends to the provider you chose.
|
|
36
|
-
|
|
37
|
-
## What it does not do
|
|
38
|
-
|
|
39
|
-
- It does not tell you whether a text was written by AI. It names writing patterns.
|
|
40
|
-
- It does not write the piece for you. Every passage it offers replaces one you already wrote.
|
|
41
|
-
- Review and rewrites need a model provider: an API key, ChatGPT Plus/Pro sign-in, or credentials Pi already stores. The local wording count works without one.
|
|
21
|
+
Click the count in the header to see all findings. `F8` / `Shift+F8` to step between them. `Keep as is` dismisses one for good.
|
|
42
22
|
|
|
43
23
|
## Run
|
|
44
24
|
|
|
45
|
-
### Command line
|
|
46
|
-
|
|
47
25
|
```bash
|
|
48
26
|
npx stilura
|
|
49
27
|
```
|
|
50
28
|
|
|
51
|
-
Needs Node
|
|
52
|
-
|
|
53
|
-
### Desktop
|
|
54
|
-
|
|
55
|
-
Download the build for your machine from [Releases](https://github.com/vadimchirkov/stilura/releases): `.dmg` on macOS, `.exe` on Windows, `.AppImage` or `.deb` on Linux. On first launch Stilura asks which folder holds your writing; `File → Open Folder…` picks a different one. It carries its own Node runtime and installs updates only when you say so.
|
|
56
|
-
|
|
57
|
-
The macOS builds are not yet signed with an Apple Developer ID, so the first launch is refused: open `System Settings → Privacy & Security`, find Stilura near the bottom, and press `Open Anyway`. Once is enough.
|
|
58
|
-
|
|
59
|
-
### Shortcuts
|
|
29
|
+
Needs Node 20+. Opens [http://127.0.0.1:3000](http://127.0.0.1:3000). Choose a provider and model under the gear button.
|
|
60
30
|
|
|
61
|
-
|
|
31
|
+
**Desktop:** download from [Releases](https://github.com/vadimchirkov/stilura/releases) (`.dmg` / `.exe` / `.AppImage` / `.deb`). On macOS, unsigned: `System Settings → Privacy & Security → Open Anyway` on first launch.
|
|
62
32
|
|
|
63
|
-
|
|
33
|
+
**Shortcuts:** `Cmd/Ctrl+K` — chat. `Cmd/Ctrl+Enter` — continuation. `Cmd/Ctrl+S` — download draft. `/` in composer — commands.
|
|
64
34
|
|
|
65
|
-
|
|
35
|
+
## Configuration
|
|
66
36
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Stilura opens one connection of its own, and only to ask about new versions: to the npm registry if you switch that on in settings, or to GitHub when the desktop app starts.
|
|
70
|
-
|
|
71
|
-
To work on Stilura itself:
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
git clone https://github.com/vadimchirkov/stilura.git
|
|
75
|
-
cd stilura
|
|
76
|
-
npm install
|
|
77
|
-
npm start
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Updating
|
|
81
|
-
|
|
82
|
-
The desktop app checks GitHub on launch and offers what it finds. Accepting downloads a bundle, verifies it against a signing key baked into the app, and restarts; declining changes nothing and the offer returns next launch. `Stilura → Check for Updates…` asks on demand. Because the app owns this, its settings have no npm update switch.
|
|
83
|
-
|
|
84
|
-
On the command line, running `npx stilura` is the update: for a bare package name npm re-resolves the registry on every run, so each start picks up the latest release. The exceptions are a global install, which shadows that check and needs `npm i -g stilura`, and a clone, which needs `git pull`.
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx stilura --check-update
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
prints the published version next to the running one.
|
|
91
|
-
|
|
92
|
-
Settings has an `Ask npm about new versions` switch, off by default. Turn it on and Stilura asks once a day and shows a badge in the header when a newer version is published; the badge links to the changelog rather than installing anything. Left off, Stilura opens no connection of its own.
|
|
93
|
-
|
|
94
|
-
Releases are cut by tag: `npm version <patch|minor|major>`, then `git push` and `git push --tags`. GitHub Actions runs the checks, verifies the tag matches `package.json`, and publishes.
|
|
95
|
-
|
|
96
|
-
An update leaves your draft, your `style.md`, and your model settings alone. Stored findings, chat history, and briefs are dropped only when a release changes their format.
|
|
97
|
-
|
|
98
|
-
## Configuring
|
|
99
|
-
|
|
100
|
-
Use the gear button to choose a provider, model, and reasoning level or to add an API key. Stilura also discovers credentials already stored by Pi and supported provider environment variables.
|
|
101
|
-
|
|
102
|
-
Continuations use a separate suggestion model (same dialog, no reasoning
|
|
103
|
-
control — the server always spends the least reasoning allowed). It defaults
|
|
104
|
-
to the cheapest authenticated model that writes well and switches reasoning
|
|
105
|
-
off; review, rewrites, chat, and `/idea` always use the default model above.
|
|
106
|
-
|
|
107
|
-
The same dialog offers ChatGPT Plus/Pro sign-in as an alternative to an API
|
|
108
|
-
key.
|
|
109
|
-
|
|
110
|
-
Optional environment defaults:
|
|
37
|
+
Use the gear button to choose a provider, model, and reasoning level. Stilura also finds credentials stored by Pi and provider environment variables. ChatGPT Plus/Pro sign-in works as an alternative to an API key.
|
|
111
38
|
|
|
112
39
|
```bash
|
|
113
40
|
PI_PROVIDER=anthropic
|
|
@@ -118,50 +45,33 @@ STYLE_FILE=./style.md
|
|
|
118
45
|
DRAFT_FILE=./draft.md
|
|
119
46
|
```
|
|
120
47
|
|
|
121
|
-
Edit `style.md` to describe the voice
|
|
48
|
+
Edit `style.md` to describe the voice and constraints to preserve. Changes apply without restarting.
|
|
49
|
+
|
|
50
|
+
## Data
|
|
51
|
+
|
|
52
|
+
The draft lives in `draft.md` in your folder. Findings, chat, brief, and model choice live in browser local storage. Nothing leaves the machine except model requests to the provider you chose.
|
|
122
53
|
|
|
123
|
-
|
|
54
|
+
The desktop app saves state under its application data directory, so changing ports does not reset it. Updates check GitHub on launch; accepting verifies the bundle against a signing key and restarts.
|
|
124
55
|
|
|
125
|
-
|
|
126
|
-
plain `draft.md`, and the server exposes the same operations the UI uses as
|
|
127
|
-
local HTTP endpoints. If an external edit lands while Stilura runs, it never
|
|
128
|
-
merges silently — it offers `Load disk` / `Keep mine` instead.
|
|
56
|
+
## Agent integration
|
|
129
57
|
|
|
130
|
-
A
|
|
131
|
-
package): voice rules distilled from `style.md`, the finding-code taxonomy,
|
|
132
|
-
and `curl` recipes for `GET/PUT /draft` and `POST /review /rewrite /suggest
|
|
133
|
-
/chat` on `http://127.0.0.1:3000` (or the next free port up to 3010).
|
|
134
|
-
Install it with:
|
|
58
|
+
The draft is a plain file, and the server exposes what the UI uses as HTTP endpoints. A skill for Claude Code / Codex ships in `skills/stilura/SKILL.md`:
|
|
135
59
|
|
|
136
60
|
```bash
|
|
137
|
-
cp -r skills/stilura ~/.
|
|
138
|
-
cp -r skills/stilura ~/.claude/skills/ # Claude Code
|
|
61
|
+
cp -r skills/stilura ~/.claude/skills/
|
|
139
62
|
```
|
|
140
63
|
|
|
141
|
-
then run the agent in the folder holding your draft while Stilura is running.
|
|
142
|
-
Writes go through revision-checked `PUT /draft` (a stale revision returns
|
|
143
|
-
`409` — re-read and retry once, never overwrite blindly).
|
|
144
|
-
`/draft` always addresses the launch file. To work on another workspace file,
|
|
145
|
-
use `?name=filename.md` on `/draft` and `/draft/history`; opening a file in one
|
|
146
|
-
tab does not change another tab's save target. `GET /file?name=filename.md`
|
|
147
|
-
also returns its revision. `PUT /file` requires that revision to replace a
|
|
148
|
-
file; without one it only creates a missing file.
|
|
149
|
-
|
|
150
64
|
### MCP server
|
|
151
65
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
same revision guard as `PUT /draft`. Start the server in the folder holding
|
|
159
|
-
your draft (or set `DRAFT_FILE`), since the draft resolves against the
|
|
160
|
-
server's working directory:
|
|
66
|
+
Seven stdio tools — `draft_read`, `draft_write`, `review`, `rewrite`, `suggest`, `chat`, `idea` — in `mcp-server.mjs`. Same prompts as the editor, same revision guard.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Claude Code
|
|
70
|
+
claude mcp add --scope user stilura -- node /path/to/stilura/mcp-server.mjs
|
|
71
|
+
```
|
|
161
72
|
|
|
162
73
|
```toml
|
|
163
|
-
# Codex: ~/.codex/config.toml
|
|
164
|
-
# review/rewrite can run past the 60 s default tool timeout — raise it.
|
|
74
|
+
# Codex: ~/.codex/config.toml
|
|
165
75
|
[mcp_servers.stilura]
|
|
166
76
|
command = "node"
|
|
167
77
|
args = ["/path/to/stilura/mcp-server.mjs"]
|
|
@@ -169,47 +79,22 @@ cwd = "/path/to/writing"
|
|
|
169
79
|
tool_timeout_sec = 180
|
|
170
80
|
```
|
|
171
81
|
|
|
172
|
-
```bash
|
|
173
|
-
# Claude Code (user scope; --scope project or .mcp.json for project scope)
|
|
174
|
-
claude mcp add --scope user stilura -- node /path/to/stilura/mcp-server.mjs
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Model credentials come from the same places as the editor: Pi's stored
|
|
178
|
-
credentials (`~/.pi/agent/auth.json`) and provider environment variables.
|
|
179
|
-
Per-call `agent` overrides accept `{ provider, model, thinkingLevel }`.
|
|
180
|
-
|
|
181
82
|
## Development
|
|
182
83
|
|
|
183
84
|
```bash
|
|
184
|
-
|
|
185
|
-
npm
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
The server uses Node's native HTTP module. The browser UI is vanilla JavaScript with CodeMirror 6 and is bundled with esbuild. Source changes belong in `src/app.js`; `public/app.js` is generated.
|
|
189
|
-
|
|
190
|
-
`npm run check:suggestions` tests insertion, cancellation and scheduling without model calls. `npm run eval:suggestions` makes real calls to the configured model using bilingual examples and records output and latency in `tmp/suggestion-evaluation.json`. See [the evaluation guide](docs/suggestion-evaluation.md) for review criteria and prompt/context experiments.
|
|
191
|
-
|
|
192
|
-
The desktop shell needs a Rust toolchain and [Tauri's system dependencies](https://tauri.app/start/prerequisites/):
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
npm run desktop
|
|
85
|
+
git clone https://github.com/vadimchirkov/stilura.git
|
|
86
|
+
cd stilura && npm install && npm start
|
|
196
87
|
```
|
|
197
88
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
Name the target when your Rust toolchain and the Tauri CLI disagree about the machine — an Intel `rustc` on Apple silicon, for instance, ends in a bundler looking for a sidecar nobody fetched:
|
|
89
|
+
Node native HTTP server. Vanilla JS frontend with CodeMirror 6, bundled by esbuild (`src/app.js` → `public/app.js`).
|
|
201
90
|
|
|
202
91
|
```bash
|
|
203
|
-
npm run
|
|
92
|
+
npm run build # bundle frontend
|
|
93
|
+
npm run check # lint + tests
|
|
94
|
+
npm run desktop # Tauri desktop shell (needs Rust + Tauri prerequisites)
|
|
204
95
|
```
|
|
205
96
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
Updates are signed with a minisign key that is not in this repository. CI reads it from the `TAURI_SIGNING_PRIVATE_KEY` and `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` secrets; the matching public key sits in `src-tauri/tauri.conf.json`, and an installed app refuses any bundle that key did not sign. Generate a new pair with `npx tauri signer generate` — and remember that replacing the public key strands every copy already installed.
|
|
209
|
-
|
|
210
|
-
The app icon in `src-tauri/icons/` is generated from `public/logo-tile.png` (black mark on the cream tile) with `npx tauri icon public/logo-tile.png`. The mark also ships as `public/logo-mark.png` (transparency, light surfaces) and `public/logo-mark-white.png` (dark surfaces).
|
|
211
|
-
|
|
212
|
-
See [SPEC.md](SPEC.md) for product behavior, API contracts, and implementation boundaries.
|
|
97
|
+
See [SPEC.md](SPEC.md) for API contracts and behavior details.
|
|
213
98
|
|
|
214
99
|
## License
|
|
215
100
|
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -29,18 +29,18 @@
|
|
|
29
29
|
mod
|
|
30
30
|
));
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// node_modules/is-buffer/index.js
|
|
33
33
|
var require_is_buffer = __commonJS({
|
|
34
|
-
"
|
|
34
|
+
"node_modules/is-buffer/index.js"(exports, module) {
|
|
35
35
|
module.exports = function isBuffer(obj) {
|
|
36
36
|
return obj != null && obj.constructor != null && typeof obj.constructor.isBuffer === "function" && obj.constructor.isBuffer(obj);
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
//
|
|
41
|
+
// node_modules/nspell/lib/util/rule-codes.js
|
|
42
42
|
var require_rule_codes = __commonJS({
|
|
43
|
-
"
|
|
43
|
+
"node_modules/nspell/lib/util/rule-codes.js"(exports, module) {
|
|
44
44
|
"use strict";
|
|
45
45
|
module.exports = ruleCodes;
|
|
46
46
|
var NO_CODES = [];
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
//
|
|
64
|
+
// node_modules/nspell/lib/util/affix.js
|
|
65
65
|
var require_affix = __commonJS({
|
|
66
|
-
"
|
|
66
|
+
"node_modules/nspell/lib/util/affix.js"(exports, module) {
|
|
67
67
|
"use strict";
|
|
68
68
|
var parse = require_rule_codes();
|
|
69
69
|
module.exports = affix;
|
|
@@ -261,9 +261,9 @@
|
|
|
261
261
|
}
|
|
262
262
|
});
|
|
263
263
|
|
|
264
|
-
//
|
|
264
|
+
// node_modules/nspell/lib/util/normalize.js
|
|
265
265
|
var require_normalize = __commonJS({
|
|
266
|
-
"
|
|
266
|
+
"node_modules/nspell/lib/util/normalize.js"(exports, module) {
|
|
267
267
|
"use strict";
|
|
268
268
|
module.exports = normalize;
|
|
269
269
|
function normalize(value, patterns) {
|
|
@@ -276,9 +276,9 @@
|
|
|
276
276
|
}
|
|
277
277
|
});
|
|
278
278
|
|
|
279
|
-
//
|
|
279
|
+
// node_modules/nspell/lib/util/flag.js
|
|
280
280
|
var require_flag = __commonJS({
|
|
281
|
-
"
|
|
281
|
+
"node_modules/nspell/lib/util/flag.js"(exports, module) {
|
|
282
282
|
"use strict";
|
|
283
283
|
module.exports = flag;
|
|
284
284
|
function flag(values, value, flags) {
|
|
@@ -287,9 +287,9 @@
|
|
|
287
287
|
}
|
|
288
288
|
});
|
|
289
289
|
|
|
290
|
-
//
|
|
290
|
+
// node_modules/nspell/lib/util/exact.js
|
|
291
291
|
var require_exact = __commonJS({
|
|
292
|
-
"
|
|
292
|
+
"node_modules/nspell/lib/util/exact.js"(exports, module) {
|
|
293
293
|
"use strict";
|
|
294
294
|
var flag = require_flag();
|
|
295
295
|
module.exports = exact;
|
|
@@ -310,9 +310,9 @@
|
|
|
310
310
|
}
|
|
311
311
|
});
|
|
312
312
|
|
|
313
|
-
//
|
|
313
|
+
// node_modules/nspell/lib/util/form.js
|
|
314
314
|
var require_form = __commonJS({
|
|
315
|
-
"
|
|
315
|
+
"node_modules/nspell/lib/util/form.js"(exports, module) {
|
|
316
316
|
"use strict";
|
|
317
317
|
var normalize = require_normalize();
|
|
318
318
|
var exact = require_exact();
|
|
@@ -357,9 +357,9 @@
|
|
|
357
357
|
}
|
|
358
358
|
});
|
|
359
359
|
|
|
360
|
-
//
|
|
360
|
+
// node_modules/nspell/lib/correct.js
|
|
361
361
|
var require_correct = __commonJS({
|
|
362
|
-
"
|
|
362
|
+
"node_modules/nspell/lib/correct.js"(exports, module) {
|
|
363
363
|
"use strict";
|
|
364
364
|
var form = require_form();
|
|
365
365
|
module.exports = correct;
|
|
@@ -369,9 +369,9 @@
|
|
|
369
369
|
}
|
|
370
370
|
});
|
|
371
371
|
|
|
372
|
-
//
|
|
372
|
+
// node_modules/nspell/lib/util/casing.js
|
|
373
373
|
var require_casing = __commonJS({
|
|
374
|
-
"
|
|
374
|
+
"node_modules/nspell/lib/util/casing.js"(exports, module) {
|
|
375
375
|
"use strict";
|
|
376
376
|
module.exports = casing;
|
|
377
377
|
function casing(value) {
|
|
@@ -395,9 +395,9 @@
|
|
|
395
395
|
}
|
|
396
396
|
});
|
|
397
397
|
|
|
398
|
-
//
|
|
398
|
+
// node_modules/nspell/lib/suggest.js
|
|
399
399
|
var require_suggest = __commonJS({
|
|
400
|
-
"
|
|
400
|
+
"node_modules/nspell/lib/suggest.js"(exports, module) {
|
|
401
401
|
"use strict";
|
|
402
402
|
var casing = require_casing();
|
|
403
403
|
var normalize = require_normalize();
|
|
@@ -655,9 +655,9 @@
|
|
|
655
655
|
}
|
|
656
656
|
});
|
|
657
657
|
|
|
658
|
-
//
|
|
658
|
+
// node_modules/nspell/lib/spell.js
|
|
659
659
|
var require_spell = __commonJS({
|
|
660
|
-
"
|
|
660
|
+
"node_modules/nspell/lib/spell.js"(exports, module) {
|
|
661
661
|
"use strict";
|
|
662
662
|
var form = require_form();
|
|
663
663
|
var flag = require_flag();
|
|
@@ -676,9 +676,9 @@
|
|
|
676
676
|
}
|
|
677
677
|
});
|
|
678
678
|
|
|
679
|
-
//
|
|
679
|
+
// node_modules/nspell/lib/util/apply.js
|
|
680
680
|
var require_apply = __commonJS({
|
|
681
|
-
"
|
|
681
|
+
"node_modules/nspell/lib/util/apply.js"(exports, module) {
|
|
682
682
|
"use strict";
|
|
683
683
|
module.exports = apply;
|
|
684
684
|
function apply(value, rule, rules, words) {
|
|
@@ -711,9 +711,9 @@
|
|
|
711
711
|
}
|
|
712
712
|
});
|
|
713
713
|
|
|
714
|
-
//
|
|
714
|
+
// node_modules/nspell/lib/util/add.js
|
|
715
715
|
var require_add = __commonJS({
|
|
716
|
-
"
|
|
716
|
+
"node_modules/nspell/lib/util/add.js"(exports, module) {
|
|
717
717
|
"use strict";
|
|
718
718
|
var apply = require_apply();
|
|
719
719
|
module.exports = add2;
|
|
@@ -782,9 +782,9 @@
|
|
|
782
782
|
}
|
|
783
783
|
});
|
|
784
784
|
|
|
785
|
-
//
|
|
785
|
+
// node_modules/nspell/lib/add.js
|
|
786
786
|
var require_add2 = __commonJS({
|
|
787
|
-
"
|
|
787
|
+
"node_modules/nspell/lib/add.js"(exports, module) {
|
|
788
788
|
"use strict";
|
|
789
789
|
var push = require_add();
|
|
790
790
|
module.exports = add2;
|
|
@@ -797,9 +797,9 @@
|
|
|
797
797
|
}
|
|
798
798
|
});
|
|
799
799
|
|
|
800
|
-
//
|
|
800
|
+
// node_modules/nspell/lib/remove.js
|
|
801
801
|
var require_remove = __commonJS({
|
|
802
|
-
"
|
|
802
|
+
"node_modules/nspell/lib/remove.js"(exports, module) {
|
|
803
803
|
"use strict";
|
|
804
804
|
module.exports = remove2;
|
|
805
805
|
function remove2(value) {
|
|
@@ -810,9 +810,9 @@
|
|
|
810
810
|
}
|
|
811
811
|
});
|
|
812
812
|
|
|
813
|
-
//
|
|
813
|
+
// node_modules/nspell/lib/word-characters.js
|
|
814
814
|
var require_word_characters = __commonJS({
|
|
815
|
-
"
|
|
815
|
+
"node_modules/nspell/lib/word-characters.js"(exports, module) {
|
|
816
816
|
"use strict";
|
|
817
817
|
module.exports = wordCharacters;
|
|
818
818
|
function wordCharacters() {
|
|
@@ -821,9 +821,9 @@
|
|
|
821
821
|
}
|
|
822
822
|
});
|
|
823
823
|
|
|
824
|
-
//
|
|
824
|
+
// node_modules/nspell/lib/util/dictionary.js
|
|
825
825
|
var require_dictionary = __commonJS({
|
|
826
|
-
"
|
|
826
|
+
"node_modules/nspell/lib/util/dictionary.js"(exports, module) {
|
|
827
827
|
"use strict";
|
|
828
828
|
var parseCodes = require_rule_codes();
|
|
829
829
|
var add2 = require_add();
|
|
@@ -875,9 +875,9 @@
|
|
|
875
875
|
}
|
|
876
876
|
});
|
|
877
877
|
|
|
878
|
-
//
|
|
878
|
+
// node_modules/nspell/lib/dictionary.js
|
|
879
879
|
var require_dictionary2 = __commonJS({
|
|
880
|
-
"
|
|
880
|
+
"node_modules/nspell/lib/dictionary.js"(exports, module) {
|
|
881
881
|
"use strict";
|
|
882
882
|
var parse = require_dictionary();
|
|
883
883
|
module.exports = add2;
|
|
@@ -904,9 +904,9 @@
|
|
|
904
904
|
}
|
|
905
905
|
});
|
|
906
906
|
|
|
907
|
-
//
|
|
907
|
+
// node_modules/nspell/lib/personal.js
|
|
908
908
|
var require_personal = __commonJS({
|
|
909
|
-
"
|
|
909
|
+
"node_modules/nspell/lib/personal.js"(exports, module) {
|
|
910
910
|
"use strict";
|
|
911
911
|
module.exports = add2;
|
|
912
912
|
function add2(buf) {
|
|
@@ -940,9 +940,9 @@
|
|
|
940
940
|
}
|
|
941
941
|
});
|
|
942
942
|
|
|
943
|
-
//
|
|
943
|
+
// node_modules/nspell/lib/index.js
|
|
944
944
|
var require_lib = __commonJS({
|
|
945
|
-
"
|
|
945
|
+
"node_modules/nspell/lib/index.js"(exports, module) {
|
|
946
946
|
"use strict";
|
|
947
947
|
var buffer = require_is_buffer();
|
|
948
948
|
var affix = require_affix();
|
|
@@ -999,7 +999,7 @@
|
|
|
999
999
|
}
|
|
1000
1000
|
});
|
|
1001
1001
|
|
|
1002
|
-
//
|
|
1002
|
+
// node_modules/@marijn/find-cluster-break/src/index.js
|
|
1003
1003
|
var rangeFrom = [];
|
|
1004
1004
|
var rangeTo = [];
|
|
1005
1005
|
(() => {
|
|
@@ -1073,7 +1073,7 @@
|
|
|
1073
1073
|
return code2 < 65536 ? 1 : 2;
|
|
1074
1074
|
}
|
|
1075
1075
|
|
|
1076
|
-
//
|
|
1076
|
+
// node_modules/@codemirror/state/dist/index.js
|
|
1077
1077
|
var Text = class _Text {
|
|
1078
1078
|
/**
|
|
1079
1079
|
Get the line description around the given position.
|
|
@@ -4426,7 +4426,7 @@
|
|
|
4426
4426
|
return strict === true ? -1 : string2.length;
|
|
4427
4427
|
}
|
|
4428
4428
|
|
|
4429
|
-
//
|
|
4429
|
+
// node_modules/style-mod/src/style-mod.js
|
|
4430
4430
|
var C = "\u037C";
|
|
4431
4431
|
var COUNT = typeof Symbol == "undefined" ? "__" + C : Symbol.for(C);
|
|
4432
4432
|
var SET = typeof Symbol == "undefined" ? "__styleSet" + Math.floor(Math.random() * 1e8) : /* @__PURE__ */ Symbol("styleSet");
|
|
@@ -4557,7 +4557,7 @@
|
|
|
4557
4557
|
}
|
|
4558
4558
|
};
|
|
4559
4559
|
|
|
4560
|
-
//
|
|
4560
|
+
// node_modules/w3c-keyname/index.js
|
|
4561
4561
|
var base = {
|
|
4562
4562
|
8: "Backspace",
|
|
4563
4563
|
9: "Tab",
|
|
@@ -4663,7 +4663,7 @@
|
|
|
4663
4663
|
return name2;
|
|
4664
4664
|
}
|
|
4665
4665
|
|
|
4666
|
-
//
|
|
4666
|
+
// node_modules/crelt/index.js
|
|
4667
4667
|
function crelt() {
|
|
4668
4668
|
var elt = arguments[0];
|
|
4669
4669
|
if (typeof elt == "string") elt = document.createElement(elt);
|
|
@@ -4692,7 +4692,7 @@
|
|
|
4692
4692
|
}
|
|
4693
4693
|
}
|
|
4694
4694
|
|
|
4695
|
-
//
|
|
4695
|
+
// node_modules/@codemirror/view/dist/index.js
|
|
4696
4696
|
var nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
4697
4697
|
var doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
4698
4698
|
var ie_edge = /* @__PURE__ */ /Edge\/(\d+)/.exec(nav.userAgent);
|
|
@@ -13367,7 +13367,7 @@
|
|
|
13367
13367
|
GutterMarker.prototype.startSide = GutterMarker.prototype.endSide = -1;
|
|
13368
13368
|
GutterMarker.prototype.point = true;
|
|
13369
13369
|
|
|
13370
|
-
//
|
|
13370
|
+
// node_modules/@lezer/common/dist/index.js
|
|
13371
13371
|
var DefaultBufferLength = 1024;
|
|
13372
13372
|
var nextPropID = 0;
|
|
13373
13373
|
var Range2 = class {
|
|
@@ -14955,7 +14955,7 @@
|
|
|
14955
14955
|
};
|
|
14956
14956
|
var stoppedInner = new NodeProp({ perNode: true });
|
|
14957
14957
|
|
|
14958
|
-
//
|
|
14958
|
+
// node_modules/@lezer/highlight/dist/index.js
|
|
14959
14959
|
var nextTagID = 0;
|
|
14960
14960
|
var Tag = class _Tag {
|
|
14961
14961
|
/**
|
|
@@ -15579,7 +15579,7 @@
|
|
|
15579
15579
|
{ tag: tags.punctuation, class: "tok-punctuation" }
|
|
15580
15580
|
]);
|
|
15581
15581
|
|
|
15582
|
-
//
|
|
15582
|
+
// node_modules/@codemirror/language/dist/index.js
|
|
15583
15583
|
var _a;
|
|
15584
15584
|
var languageDataProp = /* @__PURE__ */ new NodeProp();
|
|
15585
15585
|
var sublanguageProp = /* @__PURE__ */ new NodeProp();
|
|
@@ -16601,7 +16601,7 @@
|
|
|
16601
16601
|
auto: /* @__PURE__ */ Decoration.mark({ class: "cm-iso", inclusive: true, attributes: { dir: "auto" }, bidiIsolate: null })
|
|
16602
16602
|
};
|
|
16603
16603
|
|
|
16604
|
-
//
|
|
16604
|
+
// node_modules/@codemirror/commands/dist/index.js
|
|
16605
16605
|
var toggleComment = (target) => {
|
|
16606
16606
|
let { state } = target, line = state.doc.lineAt(state.selection.main.from), config = getConfig(target.state, line.from);
|
|
16607
16607
|
return config.line ? toggleLineComment(target) : config.block ? toggleBlockCommentByLine(target) : false;
|
|
@@ -17681,7 +17681,7 @@
|
|
|
17681
17681
|
{ key: "Ctrl-m", mac: "Shift-Alt-m", run: toggleTabFocusMode }
|
|
17682
17682
|
].concat(standardKeymap);
|
|
17683
17683
|
|
|
17684
|
-
//
|
|
17684
|
+
// review.js
|
|
17685
17685
|
var TELL_WORDS_STRONG = [
|
|
17686
17686
|
"delve",
|
|
17687
17687
|
"delves",
|
|
@@ -17858,7 +17858,7 @@
|
|
|
17858
17858
|
return located.sort((a, b) => a.from - b.from);
|
|
17859
17859
|
}
|
|
17860
17860
|
|
|
17861
|
-
//
|
|
17861
|
+
// markdown.js
|
|
17862
17862
|
var ESCAPES = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
|
|
17863
17863
|
var escapeHtml = (text) => text.replace(/[&<>"']/g, (char) => ESCAPES[char]);
|
|
17864
17864
|
var MARKS = ["\0", "\uE000", "\uE001", "\uE002"];
|
|
@@ -17890,7 +17890,7 @@
|
|
|
17890
17890
|
return text.split(/\n{2,}/).map((part) => block(part.trim(), isPlaceholder)).join("").replace(placeholder2, (_, index) => stash[Number(index)]);
|
|
17891
17891
|
}
|
|
17892
17892
|
|
|
17893
|
-
//
|
|
17893
|
+
// editing.js
|
|
17894
17894
|
function replacementTarget(document2, target) {
|
|
17895
17895
|
if (!target || document2 !== target.document || !Number.isInteger(target.from) || target.from < 0 || target.to < target.from) return false;
|
|
17896
17896
|
if (target.to === target.from) return target.text === "";
|
|
@@ -17997,7 +17997,7 @@
|
|
|
17997
17997
|
return { text: joined ? out.join("\n") : input, joined };
|
|
17998
17998
|
}
|
|
17999
17999
|
|
|
18000
|
-
//
|
|
18000
|
+
// chat-edits.js
|
|
18001
18001
|
var EDITS_OPEN = "<litura-edits>";
|
|
18002
18002
|
var BARE_EDITS_RE = /(?:^|\n)[ \t]*(?:Proposed edits:\s*)?(?:```(?:json)?\s*)?(?=\[\s*\{\s*"(?:label|quote|replacement)")/;
|
|
18003
18003
|
function envelopeStart(raw) {
|
|
@@ -18055,7 +18055,7 @@
|
|
|
18055
18055
|
return ["pending", "applied", "kept"].includes(edit.state) && Number.isInteger(edit.from) && Number.isInteger(edit.to) && edit.from >= 0 && edit.to >= edit.from && edit.to <= document2.length && document2.slice(edit.from, edit.to) === expected;
|
|
18056
18056
|
}
|
|
18057
18057
|
|
|
18058
|
-
//
|
|
18058
|
+
// spellcheck.js
|
|
18059
18059
|
var import_nspell = __toESM(require_lib(), 1);
|
|
18060
18060
|
var cached = null;
|
|
18061
18061
|
function loadSpellDictionary() {
|
|
@@ -18113,7 +18113,7 @@
|
|
|
18113
18113
|
return out;
|
|
18114
18114
|
}
|
|
18115
18115
|
|
|
18116
|
-
//
|
|
18116
|
+
// node_modules/@codemirror/search/dist/index.js
|
|
18117
18117
|
var basicNormalize = typeof String.prototype.normalize == "function" ? (x) => x.normalize("NFKD") : (x) => x;
|
|
18118
18118
|
var SearchCursor = class {
|
|
18119
18119
|
/**
|
|
@@ -19100,7 +19100,7 @@
|
|
|
19100
19100
|
baseTheme2
|
|
19101
19101
|
];
|
|
19102
19102
|
|
|
19103
|
-
//
|
|
19103
|
+
// src/icons.js
|
|
19104
19104
|
var PATHS = {
|
|
19105
19105
|
"sidebar": '<path d="M4 6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" /> <path d="M9 4l0 16" />',
|
|
19106
19106
|
"file-text": '<path d="M14 3v4a1 1 0 0 0 1 1h4" /> <path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2" /> <path d="M9 9l1 0" /> <path d="M9 13l6 0" /> <path d="M9 17l6 0" />',
|
|
@@ -19132,7 +19132,7 @@
|
|
|
19132
19132
|
}
|
|
19133
19133
|
}
|
|
19134
19134
|
|
|
19135
|
-
//
|
|
19135
|
+
// src/storage.js
|
|
19136
19136
|
async function openStorage({ desktop, browser: browser2 = window.localStorage, request = fetch, onError }) {
|
|
19137
19137
|
if (!desktop) return browser2;
|
|
19138
19138
|
const response = await request("/api/desktop/storage");
|
|
@@ -19189,7 +19189,7 @@
|
|
|
19189
19189
|
};
|
|
19190
19190
|
}
|
|
19191
19191
|
|
|
19192
|
-
//
|
|
19192
|
+
// src/app.js
|
|
19193
19193
|
async function main() {
|
|
19194
19194
|
const desktop = new URLSearchParams(location.search).get("shell") === "desktop";
|
|
19195
19195
|
const localStorage = await openStorage({
|