@gmickel/gno 1.36.0 → 1.37.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.
@@ -1,9 +1,14 @@
1
- import { useCallback, useEffect, useMemo, useState } from "react";
1
+ import {
2
+ lazy,
3
+ Suspense,
4
+ useCallback,
5
+ useEffect,
6
+ useMemo,
7
+ useState,
8
+ } from "react";
2
9
  import { createRoot } from "react-dom/client";
3
10
 
4
11
  import { HelpButton } from "./components/HelpButton";
5
- import { QuickSwitcher } from "./components/QuickSwitcher";
6
- import { ShortcutHelpModal } from "./components/ShortcutHelpModal";
7
12
  import { WorkspaceTabs } from "./components/WorkspaceTabs";
8
13
  import { CaptureModalProvider, useCaptureModal } from "./hooks/useCaptureModal";
9
14
  import { useKeyboardShortcuts } from "./hooks/useKeyboardShortcuts";
@@ -21,17 +26,28 @@ import {
21
26
  updateActiveTabBrowseState,
22
27
  type WorkspaceState,
23
28
  } from "./lib/workspace-tabs";
24
- import Ask from "./pages/Ask";
25
- import Browse from "./pages/Browse";
26
29
  import ClipperPairing from "./pages/ClipperPairing";
27
- import Collections from "./pages/Collections";
28
- import Connectors from "./pages/Connectors";
29
30
  import Dashboard from "./pages/Dashboard";
30
- import DocumentEditor from "./pages/DocumentEditor";
31
- import DocView from "./pages/DocView";
32
- import GraphView from "./pages/GraphView";
33
- import Search from "./pages/Search";
34
- import TraceHistory from "./pages/TraceHistory";
31
+
32
+ const QuickSwitcher = lazy(() =>
33
+ import("./components/QuickSwitcher").then((module) => ({
34
+ default: module.QuickSwitcher,
35
+ }))
36
+ );
37
+ const ShortcutHelpModal = lazy(() =>
38
+ import("./components/ShortcutHelpModal").then((module) => ({
39
+ default: module.ShortcutHelpModal,
40
+ }))
41
+ );
42
+ const Search = lazy(() => import("./pages/Search"));
43
+ const Browse = lazy(() => import("./pages/Browse"));
44
+ const DocView = lazy(() => import("./pages/DocView"));
45
+ const DocumentEditor = lazy(() => import("./pages/DocumentEditor"));
46
+ const Collections = lazy(() => import("./pages/Collections"));
47
+ const Connectors = lazy(() => import("./pages/Connectors"));
48
+ const Ask = lazy(() => import("./pages/Ask"));
49
+ const GraphView = lazy(() => import("./pages/GraphView"));
50
+ const TraceHistory = lazy(() => import("./pages/TraceHistory"));
35
51
 
36
52
  type Route =
37
53
  | "/"
@@ -155,7 +171,9 @@ function AppContent({
155
171
  tabs={workspace.tabs}
156
172
  />
157
173
  <div className="flex-1">
158
- <Page key={pageKey} location={location} navigate={navigate} />
174
+ <Suspense fallback={null}>
175
+ <Page key={pageKey} location={location} navigate={navigate} />
176
+ </Suspense>
159
177
  </div>
160
178
  <footer className="border-t border-border/30 bg-background/60 py-6 text-center text-sm backdrop-blur-sm">
161
179
  <div className="ornament mx-auto mb-4 max-w-[8rem] text-muted-foreground/20">
@@ -217,17 +235,19 @@ function AppContent({
217
235
  </footer>
218
236
  </div>
219
237
  <HelpButton onClick={() => setShortcutHelpOpen(true)} />
220
- <QuickSwitcher
221
- location={location}
222
- navigate={(to) => navigate(to)}
223
- onCreateNote={openCapture}
224
- onOpenChange={setQuickSwitcherOpen}
225
- open={quickSwitcherOpen}
226
- />
227
- <ShortcutHelpModal
228
- onOpenChange={setShortcutHelpOpen}
229
- open={shortcutHelpOpen}
230
- />
238
+ <Suspense fallback={null}>
239
+ <QuickSwitcher
240
+ location={location}
241
+ navigate={(to) => navigate(to)}
242
+ onCreateNote={openCapture}
243
+ onOpenChange={setQuickSwitcherOpen}
244
+ open={quickSwitcherOpen}
245
+ />
246
+ <ShortcutHelpModal
247
+ onOpenChange={setShortcutHelpOpen}
248
+ open={shortcutHelpOpen}
249
+ />
250
+ </Suspense>
231
251
  </>
232
252
  );
233
253
  }
@@ -33,14 +33,19 @@ const CodeBlockContext = createContext<CodeBlockContextType>({
33
33
  code: "",
34
34
  });
35
35
 
36
- const highlighterPromise = createHighlighter({
37
- engine: createJavaScriptRegexEngine(),
38
- langs: ["text"],
39
- themes: ["one-light", "one-dark-pro"],
40
- });
36
+ let highlighterPromise: ReturnType<typeof createHighlighter> | null = null;
37
+
38
+ function getHighlighterRuntime(): ReturnType<typeof createHighlighter> {
39
+ highlighterPromise ??= createHighlighter({
40
+ engine: createJavaScriptRegexEngine(),
41
+ langs: ["text"],
42
+ themes: ["one-light", "one-dark-pro"],
43
+ });
44
+ return highlighterPromise;
45
+ }
41
46
 
42
47
  async function getHighlighter(language: BundledLanguage | "text") {
43
- const highlighter = await highlighterPromise;
48
+ const highlighter = await getHighlighterRuntime();
44
49
  if (!highlighter.getLoadedLanguages().includes(language)) {
45
50
  await highlighter.loadLanguage(language);
46
51
  }
@@ -2,7 +2,6 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
- <base href="/" />
6
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
6
  <meta name="referrer" content="no-referrer" />
8
7
  <title>GNO - Local Knowledge Index</title>
@@ -1,4 +1,6 @@
1
- import { bundledLanguages, type BundledLanguage } from "shiki";
1
+ import type { BundledLanguage } from "shiki";
2
+
3
+ import { BUNDLED_LANGUAGE_IDS } from "./shiki-language-ids";
2
4
 
3
5
  export type CodeLanguage = BundledLanguage | "text";
4
6
 
@@ -41,7 +43,7 @@ export function resolveCodeLanguage(
41
43
  return "text";
42
44
  }
43
45
 
44
- if (aliased in bundledLanguages) {
46
+ if (BUNDLED_LANGUAGE_IDS.has(aliased)) {
45
47
  return aliased as BundledLanguage;
46
48
  }
47
49
 
@@ -0,0 +1,335 @@
1
+ /** Shiki bundled language ids only. Do not import grammar modules. */
2
+ export const BUNDLED_LANGUAGE_IDS: ReadonlySet<string> = new Set([
3
+ "1c",
4
+ "1c-query",
5
+ "abap",
6
+ "actionscript-3",
7
+ "ada",
8
+ "adoc",
9
+ "angular-html",
10
+ "angular-ts",
11
+ "apache",
12
+ "apex",
13
+ "apl",
14
+ "applescript",
15
+ "ara",
16
+ "asciidoc",
17
+ "asm",
18
+ "astro",
19
+ "awk",
20
+ "ballerina",
21
+ "bash",
22
+ "bat",
23
+ "batch",
24
+ "be",
25
+ "beancount",
26
+ "berry",
27
+ "bibtex",
28
+ "bicep",
29
+ "bird",
30
+ "bird2",
31
+ "blade",
32
+ "bsl",
33
+ "c",
34
+ "c#",
35
+ "c++",
36
+ "c3",
37
+ "cadence",
38
+ "cairo",
39
+ "cdc",
40
+ "cjs",
41
+ "clarity",
42
+ "clj",
43
+ "clojure",
44
+ "closure-templates",
45
+ "cmake",
46
+ "cmd",
47
+ "cobol",
48
+ "codeowners",
49
+ "codeql",
50
+ "coffee",
51
+ "coffeescript",
52
+ "common-lisp",
53
+ "console",
54
+ "coq",
55
+ "cpp",
56
+ "cql",
57
+ "crystal",
58
+ "cs",
59
+ "csharp",
60
+ "css",
61
+ "csv",
62
+ "cts",
63
+ "cue",
64
+ "cypher",
65
+ "d",
66
+ "dart",
67
+ "dax",
68
+ "desktop",
69
+ "diff",
70
+ "docker",
71
+ "dockerfile",
72
+ "dotenv",
73
+ "dream-maker",
74
+ "edge",
75
+ "elisp",
76
+ "elixir",
77
+ "elm",
78
+ "emacs-lisp",
79
+ "erb",
80
+ "erl",
81
+ "erlang",
82
+ "f",
83
+ "f#",
84
+ "f03",
85
+ "f08",
86
+ "f18",
87
+ "f77",
88
+ "f90",
89
+ "f95",
90
+ "fennel",
91
+ "fish",
92
+ "fluent",
93
+ "for",
94
+ "fortran-fixed-form",
95
+ "fortran-free-form",
96
+ "fs",
97
+ "fsharp",
98
+ "fsl",
99
+ "ftl",
100
+ "gd",
101
+ "gdresource",
102
+ "gdscript",
103
+ "gdshader",
104
+ "genie",
105
+ "gherkin",
106
+ "git-commit",
107
+ "git-rebase",
108
+ "gjs",
109
+ "gleam",
110
+ "glimmer-js",
111
+ "glimmer-ts",
112
+ "glsl",
113
+ "gn",
114
+ "gnuplot",
115
+ "go",
116
+ "gql",
117
+ "graphql",
118
+ "groovy",
119
+ "gts",
120
+ "hack",
121
+ "haml",
122
+ "handlebars",
123
+ "haskell",
124
+ "haxe",
125
+ "hbs",
126
+ "hcl",
127
+ "hjson",
128
+ "hlsl",
129
+ "hs",
130
+ "html",
131
+ "html-derivative",
132
+ "http",
133
+ "hurl",
134
+ "hxml",
135
+ "hy",
136
+ "imba",
137
+ "ini",
138
+ "jade",
139
+ "java",
140
+ "javascript",
141
+ "jinja",
142
+ "jison",
143
+ "jl",
144
+ "js",
145
+ "json",
146
+ "json5",
147
+ "jsonc",
148
+ "jsonl",
149
+ "jsonnet",
150
+ "jssm",
151
+ "jsx",
152
+ "julia",
153
+ "just",
154
+ "kdl",
155
+ "kotlin",
156
+ "kql",
157
+ "kt",
158
+ "kts",
159
+ "kusto",
160
+ "latex",
161
+ "lean",
162
+ "lean4",
163
+ "less",
164
+ "liquid",
165
+ "lisp",
166
+ "lit",
167
+ "llvm",
168
+ "log",
169
+ "logo",
170
+ "lua",
171
+ "luau",
172
+ "make",
173
+ "makefile",
174
+ "markdown",
175
+ "marko",
176
+ "matlab",
177
+ "mbt",
178
+ "mbti",
179
+ "md",
180
+ "mdc",
181
+ "mdx",
182
+ "mediawiki",
183
+ "mermaid",
184
+ "mips",
185
+ "mipsasm",
186
+ "mjs",
187
+ "mmd",
188
+ "mojo",
189
+ "moonbit",
190
+ "move",
191
+ "mts",
192
+ "nar",
193
+ "narrat",
194
+ "nextflow",
195
+ "nextflow-groovy",
196
+ "nf",
197
+ "nginx",
198
+ "nim",
199
+ "nix",
200
+ "nu",
201
+ "nushell",
202
+ "objc",
203
+ "objective-c",
204
+ "objective-cpp",
205
+ "ocaml",
206
+ "odin",
207
+ "openscad",
208
+ "pascal",
209
+ "perl",
210
+ "perl6",
211
+ "php",
212
+ "pkl",
213
+ "plsql",
214
+ "po",
215
+ "polar",
216
+ "postcss",
217
+ "pot",
218
+ "potx",
219
+ "powerquery",
220
+ "powershell",
221
+ "prisma",
222
+ "prolog",
223
+ "properties",
224
+ "proto",
225
+ "protobuf",
226
+ "ps",
227
+ "ps1",
228
+ "pug",
229
+ "puppet",
230
+ "purescript",
231
+ "py",
232
+ "python",
233
+ "ql",
234
+ "qml",
235
+ "qmldir",
236
+ "qss",
237
+ "r",
238
+ "racket",
239
+ "raku",
240
+ "razor",
241
+ "rb",
242
+ "reg",
243
+ "regex",
244
+ "regexp",
245
+ "rel",
246
+ "riscv",
247
+ "ron",
248
+ "rosmsg",
249
+ "rs",
250
+ "rst",
251
+ "ruby",
252
+ "rust",
253
+ "sas",
254
+ "sass",
255
+ "scad",
256
+ "scala",
257
+ "scheme",
258
+ "scss",
259
+ "sdbl",
260
+ "sh",
261
+ "shader",
262
+ "shaderlab",
263
+ "shell",
264
+ "shellscript",
265
+ "shellsession",
266
+ "smalltalk",
267
+ "solidity",
268
+ "soy",
269
+ "sparql",
270
+ "spl",
271
+ "splunk",
272
+ "sql",
273
+ "ssh-config",
274
+ "stata",
275
+ "styl",
276
+ "stylus",
277
+ "surql",
278
+ "surrealql",
279
+ "svelte",
280
+ "swift",
281
+ "system-verilog",
282
+ "systemd",
283
+ "talon",
284
+ "talonscript",
285
+ "tasl",
286
+ "tcl",
287
+ "templ",
288
+ "terraform",
289
+ "tex",
290
+ "tf",
291
+ "tfvars",
292
+ "toml",
293
+ "tres",
294
+ "ts",
295
+ "ts-tags",
296
+ "tscn",
297
+ "tsp",
298
+ "tsv",
299
+ "tsx",
300
+ "turtle",
301
+ "twig",
302
+ "typ",
303
+ "typescript",
304
+ "typespec",
305
+ "typst",
306
+ "v",
307
+ "vala",
308
+ "vb",
309
+ "verilog",
310
+ "vhdl",
311
+ "vim",
312
+ "viml",
313
+ "vimscript",
314
+ "vue",
315
+ "vue-html",
316
+ "vue-vine",
317
+ "vy",
318
+ "vyper",
319
+ "wasm",
320
+ "wenyan",
321
+ "wgsl",
322
+ "wiki",
323
+ "wikitext",
324
+ "wit",
325
+ "wl",
326
+ "wolfram",
327
+ "xml",
328
+ "xsl",
329
+ "yaml",
330
+ "yml",
331
+ "zenscript",
332
+ "zig",
333
+ "zsh",
334
+ "文言",
335
+ ]);
@@ -16,18 +16,12 @@ import {
16
16
  Search,
17
17
  StarIcon,
18
18
  } from "lucide-react";
19
- import { useCallback, useEffect, useState } from "react";
19
+ import { lazy, Suspense, useCallback, useEffect, useState } from "react";
20
20
 
21
21
  import type { AppStatusResponse, HealthActionKind } from "../../status-model";
22
22
 
23
- import { AddCollectionDialog } from "../components/AddCollectionDialog";
24
- import { AIModelSelector } from "../components/AIModelSelector";
25
- import { BootstrapStatus } from "../components/BootstrapStatus";
26
23
  import { CaptureButton } from "../components/CaptureButton";
27
- import { FirstRunWizard } from "../components/FirstRunWizard";
28
24
  import { GnoLogo } from "../components/GnoLogo";
29
- import { HealthCenter } from "../components/HealthCenter";
30
- import { IndexingProgress } from "../components/IndexingProgress";
31
25
  import { Button } from "../components/ui/button";
32
26
  import {
33
27
  Card,
@@ -93,6 +87,37 @@ interface ModelDownloadStatus {
93
87
  startedAt: number | null;
94
88
  }
95
89
 
90
+ const AddCollectionDialog = lazy(() =>
91
+ import("../components/AddCollectionDialog").then((module) => ({
92
+ default: module.AddCollectionDialog,
93
+ }))
94
+ );
95
+ const AIModelSelector = lazy(() =>
96
+ import("../components/AIModelSelector").then((module) => ({
97
+ default: module.AIModelSelector,
98
+ }))
99
+ );
100
+ const BootstrapStatus = lazy(() =>
101
+ import("../components/BootstrapStatus").then((module) => ({
102
+ default: module.BootstrapStatus,
103
+ }))
104
+ );
105
+ const FirstRunWizard = lazy(() =>
106
+ import("../components/FirstRunWizard").then((module) => ({
107
+ default: module.FirstRunWizard,
108
+ }))
109
+ );
110
+ const HealthCenter = lazy(() =>
111
+ import("../components/HealthCenter").then((module) => ({
112
+ default: module.HealthCenter,
113
+ }))
114
+ );
115
+ const IndexingProgress = lazy(() =>
116
+ import("../components/IndexingProgress").then((module) => ({
117
+ default: module.IndexingProgress,
118
+ }))
119
+ );
120
+
96
121
  interface PageProps {
97
122
  navigate: (to: string | number) => void;
98
123
  }
@@ -397,7 +422,9 @@ export default function Dashboard({ navigate }: PageProps) {
397
422
  </div>
398
423
 
399
424
  <div className="flex flex-wrap items-center gap-3 md:justify-end">
400
- <AIModelSelector appStatus={status} showLabel={false} />
425
+ <Suspense fallback={null}>
426
+ <AIModelSelector appStatus={status} showLabel={false} />
427
+ </Suspense>
401
428
  <Button
402
429
  disabled={syncing}
403
430
  onClick={() => void handleSync()}
@@ -416,14 +443,16 @@ export default function Dashboard({ navigate }: PageProps) {
416
443
 
417
444
  {syncJobId && (!status || status.onboarding.ready) && (
418
445
  <div className="mt-4 rounded-lg border border-border/50 bg-background/50 p-4">
419
- <IndexingProgress
420
- jobId={syncJobId}
421
- onComplete={handleSyncComplete}
422
- onError={() => {
423
- setSyncing(false);
424
- setSyncJobId(null);
425
- }}
426
- />
446
+ <Suspense fallback={null}>
447
+ <IndexingProgress
448
+ jobId={syncJobId}
449
+ onComplete={handleSyncComplete}
450
+ onError={() => {
451
+ setSyncing(false);
452
+ setSyncJobId(null);
453
+ }}
454
+ />
455
+ </Suspense>
427
456
  </div>
428
457
  )}
429
458
  </div>
@@ -432,17 +461,19 @@ export default function Dashboard({ navigate }: PageProps) {
432
461
  <main className="mx-auto max-w-6xl p-8">
433
462
  {status && !status.onboarding.ready && (
434
463
  <section className="mb-10">
435
- <FirstRunWizard
436
- onboarding={status.onboarding}
437
- onAddCollection={handleOpenAddCollection}
438
- onDownloadModels={() => void handleDownloadModels()}
439
- onEmbed={() => void handleEmbedNow()}
440
- onSync={() => void handleSync()}
441
- onSyncComplete={handleSyncComplete}
442
- embedding={busyAction === "embed"}
443
- syncJobId={syncJobId}
444
- syncing={syncing}
445
- />
464
+ <Suspense fallback={null}>
465
+ <FirstRunWizard
466
+ embedding={busyAction === "embed"}
467
+ onAddCollection={handleOpenAddCollection}
468
+ onDownloadModels={() => void handleDownloadModels()}
469
+ onEmbed={() => void handleEmbedNow()}
470
+ onboarding={status.onboarding}
471
+ onSync={() => void handleSync()}
472
+ onSyncComplete={handleSyncComplete}
473
+ syncJobId={syncJobId}
474
+ syncing={syncing}
475
+ />
476
+ </Suspense>
446
477
  </section>
447
478
  )}
448
479
 
@@ -519,22 +550,26 @@ export default function Dashboard({ navigate }: PageProps) {
519
550
 
520
551
  {status && (
521
552
  <div className="mb-10">
522
- <HealthCenter
523
- busyAction={busyAction}
524
- health={status.health}
525
- onAction={handleHealthAction}
526
- resident={status.resident}
527
- />
553
+ <Suspense fallback={null}>
554
+ <HealthCenter
555
+ busyAction={busyAction}
556
+ health={status.health}
557
+ onAction={handleHealthAction}
558
+ resident={status.resident}
559
+ />
560
+ </Suspense>
528
561
  </div>
529
562
  )}
530
563
 
531
564
  {status && (
532
565
  <div className="mb-10">
533
- <BootstrapStatus
534
- activation={status.activation}
535
- bootstrap={status.bootstrap}
536
- onDownloadModels={() => void handleDownloadModels()}
537
- />
566
+ <Suspense fallback={null}>
567
+ <BootstrapStatus
568
+ activation={status.activation}
569
+ bootstrap={status.bootstrap}
570
+ onDownloadModels={() => void handleDownloadModels()}
571
+ />
572
+ </Suspense>
538
573
  </div>
539
574
  )}
540
575
 
@@ -791,12 +826,14 @@ export default function Dashboard({ navigate }: PageProps) {
791
826
  </main>
792
827
 
793
828
  <CaptureButton onClick={() => openCapture()} />
794
- <AddCollectionDialog
795
- initialPath={initialCollectionPath}
796
- onOpenChange={setAddDialogOpen}
797
- onSuccess={() => void loadStatus()}
798
- open={addDialogOpen}
799
- />
829
+ <Suspense fallback={null}>
830
+ <AddCollectionDialog
831
+ initialPath={initialCollectionPath}
832
+ onOpenChange={setAddDialogOpen}
833
+ onSuccess={() => void loadStatus()}
834
+ open={addDialogOpen}
835
+ />
836
+ </Suspense>
800
837
  </div>
801
838
  );
802
839
  }
@@ -43,10 +43,6 @@ import {
43
43
  import { Loader } from "../components/ai-elements/loader";
44
44
  import { BacklinksPanel } from "../components/BacklinksPanel";
45
45
  import { MarkdownPreview } from "../components/editor";
46
- import {
47
- FrontmatterDisplay,
48
- parseFrontmatter,
49
- } from "../components/FrontmatterDisplay";
50
46
  import {
51
47
  OutgoingLinksPanel,
52
48
  type OutgoingLink,
@@ -99,6 +95,10 @@ import {
99
95
  type SectionLinkNoticeKind,
100
96
  } from "../lib/section-links";
101
97
  import { subscribeWorkspaceActionRequest } from "../lib/workspace-events";
98
+ import {
99
+ FrontmatterDisplay,
100
+ parseFrontmatter,
101
+ } from "./doc-frontmatter-display";
102
102
 
103
103
  /** Lazy so pdfjs is never pulled for non-PDF documents. */
104
104
  const PdfViewer = lazy(() => import("./doc-pdf-viewer"));