kyp-mem 0.2.2 → 0.3.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/README.md +53 -54
- package/bin/cli.mjs +56 -1
- package/kyp_mem/__init__.py +1 -1
- package/kyp_mem/cli.py +101 -0
- package/kyp_mem/hooks.py +126 -0
- package/kyp_mem/server.py +36 -9
- package/kyp_mem/static/index.html +953 -310
- package/kyp_mem/ui.py +46 -2
- package/package.json +2 -2
- package/pyproject.toml +2 -2
|
@@ -3,42 +3,47 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>KYP-MEM
|
|
6
|
+
<title>KYP-MEM</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
9
9
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
10
10
|
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
|
11
11
|
<style>
|
|
12
12
|
:root {
|
|
13
|
-
--bg-void: #
|
|
14
|
-
--bg-primary: #
|
|
15
|
-
--bg-secondary: #
|
|
16
|
-
--bg-tertiary: #
|
|
17
|
-
--bg-hover: #
|
|
18
|
-
--bg-active: #
|
|
19
|
-
--bg-card: #
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
--neon-
|
|
23
|
-
--neon-
|
|
24
|
-
--neon-
|
|
25
|
-
--neon-
|
|
26
|
-
--neon-
|
|
27
|
-
--neon-
|
|
28
|
-
--neon-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
--glow-
|
|
32
|
-
--glow-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
--text-
|
|
36
|
-
--text-
|
|
37
|
-
--
|
|
38
|
-
--border
|
|
13
|
+
--bg-void: #08080f;
|
|
14
|
+
--bg-primary: #0c0c16;
|
|
15
|
+
--bg-secondary: #0e0e1a;
|
|
16
|
+
--bg-tertiary: #070710;
|
|
17
|
+
--bg-hover: #121224;
|
|
18
|
+
--bg-active: #181836;
|
|
19
|
+
--bg-card: #101020;
|
|
20
|
+
--bg-surface: #0a0a15;
|
|
21
|
+
|
|
22
|
+
--neon-cyan: #00e8df;
|
|
23
|
+
--neon-green: #34d399;
|
|
24
|
+
--neon-magenta: #e879f9;
|
|
25
|
+
--neon-purple: #a78bfa;
|
|
26
|
+
--neon-orange: #fb923c;
|
|
27
|
+
--neon-yellow: #fbbf24;
|
|
28
|
+
--neon-blue: #60a5fa;
|
|
29
|
+
--neon-red: #f87171;
|
|
30
|
+
|
|
31
|
+
--glow-cyan: 0 0 8px #00e8df30;
|
|
32
|
+
--glow-green: 0 0 8px #34d39930;
|
|
33
|
+
--glow-magenta: 0 0 8px #e879f930;
|
|
34
|
+
|
|
35
|
+
--text-primary: #d4d4e8;
|
|
36
|
+
--text-secondary: #7a7a9a;
|
|
37
|
+
--text-muted: #3e3e5c;
|
|
38
|
+
--border: #16162a;
|
|
39
|
+
--border-subtle: #121225;
|
|
39
40
|
|
|
40
41
|
--font: 'Inter', -apple-system, sans-serif;
|
|
41
42
|
--font-mono: 'JetBrains Mono', monospace;
|
|
43
|
+
|
|
44
|
+
--radius-sm: 4px;
|
|
45
|
+
--radius: 6px;
|
|
46
|
+
--radius-lg: 10px;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
@@ -49,91 +54,61 @@ body {
|
|
|
49
54
|
color: var(--text-primary);
|
|
50
55
|
height: 100vh;
|
|
51
56
|
overflow: hidden;
|
|
57
|
+
-webkit-font-smoothing: antialiased;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
/* Subtle grid background */
|
|
55
60
|
body::before {
|
|
56
61
|
content: '';
|
|
57
62
|
position: fixed;
|
|
58
63
|
inset: 0;
|
|
59
64
|
background-image:
|
|
60
|
-
linear-gradient(rgba(0,
|
|
61
|
-
linear-gradient(90deg, rgba(0,
|
|
62
|
-
background-size:
|
|
65
|
+
linear-gradient(rgba(0,232,223,0.015) 1px, transparent 1px),
|
|
66
|
+
linear-gradient(90deg, rgba(0,232,223,0.015) 1px, transparent 1px);
|
|
67
|
+
background-size: 48px 48px;
|
|
63
68
|
pointer-events: none;
|
|
64
69
|
z-index: 0;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
.layout {
|
|
68
73
|
display: grid;
|
|
69
|
-
grid-template-columns: var(--sidebar-w,
|
|
70
|
-
grid-template-rows:
|
|
74
|
+
grid-template-columns: var(--sidebar-w, 256px) 1px 1fr 1px var(--right-w, 272px);
|
|
75
|
+
grid-template-rows: 48px 1fr;
|
|
71
76
|
height: 100vh;
|
|
72
77
|
position: relative;
|
|
73
78
|
z-index: 1;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
.layout.no-right-panel {
|
|
77
|
-
grid-template-columns: var(--sidebar-w,
|
|
82
|
+
grid-template-columns: var(--sidebar-w, 256px) 1px 1fr;
|
|
78
83
|
}
|
|
79
84
|
.layout.no-right-panel .right-panel,
|
|
80
85
|
.layout.no-right-panel #resize-right { display: none; }
|
|
81
86
|
|
|
82
87
|
/* ============ RESIZE HANDLES ============ */
|
|
83
88
|
.resize-handle {
|
|
84
|
-
background:
|
|
89
|
+
background: var(--border-subtle);
|
|
85
90
|
cursor: col-resize;
|
|
86
91
|
position: relative;
|
|
87
92
|
z-index: 10;
|
|
88
|
-
transition: background 0.
|
|
93
|
+
transition: background 0.3s;
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
.resize-handle::before {
|
|
92
97
|
content: '';
|
|
93
98
|
position: absolute;
|
|
94
|
-
inset: 0 -
|
|
99
|
+
inset: 0 -4px;
|
|
95
100
|
z-index: 1;
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
.resize-handle::after {
|
|
99
|
-
content: '';
|
|
100
|
-
position: absolute;
|
|
101
|
-
top: 50%;
|
|
102
|
-
left: 50%;
|
|
103
|
-
transform: translate(-50%, -50%);
|
|
104
|
-
width: 3px;
|
|
105
|
-
height: 32px;
|
|
106
|
-
border-radius: 2px;
|
|
107
|
-
background: var(--text-muted);
|
|
108
|
-
opacity: 0;
|
|
109
|
-
transition: opacity 0.2s, background 0.2s, box-shadow 0.2s;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.resize-handle:hover::after,
|
|
113
|
-
.resize-handle.dragging::after {
|
|
114
|
-
opacity: 1;
|
|
115
|
-
background: var(--neon-cyan);
|
|
116
|
-
box-shadow: 0 0 8px rgba(0, 255, 245, 0.4);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
103
|
.resize-handle:hover,
|
|
120
104
|
.resize-handle.dragging {
|
|
121
|
-
background:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
body.resizing {
|
|
125
|
-
cursor: col-resize !important;
|
|
126
|
-
user-select: none !important;
|
|
105
|
+
background: var(--neon-cyan);
|
|
106
|
+
box-shadow: 0 0 12px rgba(0,232,223,0.2);
|
|
127
107
|
}
|
|
128
108
|
|
|
129
|
-
body.resizing
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
body.resizing .resize-handle {
|
|
135
|
-
pointer-events: auto !important;
|
|
136
|
-
}
|
|
109
|
+
body.resizing { cursor: col-resize !important; user-select: none !important; }
|
|
110
|
+
body.resizing * { cursor: col-resize !important; pointer-events: none !important; }
|
|
111
|
+
body.resizing .resize-handle { pointer-events: auto !important; }
|
|
137
112
|
|
|
138
113
|
/* ============ HEADER ============ */
|
|
139
114
|
.header {
|
|
@@ -150,21 +125,20 @@ body.resizing .resize-handle {
|
|
|
150
125
|
.header::after {
|
|
151
126
|
content: '';
|
|
152
127
|
position: absolute;
|
|
153
|
-
bottom:
|
|
128
|
+
bottom: 0;
|
|
154
129
|
left: 0;
|
|
155
130
|
right: 0;
|
|
156
131
|
height: 1px;
|
|
157
|
-
background: linear-gradient(90deg, transparent, var(--neon-cyan), var(--neon-magenta),
|
|
158
|
-
opacity: 0.
|
|
132
|
+
background: linear-gradient(90deg, transparent, var(--neon-cyan), var(--neon-magenta), transparent);
|
|
133
|
+
opacity: 0.2;
|
|
159
134
|
}
|
|
160
135
|
|
|
161
136
|
.logo {
|
|
162
137
|
font-family: var(--font-mono);
|
|
163
138
|
font-weight: 700;
|
|
164
|
-
font-size:
|
|
139
|
+
font-size: 13px;
|
|
165
140
|
color: var(--neon-cyan);
|
|
166
|
-
|
|
167
|
-
letter-spacing: 1px;
|
|
141
|
+
letter-spacing: 2px;
|
|
168
142
|
flex-shrink: 0;
|
|
169
143
|
}
|
|
170
144
|
|
|
@@ -172,66 +146,65 @@ body.resizing .resize-handle {
|
|
|
172
146
|
font-size: 10px;
|
|
173
147
|
font-weight: 400;
|
|
174
148
|
color: var(--text-muted);
|
|
175
|
-
text-shadow: none;
|
|
176
149
|
letter-spacing: 0.5px;
|
|
177
|
-
margin-left:
|
|
150
|
+
margin-left: 10px;
|
|
178
151
|
}
|
|
179
152
|
|
|
180
153
|
.breadcrumb {
|
|
181
154
|
font-family: var(--font-mono);
|
|
182
|
-
font-size:
|
|
155
|
+
font-size: 11px;
|
|
183
156
|
color: var(--text-secondary);
|
|
184
157
|
overflow: hidden;
|
|
185
158
|
text-overflow: ellipsis;
|
|
186
159
|
white-space: nowrap;
|
|
187
160
|
}
|
|
188
161
|
|
|
189
|
-
.breadcrumb .sep { color: var(--text-muted); margin: 0
|
|
190
|
-
.breadcrumb .current { color: var(--neon-cyan); font-weight:
|
|
162
|
+
.breadcrumb .sep { color: var(--text-muted); margin: 0 5px; }
|
|
163
|
+
.breadcrumb .current { color: var(--neon-cyan); font-weight: 500; }
|
|
191
164
|
|
|
192
165
|
.header-actions {
|
|
193
166
|
margin-left: auto;
|
|
194
167
|
display: flex;
|
|
195
168
|
align-items: center;
|
|
196
|
-
gap:
|
|
169
|
+
gap: 8px;
|
|
197
170
|
}
|
|
198
171
|
|
|
199
|
-
.
|
|
200
|
-
background:
|
|
172
|
+
.header-btn {
|
|
173
|
+
background: transparent;
|
|
201
174
|
border: 1px solid var(--border);
|
|
202
|
-
color: var(--text-
|
|
175
|
+
color: var(--text-muted);
|
|
203
176
|
font-family: var(--font-mono);
|
|
204
|
-
font-size:
|
|
177
|
+
font-size: 10px;
|
|
205
178
|
padding: 5px 10px;
|
|
206
|
-
border-radius:
|
|
179
|
+
border-radius: var(--radius);
|
|
207
180
|
cursor: pointer;
|
|
208
181
|
transition: all 0.2s;
|
|
209
182
|
display: flex;
|
|
210
183
|
align-items: center;
|
|
211
184
|
gap: 5px;
|
|
185
|
+
letter-spacing: 0.5px;
|
|
212
186
|
}
|
|
213
187
|
|
|
214
|
-
.
|
|
215
|
-
border-color: var(--
|
|
216
|
-
color: var(--
|
|
188
|
+
.header-btn:hover {
|
|
189
|
+
border-color: var(--text-muted);
|
|
190
|
+
color: var(--text-secondary);
|
|
217
191
|
}
|
|
218
192
|
|
|
219
|
-
.
|
|
220
|
-
border-color:
|
|
193
|
+
.header-btn.active {
|
|
194
|
+
border-color: rgba(0,232,223,0.3);
|
|
221
195
|
color: var(--neon-cyan);
|
|
222
|
-
background: rgba(0,
|
|
223
|
-
box-shadow: 0 0 8px rgba(0, 255, 245, 0.15);
|
|
196
|
+
background: rgba(0,232,223,0.05);
|
|
224
197
|
}
|
|
225
198
|
|
|
226
|
-
.
|
|
227
|
-
width:
|
|
228
|
-
height:
|
|
199
|
+
.header-btn .dot {
|
|
200
|
+
width: 5px;
|
|
201
|
+
height: 5px;
|
|
229
202
|
border-radius: 50%;
|
|
230
203
|
background: var(--text-muted);
|
|
231
204
|
transition: all 0.2s;
|
|
232
205
|
}
|
|
233
206
|
|
|
234
|
-
.
|
|
207
|
+
.header-btn.active .dot {
|
|
235
208
|
background: var(--neon-green);
|
|
236
209
|
box-shadow: 0 0 6px var(--neon-green);
|
|
237
210
|
}
|
|
@@ -241,33 +214,33 @@ body.resizing .resize-handle {
|
|
|
241
214
|
}
|
|
242
215
|
|
|
243
216
|
.search-box input {
|
|
244
|
-
background: var(--bg-
|
|
217
|
+
background: var(--bg-surface);
|
|
245
218
|
border: 1px solid var(--border);
|
|
246
219
|
color: var(--text-primary);
|
|
247
220
|
font-family: var(--font-mono);
|
|
248
221
|
padding: 6px 12px 6px 28px;
|
|
249
|
-
border-radius:
|
|
250
|
-
font-size:
|
|
251
|
-
width:
|
|
222
|
+
border-radius: var(--radius);
|
|
223
|
+
font-size: 11px;
|
|
224
|
+
width: 200px;
|
|
252
225
|
outline: none;
|
|
253
|
-
transition: all 0.
|
|
226
|
+
transition: all 0.25s;
|
|
254
227
|
}
|
|
255
228
|
|
|
256
229
|
.search-box input::placeholder { color: var(--text-muted); }
|
|
257
230
|
|
|
258
231
|
.search-box input:focus {
|
|
259
|
-
border-color:
|
|
260
|
-
box-shadow: 0 0
|
|
261
|
-
width:
|
|
232
|
+
border-color: rgba(0,232,223,0.3);
|
|
233
|
+
box-shadow: 0 0 16px rgba(0,232,223,0.08);
|
|
234
|
+
width: 260px;
|
|
262
235
|
}
|
|
263
236
|
|
|
264
237
|
.search-box .search-icon {
|
|
265
238
|
position: absolute;
|
|
266
|
-
left:
|
|
239
|
+
left: 10px;
|
|
267
240
|
top: 50%;
|
|
268
241
|
transform: translateY(-50%);
|
|
269
242
|
color: var(--text-muted);
|
|
270
|
-
font-size:
|
|
243
|
+
font-size: 11px;
|
|
271
244
|
}
|
|
272
245
|
|
|
273
246
|
.search-box .search-hint {
|
|
@@ -276,36 +249,36 @@ body.resizing .resize-handle {
|
|
|
276
249
|
top: 50%;
|
|
277
250
|
transform: translateY(-50%);
|
|
278
251
|
font-family: var(--font-mono);
|
|
279
|
-
font-size:
|
|
252
|
+
font-size: 9px;
|
|
280
253
|
color: var(--text-muted);
|
|
281
254
|
background: var(--bg-hover);
|
|
282
255
|
padding: 1px 5px;
|
|
283
256
|
border-radius: 3px;
|
|
284
257
|
border: 1px solid var(--border);
|
|
258
|
+
letter-spacing: 0.5px;
|
|
285
259
|
}
|
|
286
260
|
|
|
287
261
|
.search-results {
|
|
288
262
|
position: absolute;
|
|
289
|
-
top: calc(100% +
|
|
263
|
+
top: calc(100% + 8px);
|
|
290
264
|
right: 0;
|
|
291
|
-
width:
|
|
292
|
-
max-height:
|
|
265
|
+
width: 400px;
|
|
266
|
+
max-height: 380px;
|
|
293
267
|
overflow-y: auto;
|
|
294
268
|
background: var(--bg-card);
|
|
295
269
|
border: 1px solid var(--border);
|
|
296
|
-
border-radius:
|
|
270
|
+
border-radius: var(--radius-lg);
|
|
297
271
|
z-index: 100;
|
|
298
272
|
display: none;
|
|
299
|
-
|
|
300
|
-
box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 1px var(--neon-cyan);
|
|
273
|
+
box-shadow: 0 12px 40px rgba(0,0,0,0.5);
|
|
301
274
|
}
|
|
302
275
|
|
|
303
276
|
.search-results.active { display: block; }
|
|
304
277
|
|
|
305
278
|
.search-result {
|
|
306
|
-
padding:
|
|
279
|
+
padding: 10px 14px;
|
|
307
280
|
cursor: pointer;
|
|
308
|
-
border-bottom: 1px solid var(--border);
|
|
281
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
309
282
|
transition: background 0.15s;
|
|
310
283
|
}
|
|
311
284
|
|
|
@@ -313,8 +286,8 @@ body.resizing .resize-handle {
|
|
|
313
286
|
.search-result:hover { background: var(--bg-hover); }
|
|
314
287
|
|
|
315
288
|
.search-result .sr-title {
|
|
316
|
-
font-size:
|
|
317
|
-
font-weight:
|
|
289
|
+
font-size: 12px;
|
|
290
|
+
font-weight: 500;
|
|
318
291
|
color: var(--neon-cyan);
|
|
319
292
|
}
|
|
320
293
|
|
|
@@ -322,20 +295,102 @@ body.resizing .resize-handle {
|
|
|
322
295
|
font-family: var(--font-mono);
|
|
323
296
|
font-size: 10px;
|
|
324
297
|
color: var(--text-muted);
|
|
325
|
-
margin-top:
|
|
298
|
+
margin-top: 2px;
|
|
326
299
|
}
|
|
327
300
|
|
|
328
301
|
.search-result .sr-snippet {
|
|
329
|
-
font-size:
|
|
302
|
+
font-size: 11px;
|
|
330
303
|
color: var(--text-secondary);
|
|
331
304
|
margin-top: 4px;
|
|
332
|
-
line-height: 1.
|
|
305
|
+
line-height: 1.5;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* ============ QUICK SWITCHER ============ */
|
|
309
|
+
.quick-switcher-overlay {
|
|
310
|
+
position: fixed;
|
|
311
|
+
inset: 0;
|
|
312
|
+
background: rgba(6,6,12,0.7);
|
|
313
|
+
z-index: 200;
|
|
314
|
+
display: none;
|
|
315
|
+
align-items: flex-start;
|
|
316
|
+
justify-content: center;
|
|
317
|
+
padding-top: 15vh;
|
|
318
|
+
backdrop-filter: blur(4px);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.quick-switcher-overlay.active { display: flex; }
|
|
322
|
+
|
|
323
|
+
.quick-switcher {
|
|
324
|
+
width: 480px;
|
|
325
|
+
background: var(--bg-card);
|
|
326
|
+
border: 1px solid var(--border);
|
|
327
|
+
border-radius: var(--radius-lg);
|
|
328
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 1px var(--neon-cyan);
|
|
329
|
+
overflow: hidden;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.quick-switcher input {
|
|
333
|
+
width: 100%;
|
|
334
|
+
background: transparent;
|
|
335
|
+
border: none;
|
|
336
|
+
border-bottom: 1px solid var(--border);
|
|
337
|
+
color: var(--text-primary);
|
|
338
|
+
font-family: var(--font-mono);
|
|
339
|
+
font-size: 14px;
|
|
340
|
+
padding: 16px 20px;
|
|
341
|
+
outline: none;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.quick-switcher input::placeholder { color: var(--text-muted); }
|
|
345
|
+
|
|
346
|
+
.quick-switcher-results {
|
|
347
|
+
max-height: 320px;
|
|
348
|
+
overflow-y: auto;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.qs-item {
|
|
352
|
+
padding: 10px 20px;
|
|
353
|
+
cursor: pointer;
|
|
354
|
+
display: flex;
|
|
355
|
+
align-items: center;
|
|
356
|
+
gap: 10px;
|
|
357
|
+
transition: background 0.1s;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.qs-item:hover, .qs-item.selected { background: var(--bg-hover); }
|
|
361
|
+
|
|
362
|
+
.qs-item .qs-icon {
|
|
363
|
+
color: var(--neon-purple);
|
|
364
|
+
font-size: 12px;
|
|
365
|
+
flex-shrink: 0;
|
|
366
|
+
opacity: 0.7;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.qs-item .qs-name {
|
|
370
|
+
font-size: 13px;
|
|
371
|
+
color: var(--text-primary);
|
|
372
|
+
font-weight: 500;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.qs-item .qs-path {
|
|
376
|
+
font-family: var(--font-mono);
|
|
377
|
+
font-size: 10px;
|
|
378
|
+
color: var(--text-muted);
|
|
379
|
+
margin-left: auto;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.qs-item.selected .qs-name { color: var(--neon-cyan); }
|
|
383
|
+
|
|
384
|
+
.qs-empty {
|
|
385
|
+
padding: 20px;
|
|
386
|
+
text-align: center;
|
|
387
|
+
color: var(--text-muted);
|
|
388
|
+
font-size: 12px;
|
|
333
389
|
}
|
|
334
390
|
|
|
335
391
|
/* ============ SIDEBAR ============ */
|
|
336
392
|
.sidebar {
|
|
337
393
|
background: var(--bg-secondary);
|
|
338
|
-
border-right: 1px solid var(--border);
|
|
339
394
|
display: flex;
|
|
340
395
|
flex-direction: column;
|
|
341
396
|
overflow: hidden;
|
|
@@ -344,38 +399,42 @@ body.resizing .resize-handle {
|
|
|
344
399
|
.sidebar-scroll {
|
|
345
400
|
flex: 1;
|
|
346
401
|
overflow-y: auto;
|
|
347
|
-
padding:
|
|
402
|
+
padding: 6px 0;
|
|
348
403
|
}
|
|
349
404
|
|
|
350
|
-
.sidebar-section { padding: 0
|
|
405
|
+
.sidebar-section { padding: 0 8px; }
|
|
351
406
|
|
|
352
|
-
.
|
|
407
|
+
.section-label {
|
|
353
408
|
font-family: var(--font-mono);
|
|
354
|
-
font-size:
|
|
409
|
+
font-size: 9px;
|
|
355
410
|
font-weight: 600;
|
|
356
411
|
text-transform: uppercase;
|
|
357
412
|
letter-spacing: 1.5px;
|
|
358
413
|
color: var(--text-muted);
|
|
359
|
-
padding: 10px
|
|
414
|
+
padding: 12px 10px 6px;
|
|
415
|
+
display: flex;
|
|
416
|
+
align-items: center;
|
|
417
|
+
justify-content: space-between;
|
|
360
418
|
}
|
|
361
419
|
|
|
362
420
|
.tree-item {
|
|
363
421
|
display: flex;
|
|
364
422
|
align-items: center;
|
|
365
|
-
padding:
|
|
366
|
-
border-radius:
|
|
423
|
+
padding: 4px 10px;
|
|
424
|
+
border-radius: var(--radius-sm);
|
|
367
425
|
cursor: pointer;
|
|
368
|
-
font-size:
|
|
426
|
+
font-size: 12px;
|
|
369
427
|
gap: 6px;
|
|
370
428
|
user-select: none;
|
|
371
|
-
transition:
|
|
429
|
+
transition: background 0.1s;
|
|
372
430
|
position: relative;
|
|
431
|
+
margin: 1px 0;
|
|
373
432
|
}
|
|
374
433
|
|
|
375
434
|
.tree-item:hover { background: var(--bg-hover); }
|
|
376
435
|
|
|
377
436
|
.tree-item.active {
|
|
378
|
-
background: rgba(0,
|
|
437
|
+
background: rgba(0,232,223,0.05);
|
|
379
438
|
}
|
|
380
439
|
|
|
381
440
|
.tree-item.active::before {
|
|
@@ -387,12 +446,11 @@ body.resizing .resize-handle {
|
|
|
387
446
|
width: 2px;
|
|
388
447
|
background: var(--neon-cyan);
|
|
389
448
|
border-radius: 1px;
|
|
390
|
-
box-shadow: 0 0 6px var(--neon-cyan);
|
|
391
449
|
}
|
|
392
450
|
|
|
393
451
|
.tree-item .arrow {
|
|
394
|
-
width:
|
|
395
|
-
font-size:
|
|
452
|
+
width: 12px;
|
|
453
|
+
font-size: 8px;
|
|
396
454
|
color: var(--text-muted);
|
|
397
455
|
text-align: center;
|
|
398
456
|
flex-shrink: 0;
|
|
@@ -403,7 +461,8 @@ body.resizing .resize-handle {
|
|
|
403
461
|
|
|
404
462
|
.tree-item .icon {
|
|
405
463
|
flex-shrink: 0;
|
|
406
|
-
font-size:
|
|
464
|
+
font-size: 11px;
|
|
465
|
+
opacity: 0.6;
|
|
407
466
|
}
|
|
408
467
|
|
|
409
468
|
.tree-item .folder-icon { color: var(--neon-yellow); }
|
|
@@ -413,146 +472,254 @@ body.resizing .resize-handle {
|
|
|
413
472
|
overflow: hidden;
|
|
414
473
|
text-overflow: ellipsis;
|
|
415
474
|
white-space: nowrap;
|
|
416
|
-
font-size:
|
|
475
|
+
font-size: 12px;
|
|
417
476
|
color: var(--text-primary);
|
|
418
477
|
}
|
|
419
478
|
|
|
420
479
|
.tree-item.active .name { color: var(--neon-cyan); }
|
|
421
480
|
|
|
422
|
-
.tree-children {
|
|
423
|
-
|
|
424
|
-
|
|
481
|
+
.tree-children { padding-left: 12px; overflow: hidden; }
|
|
482
|
+
.tree-children.collapsed { display: none; }
|
|
483
|
+
|
|
484
|
+
/* ============ TAG FILTER ============ */
|
|
485
|
+
.tag-filter-section { padding: 0 8px 8px; }
|
|
486
|
+
|
|
487
|
+
.tag-filter-header {
|
|
488
|
+
font-family: var(--font-mono);
|
|
489
|
+
font-size: 9px;
|
|
490
|
+
font-weight: 600;
|
|
491
|
+
text-transform: uppercase;
|
|
492
|
+
letter-spacing: 1.5px;
|
|
493
|
+
color: var(--text-muted);
|
|
494
|
+
padding: 12px 10px 6px;
|
|
495
|
+
display: flex;
|
|
496
|
+
align-items: center;
|
|
497
|
+
justify-content: space-between;
|
|
498
|
+
cursor: pointer;
|
|
499
|
+
user-select: none;
|
|
425
500
|
}
|
|
426
501
|
|
|
427
|
-
.
|
|
502
|
+
.tag-filter-header .arrow {
|
|
503
|
+
font-size: 8px;
|
|
504
|
+
transition: transform 0.15s;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.tag-filter-header .arrow.open { transform: rotate(90deg); }
|
|
508
|
+
|
|
509
|
+
.tag-filter-body { padding: 0 4px; }
|
|
510
|
+
.tag-filter-body.collapsed { display: none; }
|
|
511
|
+
|
|
512
|
+
.tag-filter-active {
|
|
513
|
+
display: flex;
|
|
514
|
+
flex-wrap: wrap;
|
|
515
|
+
gap: 4px;
|
|
516
|
+
margin-bottom: 6px;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.tag-filter-active:empty { display: none; }
|
|
520
|
+
|
|
521
|
+
.active-tag {
|
|
522
|
+
font-family: var(--font-mono);
|
|
523
|
+
font-size: 9px;
|
|
524
|
+
padding: 2px 7px;
|
|
525
|
+
border-radius: var(--radius-sm);
|
|
526
|
+
background: rgba(0,232,223,0.08);
|
|
527
|
+
color: var(--neon-cyan);
|
|
528
|
+
border: 1px solid rgba(0,232,223,0.2);
|
|
529
|
+
cursor: pointer;
|
|
530
|
+
display: flex;
|
|
531
|
+
align-items: center;
|
|
532
|
+
gap: 3px;
|
|
533
|
+
transition: all 0.15s;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.active-tag:hover { background: rgba(0,232,223,0.15); }
|
|
537
|
+
.active-tag .remove { font-size: 11px; opacity: 0.5; }
|
|
538
|
+
.active-tag .remove:hover { opacity: 1; }
|
|
539
|
+
|
|
540
|
+
.tag-cloud {
|
|
541
|
+
display: flex;
|
|
542
|
+
flex-wrap: wrap;
|
|
543
|
+
gap: 3px;
|
|
544
|
+
max-height: 140px;
|
|
545
|
+
overflow-y: auto;
|
|
546
|
+
padding: 2px 0;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.tag-chip {
|
|
550
|
+
font-family: var(--font-mono);
|
|
551
|
+
font-size: 9px;
|
|
552
|
+
font-weight: 500;
|
|
553
|
+
padding: 2px 7px;
|
|
554
|
+
border-radius: var(--radius-sm);
|
|
555
|
+
background: rgba(168,139,250,0.06);
|
|
556
|
+
color: var(--neon-purple);
|
|
557
|
+
border: 1px solid rgba(168,139,250,0.1);
|
|
558
|
+
cursor: pointer;
|
|
559
|
+
transition: all 0.15s;
|
|
560
|
+
user-select: none;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.tag-chip:hover {
|
|
564
|
+
background: rgba(168,139,250,0.12);
|
|
565
|
+
border-color: rgba(168,139,250,0.25);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.tag-chip.selected {
|
|
569
|
+
background: rgba(0,232,223,0.08);
|
|
570
|
+
color: var(--neon-cyan);
|
|
571
|
+
border-color: rgba(0,232,223,0.2);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.tag-chip .tag-count {
|
|
575
|
+
font-size: 8px;
|
|
576
|
+
opacity: 0.4;
|
|
577
|
+
margin-left: 2px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.filter-info {
|
|
581
|
+
font-family: var(--font-mono);
|
|
582
|
+
font-size: 9px;
|
|
583
|
+
color: var(--text-muted);
|
|
584
|
+
padding: 2px 10px 4px;
|
|
585
|
+
display: flex;
|
|
586
|
+
align-items: center;
|
|
587
|
+
justify-content: space-between;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.filter-info .clear-btn {
|
|
591
|
+
color: var(--neon-cyan);
|
|
592
|
+
cursor: pointer;
|
|
593
|
+
font-size: 9px;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.filter-info .clear-btn:hover { text-decoration: underline; }
|
|
428
597
|
|
|
429
598
|
.stats-bar {
|
|
430
|
-
padding:
|
|
431
|
-
border-top: 1px solid var(--border);
|
|
599
|
+
padding: 8px 14px;
|
|
600
|
+
border-top: 1px solid var(--border-subtle);
|
|
432
601
|
font-family: var(--font-mono);
|
|
433
|
-
font-size:
|
|
602
|
+
font-size: 9px;
|
|
434
603
|
color: var(--text-muted);
|
|
435
604
|
display: flex;
|
|
436
|
-
gap:
|
|
605
|
+
gap: 12px;
|
|
437
606
|
flex-wrap: wrap;
|
|
438
607
|
}
|
|
439
608
|
|
|
440
|
-
.stat-val { color: var(--neon-green); font-weight:
|
|
609
|
+
.stat-val { color: var(--neon-green); font-weight: 500; }
|
|
441
610
|
|
|
442
611
|
/* ============ CONTENT ============ */
|
|
443
612
|
.content {
|
|
444
613
|
overflow-y: auto;
|
|
445
|
-
padding:
|
|
614
|
+
padding: 40px 56px;
|
|
446
615
|
background: var(--bg-primary);
|
|
447
616
|
}
|
|
448
617
|
|
|
449
618
|
.note-properties {
|
|
450
619
|
display: flex;
|
|
451
620
|
flex-wrap: wrap;
|
|
452
|
-
gap:
|
|
453
|
-
margin-bottom:
|
|
454
|
-
padding-bottom:
|
|
455
|
-
border-bottom: 1px solid var(--border);
|
|
621
|
+
gap: 5px;
|
|
622
|
+
margin-bottom: 28px;
|
|
623
|
+
padding-bottom: 20px;
|
|
624
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
456
625
|
}
|
|
457
626
|
|
|
458
627
|
.tag {
|
|
459
628
|
font-family: var(--font-mono);
|
|
460
|
-
font-size:
|
|
629
|
+
font-size: 10px;
|
|
461
630
|
font-weight: 500;
|
|
462
|
-
padding:
|
|
463
|
-
border-radius:
|
|
464
|
-
background: rgba(
|
|
465
|
-
color: var(--neon-
|
|
466
|
-
border: 1px solid rgba(
|
|
631
|
+
padding: 2px 9px;
|
|
632
|
+
border-radius: var(--radius-sm);
|
|
633
|
+
background: rgba(168,139,250,0.08);
|
|
634
|
+
color: var(--neon-purple);
|
|
635
|
+
border: 1px solid rgba(168,139,250,0.12);
|
|
636
|
+
transition: all 0.15s;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.tag.clickable-tag:hover {
|
|
640
|
+
background: rgba(0,232,223,0.08);
|
|
641
|
+
color: var(--neon-cyan);
|
|
642
|
+
border-color: rgba(0,232,223,0.2);
|
|
643
|
+
cursor: pointer;
|
|
467
644
|
}
|
|
468
645
|
|
|
469
646
|
.prop-item {
|
|
470
647
|
font-family: var(--font-mono);
|
|
471
|
-
font-size:
|
|
472
|
-
padding:
|
|
473
|
-
border-radius:
|
|
648
|
+
font-size: 10px;
|
|
649
|
+
padding: 2px 9px;
|
|
650
|
+
border-radius: var(--radius-sm);
|
|
474
651
|
background: var(--bg-card);
|
|
475
652
|
color: var(--text-secondary);
|
|
476
|
-
border: 1px solid var(--border);
|
|
653
|
+
border: 1px solid var(--border-subtle);
|
|
477
654
|
}
|
|
478
655
|
|
|
479
656
|
.prop-item .prop-key { color: var(--text-muted); }
|
|
480
657
|
|
|
481
658
|
/* ============ MARKDOWN ============ */
|
|
482
659
|
.md-body h1 {
|
|
483
|
-
font-size:
|
|
660
|
+
font-size: 26px;
|
|
484
661
|
font-weight: 700;
|
|
485
|
-
margin: 0 0
|
|
486
|
-
color: var(--
|
|
487
|
-
|
|
662
|
+
margin: 0 0 24px;
|
|
663
|
+
color: var(--text-primary);
|
|
664
|
+
letter-spacing: -0.3px;
|
|
488
665
|
}
|
|
489
666
|
|
|
490
667
|
.md-body h2 {
|
|
491
|
-
font-size:
|
|
668
|
+
font-size: 18px;
|
|
492
669
|
font-weight: 600;
|
|
493
|
-
margin:
|
|
494
|
-
color: var(--
|
|
670
|
+
margin: 36px 0 12px;
|
|
671
|
+
color: var(--text-primary);
|
|
495
672
|
padding-bottom: 8px;
|
|
496
|
-
border-bottom: 1px solid var(--border);
|
|
673
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
497
674
|
}
|
|
498
675
|
|
|
499
676
|
.md-body h3 {
|
|
500
|
-
font-size:
|
|
677
|
+
font-size: 15px;
|
|
501
678
|
font-weight: 600;
|
|
502
|
-
margin:
|
|
679
|
+
margin: 28px 0 8px;
|
|
503
680
|
color: var(--neon-purple);
|
|
504
681
|
}
|
|
505
682
|
|
|
506
683
|
.md-body p {
|
|
507
|
-
line-height: 1.
|
|
508
|
-
margin:
|
|
684
|
+
line-height: 1.8;
|
|
685
|
+
margin: 8px 0;
|
|
509
686
|
color: var(--text-secondary);
|
|
687
|
+
font-size: 13.5px;
|
|
510
688
|
}
|
|
511
689
|
|
|
512
690
|
.md-body ul, .md-body ol { padding-left: 24px; margin: 8px 0; }
|
|
513
691
|
|
|
514
692
|
.md-body li {
|
|
515
|
-
line-height: 1.
|
|
693
|
+
line-height: 1.8;
|
|
516
694
|
color: var(--text-secondary);
|
|
517
|
-
margin:
|
|
695
|
+
margin: 2px 0;
|
|
696
|
+
font-size: 13.5px;
|
|
518
697
|
}
|
|
519
698
|
|
|
520
|
-
.md-body li::marker { color: var(--
|
|
699
|
+
.md-body li::marker { color: var(--text-muted); }
|
|
521
700
|
|
|
522
701
|
.md-body a { color: var(--neon-blue); text-decoration: none; }
|
|
523
|
-
.md-body a:hover { text-decoration: underline;
|
|
702
|
+
.md-body a:hover { text-decoration: underline; }
|
|
524
703
|
|
|
525
704
|
.md-body strong { color: var(--text-primary); font-weight: 600; }
|
|
526
705
|
|
|
527
706
|
.md-body code {
|
|
528
707
|
background: var(--bg-card);
|
|
529
|
-
padding:
|
|
530
|
-
border-radius:
|
|
708
|
+
padding: 1.5px 6px;
|
|
709
|
+
border-radius: 3px;
|
|
531
710
|
font-family: var(--font-mono);
|
|
532
711
|
font-size: 12px;
|
|
533
712
|
color: var(--neon-orange);
|
|
534
|
-
border: 1px solid var(--border);
|
|
713
|
+
border: 1px solid var(--border-subtle);
|
|
535
714
|
}
|
|
536
715
|
|
|
537
716
|
.md-body pre {
|
|
538
717
|
background: var(--bg-tertiary);
|
|
539
718
|
border: 1px solid var(--border);
|
|
540
|
-
border-radius:
|
|
541
|
-
padding: 18px;
|
|
719
|
+
border-radius: var(--radius);
|
|
720
|
+
padding: 16px 18px;
|
|
542
721
|
overflow-x: auto;
|
|
543
722
|
margin: 16px 0;
|
|
544
|
-
position: relative;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
.md-body pre::before {
|
|
548
|
-
content: '';
|
|
549
|
-
position: absolute;
|
|
550
|
-
top: 0;
|
|
551
|
-
left: 0;
|
|
552
|
-
right: 0;
|
|
553
|
-
height: 1px;
|
|
554
|
-
background: linear-gradient(90deg, var(--neon-cyan), var(--neon-magenta), transparent);
|
|
555
|
-
opacity: 0.3;
|
|
556
723
|
}
|
|
557
724
|
|
|
558
725
|
.md-body pre code {
|
|
@@ -560,65 +727,63 @@ body.resizing .resize-handle {
|
|
|
560
727
|
padding: 0;
|
|
561
728
|
border: none;
|
|
562
729
|
color: var(--text-primary);
|
|
563
|
-
font-size:
|
|
564
|
-
line-height: 1.
|
|
730
|
+
font-size: 12px;
|
|
731
|
+
line-height: 1.7;
|
|
565
732
|
}
|
|
566
733
|
|
|
567
734
|
.md-body table {
|
|
568
735
|
width: 100%;
|
|
569
736
|
border-collapse: collapse;
|
|
570
737
|
margin: 16px 0;
|
|
571
|
-
font-size:
|
|
738
|
+
font-size: 12.5px;
|
|
572
739
|
}
|
|
573
740
|
|
|
574
741
|
.md-body th {
|
|
575
742
|
text-align: left;
|
|
576
|
-
padding:
|
|
577
|
-
border-bottom:
|
|
578
|
-
color: var(--
|
|
743
|
+
padding: 8px 12px;
|
|
744
|
+
border-bottom: 1px solid var(--border);
|
|
745
|
+
color: var(--text-secondary);
|
|
579
746
|
font-family: var(--font-mono);
|
|
580
747
|
font-weight: 600;
|
|
581
|
-
font-size:
|
|
748
|
+
font-size: 10px;
|
|
582
749
|
text-transform: uppercase;
|
|
583
750
|
letter-spacing: 0.5px;
|
|
584
751
|
}
|
|
585
752
|
|
|
586
753
|
.md-body td {
|
|
587
|
-
padding:
|
|
588
|
-
border-bottom: 1px solid var(--border);
|
|
754
|
+
padding: 8px 12px;
|
|
755
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
589
756
|
color: var(--text-secondary);
|
|
590
757
|
}
|
|
591
758
|
|
|
592
759
|
.md-body tr:hover td { background: var(--bg-hover); }
|
|
593
760
|
|
|
594
761
|
.md-body blockquote {
|
|
595
|
-
border-left:
|
|
762
|
+
border-left: 2px solid var(--neon-purple);
|
|
596
763
|
padding-left: 16px;
|
|
597
764
|
margin: 16px 0;
|
|
598
765
|
color: var(--text-muted);
|
|
599
|
-
box-shadow: -3px 0 8px rgba(255,0,224,0.1);
|
|
600
766
|
}
|
|
601
767
|
|
|
602
768
|
.md-body hr {
|
|
603
769
|
border: none;
|
|
604
770
|
height: 1px;
|
|
605
|
-
background:
|
|
606
|
-
margin:
|
|
771
|
+
background: var(--border);
|
|
772
|
+
margin: 28px 0;
|
|
607
773
|
}
|
|
608
774
|
|
|
609
775
|
.wikilink {
|
|
610
776
|
color: var(--neon-purple);
|
|
611
777
|
cursor: pointer;
|
|
612
778
|
text-decoration: none;
|
|
613
|
-
border-bottom: 1px dashed rgba(
|
|
779
|
+
border-bottom: 1px dashed rgba(168,139,250,0.3);
|
|
614
780
|
transition: all 0.15s;
|
|
615
781
|
font-weight: 500;
|
|
616
782
|
}
|
|
617
783
|
|
|
618
784
|
.wikilink:hover {
|
|
619
|
-
color: var(--neon-
|
|
620
|
-
|
|
621
|
-
border-bottom-color: var(--neon-magenta);
|
|
785
|
+
color: var(--neon-cyan);
|
|
786
|
+
border-bottom-color: rgba(0,232,223,0.4);
|
|
622
787
|
}
|
|
623
788
|
|
|
624
789
|
/* ============ EMPTY STATE ============ */
|
|
@@ -628,35 +793,35 @@ body.resizing .resize-handle {
|
|
|
628
793
|
align-items: center;
|
|
629
794
|
justify-content: center;
|
|
630
795
|
height: 100%;
|
|
631
|
-
gap:
|
|
796
|
+
gap: 12px;
|
|
632
797
|
}
|
|
633
798
|
|
|
634
799
|
.empty-state .es-logo {
|
|
635
800
|
font-family: var(--font-mono);
|
|
636
|
-
font-size:
|
|
801
|
+
font-size: 28px;
|
|
637
802
|
font-weight: 700;
|
|
638
803
|
color: var(--neon-cyan);
|
|
639
|
-
|
|
640
|
-
|
|
804
|
+
letter-spacing: 4px;
|
|
805
|
+
opacity: 0.6;
|
|
641
806
|
}
|
|
642
807
|
|
|
643
808
|
.empty-state .es-tagline {
|
|
644
809
|
font-family: var(--font-mono);
|
|
645
|
-
font-size:
|
|
810
|
+
font-size: 11px;
|
|
646
811
|
color: var(--text-muted);
|
|
647
|
-
letter-spacing:
|
|
812
|
+
letter-spacing: 3px;
|
|
648
813
|
text-transform: uppercase;
|
|
649
814
|
}
|
|
650
815
|
|
|
651
816
|
.empty-state .es-hint {
|
|
652
|
-
font-size:
|
|
817
|
+
font-size: 12px;
|
|
653
818
|
color: var(--text-muted);
|
|
654
|
-
margin-top:
|
|
819
|
+
margin-top: 24px;
|
|
655
820
|
}
|
|
656
821
|
|
|
657
822
|
.empty-state .es-hint kbd {
|
|
658
823
|
font-family: var(--font-mono);
|
|
659
|
-
font-size:
|
|
824
|
+
font-size: 10px;
|
|
660
825
|
background: var(--bg-card);
|
|
661
826
|
border: 1px solid var(--border);
|
|
662
827
|
padding: 2px 6px;
|
|
@@ -667,21 +832,20 @@ body.resizing .resize-handle {
|
|
|
667
832
|
/* ============ RIGHT PANEL ============ */
|
|
668
833
|
.right-panel {
|
|
669
834
|
background: var(--bg-secondary);
|
|
670
|
-
border-left: 1px solid var(--border);
|
|
671
835
|
overflow-y: auto;
|
|
672
|
-
padding:
|
|
836
|
+
padding: 12px;
|
|
673
837
|
}
|
|
674
838
|
|
|
675
|
-
.rp-section { margin-bottom:
|
|
839
|
+
.rp-section { margin-bottom: 20px; }
|
|
676
840
|
|
|
677
841
|
.rp-section-title {
|
|
678
842
|
font-family: var(--font-mono);
|
|
679
|
-
font-size:
|
|
843
|
+
font-size: 9px;
|
|
680
844
|
font-weight: 600;
|
|
681
845
|
text-transform: uppercase;
|
|
682
846
|
letter-spacing: 1.5px;
|
|
683
847
|
color: var(--text-muted);
|
|
684
|
-
margin-bottom:
|
|
848
|
+
margin-bottom: 8px;
|
|
685
849
|
display: flex;
|
|
686
850
|
align-items: center;
|
|
687
851
|
gap: 6px;
|
|
@@ -691,32 +855,30 @@ body.resizing .resize-handle {
|
|
|
691
855
|
background: var(--bg-hover);
|
|
692
856
|
color: var(--text-muted);
|
|
693
857
|
font-size: 9px;
|
|
694
|
-
padding:
|
|
858
|
+
padding: 0px 5px;
|
|
695
859
|
border-radius: 8px;
|
|
696
860
|
}
|
|
697
861
|
|
|
698
862
|
.rp-item {
|
|
699
863
|
display: flex;
|
|
700
864
|
align-items: center;
|
|
701
|
-
padding:
|
|
702
|
-
border-radius:
|
|
865
|
+
padding: 5px 8px;
|
|
866
|
+
border-radius: var(--radius-sm);
|
|
703
867
|
cursor: pointer;
|
|
704
|
-
font-size:
|
|
868
|
+
font-size: 11px;
|
|
705
869
|
gap: 8px;
|
|
706
|
-
margin-bottom:
|
|
707
|
-
transition:
|
|
870
|
+
margin-bottom: 1px;
|
|
871
|
+
transition: background 0.1s;
|
|
708
872
|
}
|
|
709
873
|
|
|
710
|
-
.rp-item:hover {
|
|
711
|
-
background: var(--bg-hover);
|
|
712
|
-
}
|
|
874
|
+
.rp-item:hover { background: var(--bg-hover); }
|
|
713
875
|
|
|
714
876
|
.rp-item .rp-score {
|
|
715
877
|
font-family: var(--font-mono);
|
|
716
|
-
font-size:
|
|
878
|
+
font-size: 10px;
|
|
717
879
|
color: var(--neon-green);
|
|
718
|
-
min-width:
|
|
719
|
-
|
|
880
|
+
min-width: 30px;
|
|
881
|
+
opacity: 0.8;
|
|
720
882
|
}
|
|
721
883
|
|
|
722
884
|
.rp-item .rp-title {
|
|
@@ -727,89 +889,214 @@ body.resizing .resize-handle {
|
|
|
727
889
|
font-weight: 500;
|
|
728
890
|
}
|
|
729
891
|
|
|
730
|
-
.rp-item .rp-backlink-title {
|
|
731
|
-
|
|
892
|
+
.rp-item .rp-backlink-title { color: var(--neon-cyan); }
|
|
893
|
+
|
|
894
|
+
/* ============ OUTLINE ============ */
|
|
895
|
+
.outline-item {
|
|
896
|
+
display: block;
|
|
897
|
+
padding: 3px 8px;
|
|
898
|
+
border-radius: var(--radius-sm);
|
|
899
|
+
cursor: pointer;
|
|
900
|
+
font-size: 11px;
|
|
901
|
+
color: var(--text-secondary);
|
|
902
|
+
transition: all 0.1s;
|
|
903
|
+
overflow: hidden;
|
|
904
|
+
text-overflow: ellipsis;
|
|
905
|
+
white-space: nowrap;
|
|
906
|
+
margin-bottom: 1px;
|
|
732
907
|
}
|
|
733
908
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
909
|
+
.outline-item:hover {
|
|
910
|
+
background: var(--bg-hover);
|
|
911
|
+
color: var(--text-primary);
|
|
737
912
|
}
|
|
738
913
|
|
|
914
|
+
.outline-item.h2 { padding-left: 8px; }
|
|
915
|
+
.outline-item.h3 { padding-left: 20px; font-size: 10px; color: var(--text-muted); }
|
|
916
|
+
|
|
917
|
+
/* ============ GRAPH ============ */
|
|
918
|
+
#graph-section { margin-bottom: 12px; }
|
|
739
919
|
#graph-section.hidden { display: none; }
|
|
740
920
|
|
|
741
921
|
#graph-container {
|
|
742
922
|
width: 100%;
|
|
743
|
-
height:
|
|
744
|
-
border: 1px solid var(--border);
|
|
745
|
-
border-radius:
|
|
923
|
+
height: 200px;
|
|
924
|
+
border: 1px solid var(--border-subtle);
|
|
925
|
+
border-radius: var(--radius);
|
|
746
926
|
overflow: hidden;
|
|
747
927
|
background: var(--bg-tertiary);
|
|
748
|
-
position: relative;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
#graph-container::before {
|
|
752
|
-
content: '';
|
|
753
|
-
position: absolute;
|
|
754
|
-
inset: 0;
|
|
755
|
-
background-image:
|
|
756
|
-
radial-gradient(rgba(0,255,245,0.03) 1px, transparent 1px);
|
|
757
|
-
background-size: 16px 16px;
|
|
758
|
-
pointer-events: none;
|
|
759
928
|
}
|
|
760
929
|
|
|
761
|
-
#graph-container svg { width: 100%; height: 100%;
|
|
930
|
+
#graph-container svg { width: 100%; height: 100%; }
|
|
762
931
|
|
|
763
932
|
.graph-node { cursor: pointer; }
|
|
764
933
|
|
|
765
934
|
.graph-node circle {
|
|
766
935
|
fill: var(--neon-purple);
|
|
767
|
-
filter: drop-shadow(0 0
|
|
936
|
+
filter: drop-shadow(0 0 2px rgba(168,139,250,0.4));
|
|
768
937
|
transition: all 0.2s;
|
|
769
938
|
}
|
|
770
939
|
|
|
771
940
|
.graph-node:hover circle {
|
|
772
941
|
fill: var(--neon-cyan);
|
|
773
|
-
filter: drop-shadow(0 0
|
|
942
|
+
filter: drop-shadow(0 0 4px rgba(0,232,223,0.5));
|
|
774
943
|
}
|
|
775
944
|
|
|
776
945
|
.graph-node.active circle {
|
|
777
946
|
fill: var(--neon-cyan);
|
|
778
|
-
r:
|
|
779
|
-
filter: drop-shadow(0 0
|
|
947
|
+
r: 6;
|
|
948
|
+
filter: drop-shadow(0 0 6px rgba(0,232,223,0.5));
|
|
780
949
|
}
|
|
781
950
|
|
|
782
951
|
.graph-node text {
|
|
783
|
-
fill: var(--text-
|
|
952
|
+
fill: var(--text-muted);
|
|
784
953
|
font-family: var(--font-mono);
|
|
785
|
-
font-size:
|
|
954
|
+
font-size: 8px;
|
|
786
955
|
}
|
|
787
956
|
|
|
788
957
|
.graph-link {
|
|
789
|
-
stroke: rgba(
|
|
958
|
+
stroke: rgba(168,139,250,0.15);
|
|
790
959
|
stroke-width: 1;
|
|
791
960
|
}
|
|
792
961
|
|
|
793
962
|
/* ============ SCROLLBAR ============ */
|
|
794
|
-
::-webkit-scrollbar { width:
|
|
963
|
+
::-webkit-scrollbar { width: 4px; }
|
|
795
964
|
::-webkit-scrollbar-track { background: transparent; }
|
|
796
|
-
::-webkit-scrollbar-thumb { background: var(--
|
|
965
|
+
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
|
|
797
966
|
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
|
|
798
967
|
|
|
799
|
-
/* ============
|
|
800
|
-
.
|
|
801
|
-
|
|
968
|
+
/* ============ EDIT MODAL ============ */
|
|
969
|
+
.edit-overlay {
|
|
970
|
+
position: fixed;
|
|
971
|
+
inset: 0;
|
|
972
|
+
background: rgba(6,6,12,0.75);
|
|
973
|
+
z-index: 200;
|
|
974
|
+
display: none;
|
|
975
|
+
align-items: center;
|
|
976
|
+
justify-content: center;
|
|
977
|
+
backdrop-filter: blur(4px);
|
|
802
978
|
}
|
|
803
979
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
980
|
+
.edit-overlay.active { display: flex; }
|
|
981
|
+
|
|
982
|
+
.edit-modal {
|
|
983
|
+
width: 640px;
|
|
984
|
+
max-height: 80vh;
|
|
985
|
+
background: var(--bg-card);
|
|
986
|
+
border: 1px solid var(--border);
|
|
987
|
+
border-radius: var(--radius-lg);
|
|
988
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.6);
|
|
989
|
+
display: flex;
|
|
990
|
+
flex-direction: column;
|
|
991
|
+
overflow: hidden;
|
|
807
992
|
}
|
|
808
993
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
994
|
+
.edit-header {
|
|
995
|
+
display: flex;
|
|
996
|
+
align-items: center;
|
|
997
|
+
justify-content: space-between;
|
|
998
|
+
padding: 12px 16px;
|
|
999
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
1000
|
+
font-family: var(--font-mono);
|
|
1001
|
+
font-size: 11px;
|
|
1002
|
+
color: var(--text-secondary);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.edit-header .edit-path { opacity: 0.6; }
|
|
1006
|
+
|
|
1007
|
+
.edit-actions { display: flex; gap: 8px; }
|
|
1008
|
+
|
|
1009
|
+
.edit-btn {
|
|
1010
|
+
font-family: var(--font-mono);
|
|
1011
|
+
font-size: 10px;
|
|
1012
|
+
padding: 5px 14px;
|
|
1013
|
+
border-radius: var(--radius);
|
|
1014
|
+
border: 1px solid var(--border);
|
|
1015
|
+
cursor: pointer;
|
|
1016
|
+
transition: all 0.15s;
|
|
1017
|
+
letter-spacing: 0.5px;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.edit-btn.cancel {
|
|
1021
|
+
background: transparent;
|
|
1022
|
+
color: var(--text-muted);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.edit-btn.cancel:hover { color: var(--text-secondary); border-color: var(--text-muted); }
|
|
1026
|
+
|
|
1027
|
+
.edit-btn.save {
|
|
1028
|
+
background: rgba(0,232,223,0.1);
|
|
1029
|
+
color: var(--neon-cyan);
|
|
1030
|
+
border-color: rgba(0,232,223,0.3);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
.edit-btn.save:hover { background: rgba(0,232,223,0.2); }
|
|
1034
|
+
|
|
1035
|
+
.edit-textarea {
|
|
1036
|
+
flex: 1;
|
|
1037
|
+
min-height: 300px;
|
|
1038
|
+
background: var(--bg-primary);
|
|
1039
|
+
border: none;
|
|
1040
|
+
color: var(--text-primary);
|
|
1041
|
+
font-family: var(--font-mono);
|
|
1042
|
+
font-size: 13px;
|
|
1043
|
+
line-height: 1.7;
|
|
1044
|
+
padding: 16px 20px;
|
|
1045
|
+
resize: none;
|
|
1046
|
+
outline: none;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.edit-textarea::placeholder { color: var(--text-muted); }
|
|
1050
|
+
|
|
1051
|
+
.note-edit-btn {
|
|
1052
|
+
background: transparent;
|
|
1053
|
+
border: 1px solid var(--border);
|
|
1054
|
+
color: var(--text-muted);
|
|
1055
|
+
font-family: var(--font-mono);
|
|
1056
|
+
font-size: 10px;
|
|
1057
|
+
padding: 3px 10px;
|
|
1058
|
+
border-radius: var(--radius-sm);
|
|
1059
|
+
cursor: pointer;
|
|
1060
|
+
transition: all 0.15s;
|
|
1061
|
+
float: right;
|
|
1062
|
+
margin-bottom: 12px;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.note-edit-btn:hover {
|
|
1066
|
+
border-color: var(--text-muted);
|
|
1067
|
+
color: var(--text-secondary);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/* ============ BACKLINK CONTEXT ============ */
|
|
1071
|
+
.rp-item .rp-context {
|
|
1072
|
+
font-size: 10px;
|
|
1073
|
+
color: var(--text-muted);
|
|
1074
|
+
margin-top: 2px;
|
|
1075
|
+
line-height: 1.4;
|
|
1076
|
+
overflow: hidden;
|
|
1077
|
+
text-overflow: ellipsis;
|
|
1078
|
+
white-space: nowrap;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.rp-item-col {
|
|
1082
|
+
display: flex;
|
|
1083
|
+
flex-direction: column;
|
|
1084
|
+
padding: 5px 8px;
|
|
1085
|
+
border-radius: var(--radius-sm);
|
|
1086
|
+
cursor: pointer;
|
|
1087
|
+
margin-bottom: 1px;
|
|
1088
|
+
transition: background 0.1s;
|
|
1089
|
+
overflow: hidden;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
.rp-item-col:hover { background: var(--bg-hover); }
|
|
1093
|
+
|
|
1094
|
+
/* ============ TRANSITIONS ============ */
|
|
1095
|
+
.fade-in { animation: fadeIn 0.15s ease; }
|
|
1096
|
+
|
|
1097
|
+
@keyframes fadeIn {
|
|
1098
|
+
from { opacity: 0; transform: translateY(3px); }
|
|
1099
|
+
to { opacity: 1; transform: translateY(0); }
|
|
813
1100
|
}
|
|
814
1101
|
</style>
|
|
815
1102
|
</head>
|
|
@@ -821,7 +1108,7 @@ body.resizing .resize-handle {
|
|
|
821
1108
|
<div class="logo">KYP-MEM <span class="logo-sub">know your project</span></div>
|
|
822
1109
|
<div class="breadcrumb" id="breadcrumb"></div>
|
|
823
1110
|
<div class="header-actions">
|
|
824
|
-
<button class="
|
|
1111
|
+
<button class="header-btn active" id="graph-toggle" title="Toggle graph">
|
|
825
1112
|
<span class="dot"></span>
|
|
826
1113
|
<span>GRAPH</span>
|
|
827
1114
|
</button>
|
|
@@ -838,9 +1125,23 @@ body.resizing .resize-handle {
|
|
|
838
1125
|
<div class="sidebar">
|
|
839
1126
|
<div class="sidebar-scroll">
|
|
840
1127
|
<div class="sidebar-section">
|
|
841
|
-
<div class="
|
|
1128
|
+
<div class="section-label">Explorer</div>
|
|
1129
|
+
<div id="filter-info" class="filter-info" style="display:none;">
|
|
1130
|
+
<span id="filter-count"></span>
|
|
1131
|
+
<span class="clear-btn" id="clear-filters">clear</span>
|
|
1132
|
+
</div>
|
|
842
1133
|
<div id="file-tree"></div>
|
|
843
1134
|
</div>
|
|
1135
|
+
<div class="tag-filter-section">
|
|
1136
|
+
<div class="tag-filter-header" id="tag-filter-toggle">
|
|
1137
|
+
<span>Tags</span>
|
|
1138
|
+
<span class="arrow open" id="tag-arrow">▶</span>
|
|
1139
|
+
</div>
|
|
1140
|
+
<div class="tag-filter-body" id="tag-filter-body">
|
|
1141
|
+
<div class="tag-filter-active" id="active-tags"></div>
|
|
1142
|
+
<div class="tag-cloud" id="tag-cloud"></div>
|
|
1143
|
+
</div>
|
|
1144
|
+
</div>
|
|
844
1145
|
</div>
|
|
845
1146
|
<div class="stats-bar" id="stats-bar"></div>
|
|
846
1147
|
</div>
|
|
@@ -853,7 +1154,7 @@ body.resizing .resize-handle {
|
|
|
853
1154
|
<div class="empty-state">
|
|
854
1155
|
<div class="es-logo">KYP-MEM</div>
|
|
855
1156
|
<div class="es-tagline">Know Your Project Memory</div>
|
|
856
|
-
<div class="es-hint">Select a note
|
|
1157
|
+
<div class="es-hint">Select a note or press <kbd>⌘O</kbd> to quick-switch · <kbd>⌘K</kbd> to search</div>
|
|
857
1158
|
</div>
|
|
858
1159
|
</div>
|
|
859
1160
|
|
|
@@ -863,9 +1164,13 @@ body.resizing .resize-handle {
|
|
|
863
1164
|
<!-- Right panel -->
|
|
864
1165
|
<div class="right-panel" id="right-panel">
|
|
865
1166
|
<div id="graph-section">
|
|
866
|
-
<div class="rp-section-title">Graph
|
|
1167
|
+
<div class="rp-section-title">Local Graph</div>
|
|
867
1168
|
<div id="graph-container"></div>
|
|
868
1169
|
</div>
|
|
1170
|
+
<div id="rp-outline" class="rp-section" style="display:none;">
|
|
1171
|
+
<div class="rp-section-title">Outline <span class="rp-count" id="outline-count"></span></div>
|
|
1172
|
+
<div id="rp-outline-list"></div>
|
|
1173
|
+
</div>
|
|
869
1174
|
<div id="rp-backlinks" class="rp-section" style="display:none;">
|
|
870
1175
|
<div class="rp-section-title">Backlinks <span class="rp-count" id="bl-count"></span></div>
|
|
871
1176
|
<div id="rp-backlinks-list"></div>
|
|
@@ -878,6 +1183,32 @@ body.resizing .resize-handle {
|
|
|
878
1183
|
<div class="rp-section-title">Outgoing Links <span class="rp-count" id="out-count"></span></div>
|
|
879
1184
|
<div id="rp-outlinks-list"></div>
|
|
880
1185
|
</div>
|
|
1186
|
+
<div id="rp-unlinked" class="rp-section" style="display:none;">
|
|
1187
|
+
<div class="rp-section-title">Unlinked Mentions <span class="rp-count" id="unlinked-count"></span></div>
|
|
1188
|
+
<div id="rp-unlinked-list"></div>
|
|
1189
|
+
</div>
|
|
1190
|
+
</div>
|
|
1191
|
+
</div>
|
|
1192
|
+
|
|
1193
|
+
<!-- Edit Modal -->
|
|
1194
|
+
<div class="edit-overlay" id="edit-overlay">
|
|
1195
|
+
<div class="edit-modal">
|
|
1196
|
+
<div class="edit-header">
|
|
1197
|
+
<span class="edit-path" id="edit-path"></span>
|
|
1198
|
+
<div class="edit-actions">
|
|
1199
|
+
<button class="edit-btn cancel" id="edit-cancel">ESC</button>
|
|
1200
|
+
<button class="edit-btn save" id="edit-save">SAVE</button>
|
|
1201
|
+
</div>
|
|
1202
|
+
</div>
|
|
1203
|
+
<textarea class="edit-textarea" id="edit-textarea" placeholder="Write markdown..."></textarea>
|
|
1204
|
+
</div>
|
|
1205
|
+
</div>
|
|
1206
|
+
|
|
1207
|
+
<!-- Quick Switcher Overlay -->
|
|
1208
|
+
<div class="quick-switcher-overlay" id="qs-overlay">
|
|
1209
|
+
<div class="quick-switcher">
|
|
1210
|
+
<input type="text" id="qs-input" placeholder="Jump to note...">
|
|
1211
|
+
<div class="quick-switcher-results" id="qs-results"></div>
|
|
881
1212
|
</div>
|
|
882
1213
|
</div>
|
|
883
1214
|
|
|
@@ -886,6 +1217,8 @@ let currentPath = null;
|
|
|
886
1217
|
let treeData = null;
|
|
887
1218
|
let allNotes = {};
|
|
888
1219
|
let graphVisible = true;
|
|
1220
|
+
let activeTagFilters = new Set();
|
|
1221
|
+
let qsSelectedIndex = 0;
|
|
889
1222
|
|
|
890
1223
|
async function fetchJSON(url) {
|
|
891
1224
|
const r = await fetch(url);
|
|
@@ -910,14 +1243,113 @@ document.getElementById('graph-toggle').addEventListener('click', () => {
|
|
|
910
1243
|
}
|
|
911
1244
|
});
|
|
912
1245
|
|
|
913
|
-
// --- Keyboard
|
|
1246
|
+
// --- Keyboard shortcuts ---
|
|
914
1247
|
document.addEventListener('keydown', (e) => {
|
|
915
1248
|
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
916
1249
|
e.preventDefault();
|
|
917
1250
|
document.getElementById('search-input').focus();
|
|
918
1251
|
}
|
|
1252
|
+
if ((e.metaKey || e.ctrlKey) && e.key === 'o') {
|
|
1253
|
+
e.preventDefault();
|
|
1254
|
+
openQuickSwitcher();
|
|
1255
|
+
}
|
|
1256
|
+
if (e.key === 'Escape') {
|
|
1257
|
+
closeQuickSwitcher();
|
|
1258
|
+
}
|
|
919
1259
|
});
|
|
920
1260
|
|
|
1261
|
+
// --- Quick Switcher ---
|
|
1262
|
+
function openQuickSwitcher() {
|
|
1263
|
+
const overlay = document.getElementById('qs-overlay');
|
|
1264
|
+
const input = document.getElementById('qs-input');
|
|
1265
|
+
overlay.classList.add('active');
|
|
1266
|
+
input.value = '';
|
|
1267
|
+
input.focus();
|
|
1268
|
+
qsSelectedIndex = 0;
|
|
1269
|
+
renderQsResults('');
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
function closeQuickSwitcher() {
|
|
1273
|
+
document.getElementById('qs-overlay').classList.remove('active');
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
document.getElementById('qs-overlay').addEventListener('click', (e) => {
|
|
1277
|
+
if (e.target === e.currentTarget) closeQuickSwitcher();
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
document.getElementById('qs-input').addEventListener('input', (e) => {
|
|
1281
|
+
qsSelectedIndex = 0;
|
|
1282
|
+
renderQsResults(e.target.value.trim().toLowerCase());
|
|
1283
|
+
});
|
|
1284
|
+
|
|
1285
|
+
document.getElementById('qs-input').addEventListener('keydown', (e) => {
|
|
1286
|
+
const items = document.querySelectorAll('.qs-item');
|
|
1287
|
+
if (e.key === 'ArrowDown') {
|
|
1288
|
+
e.preventDefault();
|
|
1289
|
+
qsSelectedIndex = Math.min(qsSelectedIndex + 1, items.length - 1);
|
|
1290
|
+
updateQsSelection();
|
|
1291
|
+
} else if (e.key === 'ArrowUp') {
|
|
1292
|
+
e.preventDefault();
|
|
1293
|
+
qsSelectedIndex = Math.max(qsSelectedIndex - 1, 0);
|
|
1294
|
+
updateQsSelection();
|
|
1295
|
+
} else if (e.key === 'Enter') {
|
|
1296
|
+
e.preventDefault();
|
|
1297
|
+
const selected = items[qsSelectedIndex];
|
|
1298
|
+
if (selected) {
|
|
1299
|
+
loadNote(selected.dataset.path);
|
|
1300
|
+
closeQuickSwitcher();
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
|
|
1305
|
+
function renderQsResults(query) {
|
|
1306
|
+
const container = document.getElementById('qs-results');
|
|
1307
|
+
const entries = Object.entries(allNotes);
|
|
1308
|
+
|
|
1309
|
+
let filtered = entries;
|
|
1310
|
+
if (query) {
|
|
1311
|
+
filtered = entries.filter(([path, note]) => {
|
|
1312
|
+
const name = note.title.toLowerCase();
|
|
1313
|
+
const p = path.toLowerCase();
|
|
1314
|
+
return name.includes(query) || p.includes(query);
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
filtered.sort((a, b) => a[1].title.localeCompare(b[1].title));
|
|
1319
|
+
filtered = filtered.slice(0, 15);
|
|
1320
|
+
|
|
1321
|
+
if (filtered.length === 0) {
|
|
1322
|
+
container.innerHTML = '<div class="qs-empty">No notes found</div>';
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
container.innerHTML = filtered.map(([path, note], i) => {
|
|
1327
|
+
const folder = path.includes('/') ? path.split('/').slice(0, -1).join('/') : '';
|
|
1328
|
+
return `<div class="qs-item${i === qsSelectedIndex ? ' selected' : ''}" data-path="${path}">
|
|
1329
|
+
<span class="qs-icon">◇</span>
|
|
1330
|
+
<span class="qs-name">${note.title}</span>
|
|
1331
|
+
${folder ? `<span class="qs-path">${folder}</span>` : ''}
|
|
1332
|
+
</div>`;
|
|
1333
|
+
}).join('');
|
|
1334
|
+
|
|
1335
|
+
container.querySelectorAll('.qs-item').forEach((el, i) => {
|
|
1336
|
+
el.addEventListener('click', () => {
|
|
1337
|
+
loadNote(el.dataset.path);
|
|
1338
|
+
closeQuickSwitcher();
|
|
1339
|
+
});
|
|
1340
|
+
el.addEventListener('mouseenter', () => {
|
|
1341
|
+
qsSelectedIndex = i;
|
|
1342
|
+
updateQsSelection();
|
|
1343
|
+
});
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
function updateQsSelection() {
|
|
1348
|
+
document.querySelectorAll('.qs-item').forEach((el, i) => {
|
|
1349
|
+
el.classList.toggle('selected', i === qsSelectedIndex);
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
|
|
921
1353
|
// --- File Tree ---
|
|
922
1354
|
function renderTree(node, container) {
|
|
923
1355
|
if (node.type === 'folder' && node.name !== 'vault') {
|
|
@@ -961,7 +1393,6 @@ async function loadNote(path) {
|
|
|
961
1393
|
el.classList.toggle('active', el.dataset.path === path);
|
|
962
1394
|
});
|
|
963
1395
|
|
|
964
|
-
// Breadcrumb
|
|
965
1396
|
const parts = path.replace('.md', '').split('/');
|
|
966
1397
|
document.getElementById('breadcrumb').innerHTML = parts.map((p, i) =>
|
|
967
1398
|
i < parts.length - 1
|
|
@@ -969,12 +1400,12 @@ async function loadNote(path) {
|
|
|
969
1400
|
: `<span class="current">${p}</span>`
|
|
970
1401
|
).join('');
|
|
971
1402
|
|
|
972
|
-
// Content
|
|
973
1403
|
const contentEl = document.getElementById('content');
|
|
974
1404
|
let html = '<div class="fade-in">';
|
|
975
1405
|
|
|
1406
|
+
html += `<button class="note-edit-btn" onclick="openEditor('${path}')">EDIT</button>`;
|
|
976
1407
|
html += '<div class="note-properties">';
|
|
977
|
-
(note.tags || []).forEach(t => { html += `<span class="tag">#${t}</span>`; });
|
|
1408
|
+
(note.tags || []).forEach(t => { html += `<span class="tag clickable-tag" data-tag="${t}">#${t}</span>`; });
|
|
978
1409
|
Object.entries(note.properties || {}).forEach(([k, v]) => {
|
|
979
1410
|
html += `<span class="prop-item"><span class="prop-key">${k}:</span> ${v}</span>`;
|
|
980
1411
|
});
|
|
@@ -1000,7 +1431,15 @@ async function loadNote(path) {
|
|
|
1000
1431
|
});
|
|
1001
1432
|
});
|
|
1002
1433
|
|
|
1434
|
+
contentEl.querySelectorAll('.clickable-tag').forEach(el => {
|
|
1435
|
+
el.addEventListener('click', () => {
|
|
1436
|
+
activeTagFilters.add(el.dataset.tag);
|
|
1437
|
+
applyTagFilter();
|
|
1438
|
+
});
|
|
1439
|
+
});
|
|
1440
|
+
|
|
1003
1441
|
renderRightPanel(note);
|
|
1442
|
+
renderOutline(note);
|
|
1004
1443
|
if (graphVisible) renderGraph(note);
|
|
1005
1444
|
}
|
|
1006
1445
|
|
|
@@ -1013,20 +1452,58 @@ function findNotePath(name) {
|
|
|
1013
1452
|
return null;
|
|
1014
1453
|
}
|
|
1015
1454
|
|
|
1455
|
+
// --- Outline ---
|
|
1456
|
+
function renderOutline(note) {
|
|
1457
|
+
const section = document.getElementById('rp-outline');
|
|
1458
|
+
const list = document.getElementById('rp-outline-list');
|
|
1459
|
+
list.innerHTML = '';
|
|
1460
|
+
|
|
1461
|
+
const content = note.content || '';
|
|
1462
|
+
const headings = [];
|
|
1463
|
+
content.split('\n').forEach(line => {
|
|
1464
|
+
const m = line.match(/^(#{1,3})\s+(.+)/);
|
|
1465
|
+
if (m) headings.push({ level: m[1].length, text: m[2].trim() });
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
if (headings.length < 2) {
|
|
1469
|
+
section.style.display = 'none';
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
section.style.display = '';
|
|
1474
|
+
document.getElementById('outline-count').textContent = headings.length;
|
|
1475
|
+
|
|
1476
|
+
headings.forEach(h => {
|
|
1477
|
+
const el = document.createElement('div');
|
|
1478
|
+
el.className = `outline-item h${h.level}`;
|
|
1479
|
+
el.textContent = h.text;
|
|
1480
|
+
el.addEventListener('click', () => {
|
|
1481
|
+
const contentEl = document.getElementById('content');
|
|
1482
|
+
const target = Array.from(contentEl.querySelectorAll('h1,h2,h3')).find(
|
|
1483
|
+
el => el.textContent.trim() === h.text
|
|
1484
|
+
);
|
|
1485
|
+
if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1486
|
+
});
|
|
1487
|
+
list.appendChild(el);
|
|
1488
|
+
});
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1016
1491
|
// --- Right Panel ---
|
|
1017
1492
|
function renderRightPanel(note) {
|
|
1018
1493
|
const blSection = document.getElementById('rp-backlinks');
|
|
1019
1494
|
const blList = document.getElementById('rp-backlinks-list');
|
|
1020
1495
|
blList.innerHTML = '';
|
|
1021
|
-
|
|
1496
|
+
const backlinks = note.backlinks || [];
|
|
1497
|
+
if (backlinks.length) {
|
|
1022
1498
|
blSection.style.display = '';
|
|
1023
|
-
document.getElementById('bl-count').textContent =
|
|
1024
|
-
|
|
1025
|
-
const n = allNotes[path];
|
|
1499
|
+
document.getElementById('bl-count').textContent = backlinks.length;
|
|
1500
|
+
backlinks.forEach(bl => {
|
|
1026
1501
|
const item = document.createElement('div');
|
|
1027
|
-
item.className = 'rp-item';
|
|
1028
|
-
|
|
1029
|
-
|
|
1502
|
+
item.className = 'rp-item-col';
|
|
1503
|
+
let html = `<span class="rp-title rp-backlink-title" style="font-size:11px">${bl.title || bl.path || bl}</span>`;
|
|
1504
|
+
if (bl.context) html += `<span class="rp-context">${bl.context}</span>`;
|
|
1505
|
+
item.innerHTML = html;
|
|
1506
|
+
item.addEventListener('click', () => loadNote(bl.path || bl));
|
|
1030
1507
|
blList.appendChild(item);
|
|
1031
1508
|
});
|
|
1032
1509
|
} else {
|
|
@@ -1062,14 +1539,86 @@ function renderRightPanel(note) {
|
|
|
1062
1539
|
item.className = 'rp-item';
|
|
1063
1540
|
item.innerHTML = `<span class="rp-title">${link}</span>`;
|
|
1064
1541
|
if (path) item.addEventListener('click', () => loadNote(path));
|
|
1065
|
-
else item.style.opacity = '0.
|
|
1542
|
+
else item.style.opacity = '0.3';
|
|
1066
1543
|
outList.appendChild(item);
|
|
1067
1544
|
});
|
|
1068
1545
|
} else {
|
|
1069
1546
|
outSection.style.display = 'none';
|
|
1070
1547
|
}
|
|
1548
|
+
|
|
1549
|
+
const ulSection = document.getElementById('rp-unlinked');
|
|
1550
|
+
const ulList = document.getElementById('rp-unlinked-list');
|
|
1551
|
+
ulList.innerHTML = '';
|
|
1552
|
+
const unlinked = note.unlinked || [];
|
|
1553
|
+
if (unlinked.length) {
|
|
1554
|
+
ulSection.style.display = '';
|
|
1555
|
+
document.getElementById('unlinked-count').textContent = unlinked.length;
|
|
1556
|
+
unlinked.forEach(u => {
|
|
1557
|
+
const item = document.createElement('div');
|
|
1558
|
+
item.className = 'rp-item-col';
|
|
1559
|
+
let html = `<span class="rp-title" style="font-size:11px;color:var(--text-secondary)">${u.title}</span>`;
|
|
1560
|
+
if (u.context) html += `<span class="rp-context">${u.context}</span>`;
|
|
1561
|
+
item.innerHTML = html;
|
|
1562
|
+
item.addEventListener('click', () => loadNote(u.path));
|
|
1563
|
+
ulList.appendChild(item);
|
|
1564
|
+
});
|
|
1565
|
+
} else {
|
|
1566
|
+
ulSection.style.display = 'none';
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
// --- Editor ---
|
|
1571
|
+
let editingPath = null;
|
|
1572
|
+
let editingNote = null;
|
|
1573
|
+
|
|
1574
|
+
async function openEditor(path) {
|
|
1575
|
+
const note = await fetchJSON(`/api/note/${path}`);
|
|
1576
|
+
if (note.error) return;
|
|
1577
|
+
editingPath = path;
|
|
1578
|
+
editingNote = note;
|
|
1579
|
+
document.getElementById('edit-path').textContent = path;
|
|
1580
|
+
document.getElementById('edit-textarea').value = note.content || '';
|
|
1581
|
+
document.getElementById('edit-overlay').classList.add('active');
|
|
1582
|
+
document.getElementById('edit-textarea').focus();
|
|
1071
1583
|
}
|
|
1072
1584
|
|
|
1585
|
+
document.getElementById('edit-cancel').addEventListener('click', closeEditor);
|
|
1586
|
+
document.getElementById('edit-overlay').addEventListener('click', (e) => {
|
|
1587
|
+
if (e.target === e.currentTarget) closeEditor();
|
|
1588
|
+
});
|
|
1589
|
+
|
|
1590
|
+
document.getElementById('edit-save').addEventListener('click', async () => {
|
|
1591
|
+
if (!editingPath) return;
|
|
1592
|
+
const content = document.getElementById('edit-textarea').value;
|
|
1593
|
+
await fetch(`/api/note/${editingPath}`, {
|
|
1594
|
+
method: 'POST',
|
|
1595
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1596
|
+
body: JSON.stringify({
|
|
1597
|
+
content,
|
|
1598
|
+
tags: editingNote.tags || [],
|
|
1599
|
+
properties: editingNote.properties || {},
|
|
1600
|
+
}),
|
|
1601
|
+
});
|
|
1602
|
+
closeEditor();
|
|
1603
|
+
await loadNote(editingPath);
|
|
1604
|
+
});
|
|
1605
|
+
|
|
1606
|
+
function closeEditor() {
|
|
1607
|
+
document.getElementById('edit-overlay').classList.remove('active');
|
|
1608
|
+
editingPath = null;
|
|
1609
|
+
editingNote = null;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
document.addEventListener('keydown', (e) => {
|
|
1613
|
+
if (e.key === 'Escape' && document.getElementById('edit-overlay').classList.contains('active')) {
|
|
1614
|
+
closeEditor();
|
|
1615
|
+
}
|
|
1616
|
+
if ((e.metaKey || e.ctrlKey) && e.key === 's' && editingPath) {
|
|
1617
|
+
e.preventDefault();
|
|
1618
|
+
document.getElementById('edit-save').click();
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
|
|
1073
1622
|
// --- Graph ---
|
|
1074
1623
|
function renderGraph(note) {
|
|
1075
1624
|
const container = document.getElementById('graph-container');
|
|
@@ -1115,16 +1664,11 @@ function renderGraph(note) {
|
|
|
1115
1664
|
const svg = d3.select(container).append('svg')
|
|
1116
1665
|
.attr('viewBox', `0 0 ${width} ${height}`);
|
|
1117
1666
|
|
|
1118
|
-
const defs = svg.append('defs');
|
|
1119
|
-
const grad = defs.append('radialGradient').attr('id', 'node-glow');
|
|
1120
|
-
grad.append('stop').attr('offset', '0%').attr('stop-color', 'var(--neon-cyan)').attr('stop-opacity', 0.3);
|
|
1121
|
-
grad.append('stop').attr('offset', '100%').attr('stop-color', 'var(--neon-cyan)').attr('stop-opacity', 0);
|
|
1122
|
-
|
|
1123
1667
|
const simulation = d3.forceSimulation(nodeArray)
|
|
1124
|
-
.force('link', d3.forceLink(links).id(d => d.id).distance(
|
|
1125
|
-
.force('charge', d3.forceManyBody().strength(-
|
|
1668
|
+
.force('link', d3.forceLink(links).id(d => d.id).distance(50))
|
|
1669
|
+
.force('charge', d3.forceManyBody().strength(-100))
|
|
1126
1670
|
.force('center', d3.forceCenter(width / 2, height / 2))
|
|
1127
|
-
.force('collision', d3.forceCollide().radius(
|
|
1671
|
+
.force('collision', d3.forceCollide().radius(22));
|
|
1128
1672
|
|
|
1129
1673
|
const link = svg.selectAll('.graph-link')
|
|
1130
1674
|
.data(links).enter().append('line')
|
|
@@ -1140,9 +1684,8 @@ function renderGraph(note) {
|
|
|
1140
1684
|
.on('end', (e, d) => { if (!e.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; })
|
|
1141
1685
|
);
|
|
1142
1686
|
|
|
1143
|
-
node.
|
|
1144
|
-
node.append('
|
|
1145
|
-
node.append('text').text(d => d.title).attr('dx', 12).attr('dy', 3);
|
|
1687
|
+
node.append('circle').attr('r', d => d.active ? 5 : 3.5);
|
|
1688
|
+
node.append('text').text(d => d.title).attr('dx', 10).attr('dy', 3);
|
|
1146
1689
|
|
|
1147
1690
|
simulation.on('tick', () => {
|
|
1148
1691
|
link
|
|
@@ -1195,14 +1738,113 @@ document.addEventListener('click', (e) => {
|
|
|
1195
1738
|
if (!e.target.closest('.search-box')) searchResults.classList.remove('active');
|
|
1196
1739
|
});
|
|
1197
1740
|
|
|
1741
|
+
// --- Tag Filter ---
|
|
1742
|
+
document.getElementById('tag-filter-toggle').addEventListener('click', () => {
|
|
1743
|
+
const body = document.getElementById('tag-filter-body');
|
|
1744
|
+
const arrow = document.getElementById('tag-arrow');
|
|
1745
|
+
body.classList.toggle('collapsed');
|
|
1746
|
+
arrow.classList.toggle('open');
|
|
1747
|
+
});
|
|
1748
|
+
|
|
1749
|
+
document.getElementById('clear-filters').addEventListener('click', () => {
|
|
1750
|
+
activeTagFilters.clear();
|
|
1751
|
+
applyTagFilter();
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1754
|
+
function renderTagCloud(tags) {
|
|
1755
|
+
const cloud = document.getElementById('tag-cloud');
|
|
1756
|
+
cloud.innerHTML = '';
|
|
1757
|
+
const sorted = Object.entries(tags).sort((a, b) => b[1] - a[1]);
|
|
1758
|
+
sorted.forEach(([tag, count]) => {
|
|
1759
|
+
const chip = document.createElement('span');
|
|
1760
|
+
chip.className = 'tag-chip' + (activeTagFilters.has(tag) ? ' selected' : '');
|
|
1761
|
+
chip.innerHTML = `#${tag}<span class="tag-count">${count}</span>`;
|
|
1762
|
+
chip.addEventListener('click', () => {
|
|
1763
|
+
if (activeTagFilters.has(tag)) {
|
|
1764
|
+
activeTagFilters.delete(tag);
|
|
1765
|
+
} else {
|
|
1766
|
+
activeTagFilters.add(tag);
|
|
1767
|
+
}
|
|
1768
|
+
applyTagFilter();
|
|
1769
|
+
});
|
|
1770
|
+
cloud.appendChild(chip);
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
function applyTagFilter() {
|
|
1775
|
+
const activeEl = document.getElementById('active-tags');
|
|
1776
|
+
const filterInfo = document.getElementById('filter-info');
|
|
1777
|
+
const filterCount = document.getElementById('filter-count');
|
|
1778
|
+
|
|
1779
|
+
activeEl.innerHTML = '';
|
|
1780
|
+
activeTagFilters.forEach(tag => {
|
|
1781
|
+
const el = document.createElement('span');
|
|
1782
|
+
el.className = 'active-tag';
|
|
1783
|
+
el.innerHTML = `#${tag}<span class="remove">×</span>`;
|
|
1784
|
+
el.addEventListener('click', () => {
|
|
1785
|
+
activeTagFilters.delete(tag);
|
|
1786
|
+
applyTagFilter();
|
|
1787
|
+
});
|
|
1788
|
+
activeEl.appendChild(el);
|
|
1789
|
+
});
|
|
1790
|
+
|
|
1791
|
+
document.querySelectorAll('.tag-chip').forEach(chip => {
|
|
1792
|
+
const tag = chip.textContent.replace('#', '').replace(/\d+$/, '');
|
|
1793
|
+
chip.classList.toggle('selected', activeTagFilters.has(tag));
|
|
1794
|
+
});
|
|
1795
|
+
|
|
1796
|
+
const treeItems = document.querySelectorAll('.tree-item[data-path]');
|
|
1797
|
+
let visibleCount = 0;
|
|
1798
|
+
|
|
1799
|
+
if (activeTagFilters.size === 0) {
|
|
1800
|
+
treeItems.forEach(el => { el.style.display = ''; });
|
|
1801
|
+
document.querySelectorAll('.tree-children').forEach(el => el.classList.remove('collapsed'));
|
|
1802
|
+
filterInfo.style.display = 'none';
|
|
1803
|
+
renderTagCloud(collectAllTags());
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
const matchingPaths = new Set();
|
|
1808
|
+
|
|
1809
|
+
for (const [path, note] of Object.entries(allNotes)) {
|
|
1810
|
+
const noteTags = (note.tags || []).map(t => t.toLowerCase());
|
|
1811
|
+
const matches = [...activeTagFilters].every(f => noteTags.includes(f.toLowerCase()));
|
|
1812
|
+
if (matches) matchingPaths.add(path);
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
treeItems.forEach(el => {
|
|
1816
|
+
const path = el.dataset.path;
|
|
1817
|
+
if (matchingPaths.has(path)) {
|
|
1818
|
+
el.style.display = '';
|
|
1819
|
+
visibleCount++;
|
|
1820
|
+
} else {
|
|
1821
|
+
el.style.display = 'none';
|
|
1822
|
+
}
|
|
1823
|
+
});
|
|
1824
|
+
|
|
1825
|
+
document.querySelectorAll('.tree-children').forEach(el => el.classList.remove('collapsed'));
|
|
1826
|
+
|
|
1827
|
+
filterInfo.style.display = '';
|
|
1828
|
+
filterCount.textContent = `${visibleCount} note${visibleCount !== 1 ? 's' : ''}`;
|
|
1829
|
+
renderTagCloud(collectAllTags());
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
function collectAllTags() {
|
|
1833
|
+
const tags = {};
|
|
1834
|
+
for (const note of Object.values(allNotes)) {
|
|
1835
|
+
(note.tags || []).forEach(t => { tags[t] = (tags[t] || 0) + 1; });
|
|
1836
|
+
}
|
|
1837
|
+
return tags;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1198
1840
|
// --- Resizable Panels ---
|
|
1199
1841
|
function initResize() {
|
|
1200
1842
|
const layout = document.getElementById('layout');
|
|
1201
1843
|
const leftHandle = document.getElementById('resize-left');
|
|
1202
1844
|
const rightHandle = document.getElementById('resize-right');
|
|
1203
1845
|
|
|
1204
|
-
let sidebarW = parseInt(localStorage.getItem('kyp-sidebar-w')) ||
|
|
1205
|
-
let rightW = parseInt(localStorage.getItem('kyp-right-w')) ||
|
|
1846
|
+
let sidebarW = parseInt(localStorage.getItem('kyp-sidebar-w')) || 256;
|
|
1847
|
+
let rightW = parseInt(localStorage.getItem('kyp-right-w')) || 272;
|
|
1206
1848
|
|
|
1207
1849
|
layout.style.setProperty('--sidebar-w', sidebarW + 'px');
|
|
1208
1850
|
layout.style.setProperty('--right-w', rightW + 'px');
|
|
@@ -1242,7 +1884,7 @@ function initResize() {
|
|
|
1242
1884
|
save: () => localStorage.setItem('kyp-sidebar-w', sidebarW),
|
|
1243
1885
|
invert: false,
|
|
1244
1886
|
min: 180,
|
|
1245
|
-
max:
|
|
1887
|
+
max: 400,
|
|
1246
1888
|
});
|
|
1247
1889
|
|
|
1248
1890
|
makeDraggable(rightHandle, {
|
|
@@ -1251,7 +1893,7 @@ function initResize() {
|
|
|
1251
1893
|
save: () => localStorage.setItem('kyp-right-w', rightW),
|
|
1252
1894
|
invert: true,
|
|
1253
1895
|
min: 200,
|
|
1254
|
-
max:
|
|
1896
|
+
max: 450,
|
|
1255
1897
|
});
|
|
1256
1898
|
}
|
|
1257
1899
|
|
|
@@ -1277,6 +1919,7 @@ async function init() {
|
|
|
1277
1919
|
await Promise.all(promises);
|
|
1278
1920
|
|
|
1279
1921
|
renderTree(treeData, document.getElementById('file-tree'));
|
|
1922
|
+
renderTagCloud(collectAllTags());
|
|
1280
1923
|
|
|
1281
1924
|
document.getElementById('stats-bar').innerHTML = `
|
|
1282
1925
|
<span><span class="stat-val">${stats.notes}</span> notes</span>
|