@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.
- package/package.json +1 -1
- package/src/serve/public/app.tsx +7 -3
- package/src/serve/public/components/BrowseDetailPane.tsx +18 -1
- package/src/serve/public/components/QuickSwitcher.tsx +226 -88
- package/src/serve/public/components/ui/command.tsx +19 -9
- package/src/serve/public/components/ui/dialog.tsx +1 -1
- package/src/serve/public/globals.built.css +2 -2
- package/src/serve/public/globals.css +47 -0
- package/src/serve/public/lib/browse.ts +1 -0
- package/src/serve/public/pages/DocView.tsx +33 -10
- package/src/store/sqlite/adapter.ts +19 -19
|
@@ -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;
|
|
@@ -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
|
-
|
|
806
|
-
|
|
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
|
-
|
|
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 —
|
|
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
|
|
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-[
|
|
1544
|
-
<div className="sticky top-
|
|
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
|
-
//
|
|
118
|
-
//
|
|
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
|