@gmickel/gno 0.35.0 → 0.36.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.
@@ -158,6 +158,53 @@ mark {
158
158
  outline: none;
159
159
  }
160
160
 
161
+ /* Command palette: own focus + selection treatment; do not inherit global rings */
162
+ [cmdk-input] {
163
+ outline: none !important;
164
+ box-shadow: none !important;
165
+ }
166
+
167
+ [cmdk-input]:focus,
168
+ [cmdk-input]:focus-visible,
169
+ [cmdk-root] [data-slot="command-input-wrapper"],
170
+ [cmdk-root] [data-slot="command-input-wrapper"]:focus-within {
171
+ outline: none !important;
172
+ box-shadow: none !important;
173
+ }
174
+
175
+ [cmdk-root] [data-slot="command-input-wrapper"] {
176
+ border-bottom: 1px solid hsl(var(--border) / 0.7);
177
+ background: hsl(var(--muted) / 0.2);
178
+ }
179
+
180
+ [cmdk-root] [data-slot="command-input-wrapper"]:focus-within {
181
+ border-bottom-color: hsl(var(--primary) / 0.45);
182
+ background: hsl(var(--card) / 0.96);
183
+ }
184
+
185
+ [cmdk-root] [cmdk-item] {
186
+ border: 1px solid transparent;
187
+ transition:
188
+ background-color 140ms ease,
189
+ border-color 140ms ease,
190
+ color 140ms ease,
191
+ box-shadow 140ms ease;
192
+ }
193
+
194
+ [cmdk-root] [cmdk-item][data-selected="true"] {
195
+ background: hsl(var(--primary) / 0.18);
196
+ border-color: hsl(var(--primary) / 0.38);
197
+ color: hsl(var(--foreground));
198
+ box-shadow:
199
+ inset 3px 0 0 hsl(var(--primary)),
200
+ inset 0 0 0 1px hsl(var(--primary) / 0.18);
201
+ }
202
+
203
+ [cmdk-root] [cmdk-item][data-selected="true"] svg,
204
+ [cmdk-root] [cmdk-item][data-selected="true"] [data-slot="command-shortcut"] {
205
+ color: hsl(var(--primary));
206
+ }
207
+
161
208
  /* Custom scrollbar */
162
209
  ::-webkit-scrollbar {
163
210
  width: 8px;
@@ -7,6 +7,7 @@ export interface BrowseDocument {
7
7
  collection: string;
8
8
  relPath: string;
9
9
  sourceExt: string;
10
+ updatedAt?: string;
10
11
  }
11
12
 
12
13
  export interface DocsResponse {
@@ -306,6 +306,10 @@ export default function DocView({ navigate }: PageProps) {
306
306
  []
307
307
  );
308
308
  const currentUri = currentTarget.uri;
309
+ const currentHash = useMemo(
310
+ () => window.location.hash.replace(/^#/u, ""),
311
+ []
312
+ );
309
313
  const highlightedLines = useMemo(() => {
310
314
  if (!currentTarget.lineStart) return [];
311
315
  const end = currentTarget.lineEnd ?? currentTarget.lineStart;
@@ -420,6 +424,19 @@ export default function DocView({ navigate }: PageProps) {
420
424
  }
421
425
  }, [currentTarget.lineStart, currentTarget.view]);
422
426
 
427
+ useEffect(() => {
428
+ if (!currentHash || showRawView || loading) {
429
+ return;
430
+ }
431
+
432
+ requestAnimationFrame(() => {
433
+ document
434
+ .getElementById(currentHash)
435
+ ?.scrollIntoView({ behavior: "smooth", block: "start" });
436
+ setActiveSectionAnchor(currentHash);
437
+ });
438
+ }, [currentHash, loading, showRawView]);
439
+
423
440
  const breadcrumbs = doc ? parseBreadcrumbs(doc.collection, doc.relPath) : [];
424
441
  const sections = useMemo(
425
442
  () => extractSections(parsedContent.body),
@@ -802,9 +819,8 @@ export default function DocView({ navigate }: PageProps) {
802
819
  setTimeout(() => setTagSaveSuccess(false), 2000);
803
820
  }, [doc, editedTags]);
804
821
 
805
- /** Slim left rail archival catalogue style, no Card chrome */
806
- const renderDocumentFactsRail = () => (
807
- <nav aria-label="Document facts" className="space-y-0">
822
+ const renderPropertiesPathRail = () => (
823
+ <nav aria-label="Document properties" className="space-y-0">
808
824
  {/* Section: Properties */}
809
825
  <div className="px-3 pb-3">
810
826
  <div className="mb-2.5 font-mono text-[10px] text-muted-foreground/50 uppercase tracking-[0.15em]">
@@ -883,11 +899,15 @@ export default function DocView({ navigate }: PageProps) {
883
899
  </button>
884
900
  </div>
885
901
  </div>
902
+ </nav>
903
+ );
886
904
 
887
- {/* Divider + Frontmatter/Tags */}
905
+ /** Left rail — metadata + outline */
906
+ const renderDocumentFactsRail = () => (
907
+ <nav aria-label="Document facts" className="space-y-0">
908
+ {/* Frontmatter + tags */}
888
909
  {(hasFrontmatter || showStandaloneTags) && (
889
910
  <>
890
- <div className="mx-3 border-border/20 border-t" />
891
911
  <div className="px-3 py-3">
892
912
  <div className="mb-2 flex items-center justify-between">
893
913
  <span className="font-mono text-[10px] text-muted-foreground/50 uppercase tracking-[0.15em]">
@@ -1372,10 +1392,12 @@ export default function DocView({ navigate }: PageProps) {
1372
1392
  </header>
1373
1393
 
1374
1394
  <div className="mx-auto flex max-w-[1800px] gap-5 px-6 xl:px-8">
1375
- {/* Left rail — document facts, only on ultra-wide */}
1395
+ {/* Left rail — metadata + outline */}
1376
1396
  {doc && (
1377
1397
  <aside className="hidden w-[200px] shrink-0 border-border/15 border-r pr-2 py-6 lg:block">
1378
- <div className="sticky top-24">{renderDocumentFactsRail()}</div>
1398
+ <div className="sticky top-24 max-h-[calc(100vh-7rem)] overflow-y-auto pr-1">
1399
+ {renderDocumentFactsRail()}
1400
+ </div>
1379
1401
  </aside>
1380
1402
  )}
1381
1403
 
@@ -1538,10 +1560,11 @@ export default function DocView({ navigate }: PageProps) {
1538
1560
  )}
1539
1561
  </main>
1540
1562
 
1541
- {/* Right rail — relationships */}
1563
+ {/* Right rail — properties/path + relationships */}
1542
1564
  {doc && (
1543
- <aside className="hidden w-[240px] min-w-0 shrink-0 overflow-hidden border-border/15 border-l pl-2 py-6 lg:block">
1544
- <div className="sticky top-24 min-w-0 space-y-1 overflow-hidden">
1565
+ <aside className="hidden w-[250px] min-w-0 shrink-0 overflow-hidden border-border/15 border-l pl-2 pt-2 pb-6 lg:block">
1566
+ <div className="sticky top-18 min-w-0 max-h-[calc(100vh-5.5rem)] space-y-1 overflow-y-auto overflow-x-hidden pr-1">
1567
+ {renderPropertiesPathRail()}
1545
1568
  <BacklinksPanel
1546
1569
  docId={doc.docid}
1547
1570
  onNavigate={(uri) =>
@@ -114,28 +114,28 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
114
114
  this.db.exec("PRAGMA foreign_keys = ON");
115
115
  this.db.exec("PRAGMA busy_timeout = 5000");
116
116
 
117
- // CI mode: trade durability for speed (no fsync, memory journal)
118
- // Safe for tests since we don't need crash recovery
117
+ // Keep WAL everywhere so readers can continue while a writer is active.
118
+ // CI still relaxes fsync/temp-store for speed, but MEMORY journal mode
119
+ // breaks the cross-process read/write behavior we rely on in CLI tests.
120
+ try {
121
+ const journalMode = this.db
122
+ .query<{ journal_mode: string }, []>("PRAGMA journal_mode")
123
+ .get()?.journal_mode;
124
+ if (journalMode?.toLowerCase() !== "wal") {
125
+ this.db.exec("PRAGMA journal_mode = WAL");
126
+ }
127
+ } catch (cause) {
128
+ if (!isDatabaseLockedError(cause)) {
129
+ throw cause;
130
+ }
131
+ // Another process may be switching journal mode or holding a write
132
+ // lock during startup. In that case we keep the connection usable and
133
+ // rely on the existing DB journal mode instead of failing open().
134
+ }
135
+
119
136
  if (process.env.CI) {
120
- this.db.exec("PRAGMA journal_mode = MEMORY");
121
137
  this.db.exec("PRAGMA synchronous = OFF");
122
138
  this.db.exec("PRAGMA temp_store = MEMORY");
123
- } else {
124
- try {
125
- const journalMode = this.db
126
- .query<{ journal_mode: string }, []>("PRAGMA journal_mode")
127
- .get()?.journal_mode;
128
- if (journalMode?.toLowerCase() !== "wal") {
129
- this.db.exec("PRAGMA journal_mode = WAL");
130
- }
131
- } catch (cause) {
132
- if (!isDatabaseLockedError(cause)) {
133
- throw cause;
134
- }
135
- // Another process may be switching journal mode or holding a write
136
- // lock during startup. In that case we keep the connection usable and
137
- // rely on the existing DB journal mode instead of failing open().
138
- }
139
139
  }
140
140
 
141
141
  // Load fts5-snowball extension if using snowball tokenizer