litura-app 0.3.7 → 0.4.2
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/CHANGELOG.md +10 -0
- package/index.js +15 -7
- package/package.json +5 -2
- package/public/app.js +1267 -201
- package/public/dictionary/LICENSE +347 -0
- package/public/dictionary/en.aff +205 -0
- package/public/dictionary/en.dic +49569 -0
- package/public/index.html +0 -1
- package/public/style.css +51 -34
- package/review.js +1 -1
- package/suggestions.js +16 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ number carries breaking changes.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.4.2 — 2026-09-13
|
|
9
|
+
|
|
10
|
+
- Clicking at the end of a paragraph now offers a Continue bubble, asking for the same continuation Cmd/Ctrl+Enter would. An explicit ask is allowed to open the next sentence and run longer than a background suggestion, instead of stopping at a finished thought.
|
|
11
|
+
- Fixed the field popovers flashing at their previous position before snapping to the trigger.
|
|
12
|
+
- Removed the unused standalone Rewrite button from the chat chip.
|
|
13
|
+
|
|
14
|
+
## 0.4.0 — 2026-09-13
|
|
15
|
+
|
|
16
|
+
- Added spell checking. Misspelled words are marked in the editor using a vendored en_US Hunspell dictionary, checked client-side alongside the existing style-tell markers.
|
|
17
|
+
|
|
8
18
|
## 0.3.7 — 2026-09-13
|
|
9
19
|
|
|
10
20
|
- Litura is now also a desktop app. A Tauri shell picks the writing folder, starts the same server on a free port, and shows it in its own window; it carries its own Node runtime, so nothing has to be installed first.
|
package/index.js
CHANGED
|
@@ -183,15 +183,18 @@ const MIME = {
|
|
|
183
183
|
'.svg': 'image/svg+xml',
|
|
184
184
|
'.woff2': 'font/woff2',
|
|
185
185
|
'.woff': 'font/woff',
|
|
186
|
+
'.aff': 'text/plain; charset=utf-8',
|
|
187
|
+
'.dic': 'text/plain; charset=utf-8',
|
|
186
188
|
};
|
|
187
189
|
|
|
188
190
|
function serveStatic(res, filePath) {
|
|
189
191
|
const ext = path.extname(filePath);
|
|
190
192
|
const mime = MIME[ext] || 'text/plain';
|
|
191
|
-
// Fonts never change under a given name; the
|
|
192
|
-
// update, and a tab holding a stale app.js
|
|
193
|
-
// classic post-upgrade bug. Revalidate it on
|
|
194
|
-
|
|
193
|
+
// Fonts and the spelling dictionary never change under a given name; the
|
|
194
|
+
// bundle changes with every update, and a tab holding a stale app.js
|
|
195
|
+
// against a new server is the classic post-upgrade bug. Revalidate it on
|
|
196
|
+
// each load.
|
|
197
|
+
const cache = ['.woff2', '.aff', '.dic'].includes(ext) ? 'public, max-age=31536000, immutable' : 'no-cache';
|
|
195
198
|
try {
|
|
196
199
|
const data = fs.readFileSync(filePath);
|
|
197
200
|
res.writeHead(200, { 'Content-Type': mime, 'Cache-Control': cache });
|
|
@@ -327,6 +330,10 @@ async function handleRequest(req, res) {
|
|
|
327
330
|
const fontFile = path.basename(url.pathname);
|
|
328
331
|
serveStatic(res, path.join(PUBLIC, 'fonts', fontFile));
|
|
329
332
|
}
|
|
333
|
+
else if (url.pathname.startsWith('/dictionary/')) {
|
|
334
|
+
const dictFile = path.basename(url.pathname);
|
|
335
|
+
serveStatic(res, path.join(PUBLIC, 'dictionary', dictFile));
|
|
336
|
+
}
|
|
330
337
|
else { res.writeHead(404); res.end('Not found'); }
|
|
331
338
|
return;
|
|
332
339
|
}
|
|
@@ -535,20 +542,21 @@ async function handleRequest(req, res) {
|
|
|
535
542
|
|
|
536
543
|
// POST /suggest — inline ghost-text suggestion (VS Code style)
|
|
537
544
|
//
|
|
538
|
-
// Request: { context, document, cursor }
|
|
545
|
+
// Request: { context, document, cursor, manual }
|
|
539
546
|
// cursor is the character offset where the ghost text will appear.
|
|
547
|
+
// manual marks a continuation the writer asked for, not one offered.
|
|
540
548
|
//
|
|
541
549
|
// Returns: { suggestion: string } — a short natural continuation
|
|
542
550
|
//
|
|
543
551
|
if (url.pathname === '/suggest') {
|
|
544
|
-
const { context, document: doc, cursor } = body;
|
|
552
|
+
const { context, document: doc, cursor, manual } = body;
|
|
545
553
|
|
|
546
554
|
const at = cursor ?? (doc ?? '').length;
|
|
547
555
|
const prefix = (doc ?? '').slice(0, at);
|
|
548
556
|
|
|
549
557
|
try {
|
|
550
558
|
const suggestion = await completeText({
|
|
551
|
-
...suggestionPrompts({ document: doc, cursor: at, context, style: readStyle() }),
|
|
559
|
+
...suggestionPrompts({ document: doc, cursor: at, context, style: readStyle(), manual: !!manual }),
|
|
552
560
|
selection: body.agent,
|
|
553
561
|
continuation: true,
|
|
554
562
|
signal: AbortSignal.any([signal, AbortSignal.timeout(30_000)]),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litura-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "A local AI-assisted editor for sharper, more human writing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"writing",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"desktop:prepare": "npm run build && npm run build:server && node scripts/fetch-node.mjs",
|
|
49
49
|
"desktop": "tauri dev",
|
|
50
50
|
"desktop:build": "tauri build",
|
|
51
|
+
"tauri": "tauri",
|
|
51
52
|
"smoke:desktop": "node scripts/smoke-desktop.mjs",
|
|
52
53
|
"check": "node --check index.js && node --check pi.js && node --check review-model.js && node --check deepcheck.js && npm run build && node selfcheck.js && node tests/suggestions.mjs && node safetycheck.js",
|
|
53
54
|
"test:browser": "node tests/browser-fixture.mjs",
|
|
@@ -63,6 +64,8 @@
|
|
|
63
64
|
"devDependencies": {
|
|
64
65
|
"@tauri-apps/cli": "^2.9.1",
|
|
65
66
|
"codemirror": "^6.0.1",
|
|
66
|
-
"
|
|
67
|
+
"dictionary-en": "^4.0.0",
|
|
68
|
+
"esbuild": "^0.25.0",
|
|
69
|
+
"nspell": "^2.1.5"
|
|
67
70
|
}
|
|
68
71
|
}
|