@nbtca/prompt 1.5.8 → 1.5.9
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/dist/app/views/docs.js +18 -4
- package/dist/features/docs-store.js +34 -0
- package/dist/features/docs.js +15 -1
- package/package.json +1 -1
package/dist/app/views/docs.js
CHANGED
|
@@ -7,7 +7,7 @@ import { pickIcon } from '../../core/icons.js';
|
|
|
7
7
|
import { glyph } from '../../core/theme.js';
|
|
8
8
|
import { fmt, getCurrentLanguage, t } from '../../i18n/index.js';
|
|
9
9
|
import { sanitizeTerminalLine, truncate } from '../../core/text.js';
|
|
10
|
-
import { localizeDocSections, fetchSections, fetchDocMetadata, fetchSectionMetadata, searchDocuments, getArchivedGroups, displayDocTitle, loadDocForReader, openDocsInBrowser, docsUrlFromPath, clearDocsCache, } from '../../features/docs.js';
|
|
10
|
+
import { localizeDocSections, fetchSections, peekSections, fetchDocMetadata, fetchSectionMetadata, searchDocuments, getArchivedGroups, displayDocTitle, loadDocForReader, openDocsInBrowser, docsUrlFromPath, clearDocsCache, } from '../../features/docs.js';
|
|
11
11
|
let state = { mode: 'loading' };
|
|
12
12
|
let sections = [];
|
|
13
13
|
let archivedGroups = new Map();
|
|
@@ -29,6 +29,9 @@ const DOC_HINT_WIDTH = 44;
|
|
|
29
29
|
function isLifecycleActive(ctx, generation) {
|
|
30
30
|
return generation === lifecycleGeneration && ctx.signal?.aborted !== true;
|
|
31
31
|
}
|
|
32
|
+
function sectionsSignature(value) {
|
|
33
|
+
return value.map((section) => `${section.key}:${String(section.files.length)}`).join('|');
|
|
34
|
+
}
|
|
32
35
|
function dedupeAdjacent(segments) {
|
|
33
36
|
return segments.filter((segment, index) => segment !== segments[index - 1]);
|
|
34
37
|
}
|
|
@@ -379,16 +382,27 @@ export const docsView = {
|
|
|
379
382
|
return;
|
|
380
383
|
}
|
|
381
384
|
const requestId = ++sectionsRequestId;
|
|
382
|
-
|
|
385
|
+
const cached = peekSections();
|
|
386
|
+
if (cached) {
|
|
387
|
+
sections = localizeDocSections(cached, t());
|
|
388
|
+
loadedLanguage = getCurrentLanguage();
|
|
389
|
+
goToSections();
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
state = { mode: 'loading' };
|
|
393
|
+
}
|
|
383
394
|
ctx.rerender();
|
|
384
395
|
try {
|
|
385
396
|
const nextSections = await fetchSections(ctx.signal);
|
|
386
397
|
if (!isLifecycleActive(ctx, generation) || requestId !== sectionsRequestId)
|
|
387
398
|
return;
|
|
388
|
-
|
|
399
|
+
const localized = localizeDocSections(nextSections, t());
|
|
400
|
+
const changed = sectionsSignature(localized) !== sectionsSignature(sections);
|
|
401
|
+
sections = localized;
|
|
389
402
|
loaded = true;
|
|
390
403
|
loadedLanguage = getCurrentLanguage();
|
|
391
|
-
|
|
404
|
+
if (!cached || changed || state.mode !== 'sections')
|
|
405
|
+
goToSections();
|
|
392
406
|
}
|
|
393
407
|
catch {
|
|
394
408
|
if (!isLifecycleActive(ctx, generation) || requestId !== sectionsRequestId)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { getStateDir, getWritableStateDir } from '../config/paths.js';
|
|
4
|
+
const INDEX_FILE = 'docs-index.json';
|
|
5
|
+
const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
6
|
+
function isDocItem(value) {
|
|
7
|
+
const item = value;
|
|
8
|
+
return (typeof item?.name === 'string' &&
|
|
9
|
+
typeof item.path === 'string' &&
|
|
10
|
+
(item.type === 'file' || item.type === 'dir'));
|
|
11
|
+
}
|
|
12
|
+
export function saveDocsIndex(docs, dir) {
|
|
13
|
+
try {
|
|
14
|
+
fs.writeFileSync(path.join(dir ?? getWritableStateDir(), INDEX_FILE), JSON.stringify(docs), {
|
|
15
|
+
encoding: 'utf8',
|
|
16
|
+
mode: 0o600,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
/* best effort */
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function loadDocsIndex(dir, maxAgeMs = MAX_AGE_MS) {
|
|
24
|
+
try {
|
|
25
|
+
const file = path.join(dir ?? getStateDir(), INDEX_FILE);
|
|
26
|
+
if (Date.now() - fs.statSync(file).mtimeMs > maxAgeMs)
|
|
27
|
+
return null;
|
|
28
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
29
|
+
return Array.isArray(parsed) && parsed.every(isDocItem) ? parsed : null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/features/docs.js
CHANGED
|
@@ -11,6 +11,7 @@ import { spawn, execFileSync } from 'child_process';
|
|
|
11
11
|
import { URLS } from '../config/data.js';
|
|
12
12
|
import { t, fmt, getCurrentLanguage } from '../i18n/index.js';
|
|
13
13
|
import { enterScreen, breadcrumb } from '../core/transitions.js';
|
|
14
|
+
import { loadDocsIndex, saveDocsIndex } from './docs-store.js';
|
|
14
15
|
import { sanitizeTerminalLine, sanitizeTerminalText, stripAnsi, truncate } from '../core/text.js';
|
|
15
16
|
import { clearDocsClients, runDocsClientOperation } from './docs-client.js';
|
|
16
17
|
import { launchBrowserUrl } from './links.js';
|
|
@@ -742,7 +743,20 @@ export async function fetchAllDocs(signal) {
|
|
|
742
743
|
return runDocsClientOperation(signal, (client) => client.listAll());
|
|
743
744
|
}
|
|
744
745
|
export async function fetchSections(signal) {
|
|
745
|
-
|
|
746
|
+
const docs = await fetchAllDocs(signal);
|
|
747
|
+
saveDocsIndex(docs);
|
|
748
|
+
return buildSections(docs);
|
|
749
|
+
}
|
|
750
|
+
export function peekSections() {
|
|
751
|
+
const docs = loadDocsIndex();
|
|
752
|
+
if (!docs)
|
|
753
|
+
return null;
|
|
754
|
+
try {
|
|
755
|
+
return buildSections(docs);
|
|
756
|
+
}
|
|
757
|
+
catch {
|
|
758
|
+
return null;
|
|
759
|
+
}
|
|
746
760
|
}
|
|
747
761
|
async function loadSections() {
|
|
748
762
|
const trans = t();
|