@oimdb/mcp 1.2.0 → 3.0.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 +25 -129
- package/bin/oimdb-mcp.cjs +13 -14
- package/bin/server.cjs +10 -1
- package/dist/index.cjs +32 -305
- package/dist/index.d.cts +13 -65
- package/dist/index.d.ts +13 -65
- package/dist/index.js +37 -302
- package/package.json +15 -8
- package/bin/cdp.cjs +0 -98
- package/bin/devtools.cjs +0 -17
- package/ui/app.css +0 -323
- package/ui/app.js +0 -409
- package/ui/index.html +0 -63
package/bin/cdp.cjs
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One-shot CDP inspector: connects to Chrome, evaluates __OIMDB_DEV__.inspect(),
|
|
3
|
-
* prints JSON to stdout. Pipe to jq or paste into an AI prompt.
|
|
4
|
-
*
|
|
5
|
-
* Requirements:
|
|
6
|
-
* Launch Chrome with: --remote-debugging-port=9222
|
|
7
|
-
* (or set CDP_URL env var to point to a different address)
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* npx @oimdb/mcp cdp
|
|
11
|
-
* OIMDB_CDP_URL=http://localhost:9222 npx @oimdb/mcp cdp
|
|
12
|
-
* npx @oimdb/mcp cdp | jq .collections
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const cdpBase = process.env.OIMDB_CDP_URL || 'http://localhost:9222';
|
|
16
|
-
|
|
17
|
-
async function run() {
|
|
18
|
-
// 1. List open tabs
|
|
19
|
-
let tabs;
|
|
20
|
-
try {
|
|
21
|
-
const res = await fetch(`${cdpBase}/json/list`);
|
|
22
|
-
tabs = await res.json();
|
|
23
|
-
} catch {
|
|
24
|
-
process.stderr.write(
|
|
25
|
-
`[OIMDB CDP] Cannot reach Chrome at ${cdpBase}\n` +
|
|
26
|
-
`Launch Chrome with: --remote-debugging-port=9222\n`
|
|
27
|
-
);
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Find first tab that has a debugger URL
|
|
32
|
-
const tab = tabs.find((t) => t.webSocketDebuggerUrl);
|
|
33
|
-
if (!tab) {
|
|
34
|
-
process.stderr.write('[OIMDB CDP] No debuggable tabs found.\n');
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
process.stderr.write(`[OIMDB CDP] Connected to: ${tab.title} (${tab.url})\n`);
|
|
39
|
-
|
|
40
|
-
// 2. Open CDP WebSocket
|
|
41
|
-
const { WebSocket } = await import('ws');
|
|
42
|
-
const ws = new WebSocket(tab.webSocketDebuggerUrl);
|
|
43
|
-
|
|
44
|
-
await new Promise((resolve, reject) => {
|
|
45
|
-
const timeout = setTimeout(() => {
|
|
46
|
-
ws.close();
|
|
47
|
-
reject(new Error('CDP timeout (5s)'));
|
|
48
|
-
}, 5000);
|
|
49
|
-
|
|
50
|
-
ws.once('open', () => {
|
|
51
|
-
ws.send(JSON.stringify({
|
|
52
|
-
id: 1,
|
|
53
|
-
method: 'Runtime.evaluate',
|
|
54
|
-
params: {
|
|
55
|
-
expression: [
|
|
56
|
-
'(function(){',
|
|
57
|
-
' if(!window.__OIMDB_DEV__) return null;',
|
|
58
|
-
' return JSON.parse(JSON.stringify(window.__OIMDB_DEV__.inspect()));',
|
|
59
|
-
'})()',
|
|
60
|
-
].join(''),
|
|
61
|
-
returnByValue: true,
|
|
62
|
-
awaitPromise: false,
|
|
63
|
-
},
|
|
64
|
-
}));
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
ws.on('message', (raw) => {
|
|
68
|
-
const msg = JSON.parse(raw.toString());
|
|
69
|
-
if (msg.id !== 1) return;
|
|
70
|
-
clearTimeout(timeout);
|
|
71
|
-
ws.close();
|
|
72
|
-
|
|
73
|
-
const val = msg.result?.result?.value;
|
|
74
|
-
if (val === null || val === undefined) {
|
|
75
|
-
process.stderr.write(
|
|
76
|
-
'[OIMDB CDP] __OIMDB_DEV__ not found on this page.\n' +
|
|
77
|
-
'Make sure debug.ts sets: window.__OIMDB_DEV__ = registry\n'
|
|
78
|
-
);
|
|
79
|
-
process.exit(1);
|
|
80
|
-
}
|
|
81
|
-
process.stdout.write(JSON.stringify(val, null, 2) + '\n');
|
|
82
|
-
resolve(undefined);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
ws.once('error', (err) => {
|
|
86
|
-
clearTimeout(timeout);
|
|
87
|
-
reject(err);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** Run the one-shot CDP snapshot (`cdp` subcommand). */
|
|
93
|
-
module.exports = function runCdp() {
|
|
94
|
-
run().catch((err) => {
|
|
95
|
-
process.stderr.write('[OIMDB CDP] Error: ' + err.message + '\n');
|
|
96
|
-
process.exit(1);
|
|
97
|
-
});
|
|
98
|
-
};
|
package/bin/devtools.cjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const { OIMDevUIServer } = require('../dist/index.cjs');
|
|
3
|
-
|
|
4
|
-
/** Start the standalone DevTools UI server (`devtools` subcommand). */
|
|
5
|
-
module.exports = function runDevtools() {
|
|
6
|
-
const wsPort = process.env.OIMDB_WS_PORT
|
|
7
|
-
? Number(process.env.OIMDB_WS_PORT)
|
|
8
|
-
: 7432;
|
|
9
|
-
const uiPort = process.env.OIMDB_UI_PORT
|
|
10
|
-
? Number(process.env.OIMDB_UI_PORT)
|
|
11
|
-
: 7433;
|
|
12
|
-
const noOpen = process.argv.includes('--no-open');
|
|
13
|
-
const uiDir = path.join(__dirname, '../ui');
|
|
14
|
-
|
|
15
|
-
const server = new OIMDevUIServer({ wsPort, uiPort, uiDir, open: !noOpen });
|
|
16
|
-
server.start();
|
|
17
|
-
};
|
package/ui/app.css
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
2
|
-
|
|
3
|
-
:root {
|
|
4
|
-
--bg: #1e1e1e;
|
|
5
|
-
--bg-panel: #252526;
|
|
6
|
-
--bg-row: #2a2a2a;
|
|
7
|
-
--bg-hover: #2e2e2e;
|
|
8
|
-
--bg-input: #3c3c3c;
|
|
9
|
-
--border: #3e3e42;
|
|
10
|
-
--text: #d4d4d4;
|
|
11
|
-
--text-dim: #808080;
|
|
12
|
-
--text-hi: #f0f0f0;
|
|
13
|
-
--accent: #4fc3f7;
|
|
14
|
-
--green: #4caf50;
|
|
15
|
-
--yellow: #ffb74d;
|
|
16
|
-
--red: #ef5350;
|
|
17
|
-
--gray: #616161;
|
|
18
|
-
--tag-bg: #2d3f4a;
|
|
19
|
-
--tag-warn: #4a2d2d;
|
|
20
|
-
--radius: 4px;
|
|
21
|
-
--mono: 'Menlo', 'Consolas', 'DejaVu Sans Mono', monospace;
|
|
22
|
-
--toolbar-h: 40px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
html, body {
|
|
26
|
-
height: 100%;
|
|
27
|
-
background: var(--bg);
|
|
28
|
-
color: var(--text);
|
|
29
|
-
font: 13px/1.5 -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
30
|
-
overflow: hidden;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/* ── Toolbar ──────────────────────────────────── */
|
|
34
|
-
|
|
35
|
-
#toolbar {
|
|
36
|
-
display: flex;
|
|
37
|
-
align-items: center;
|
|
38
|
-
gap: 16px;
|
|
39
|
-
height: var(--toolbar-h);
|
|
40
|
-
padding: 0 16px;
|
|
41
|
-
background: var(--bg-panel);
|
|
42
|
-
border-bottom: 1px solid var(--border);
|
|
43
|
-
flex-shrink: 0;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.toolbar-brand { display: flex; align-items: baseline; gap: 6px; }
|
|
47
|
-
.brand-name { font-weight: 700; font-size: 15px; color: var(--accent); letter-spacing: -0.3px; }
|
|
48
|
-
.brand-sub { font-size: 11px; color: var(--text-dim); }
|
|
49
|
-
|
|
50
|
-
.toolbar-status { display: flex; align-items: center; gap: 7px; flex: 1; }
|
|
51
|
-
|
|
52
|
-
.conn-dot {
|
|
53
|
-
width: 8px; height: 8px; border-radius: 50%;
|
|
54
|
-
background: var(--gray); flex-shrink: 0;
|
|
55
|
-
transition: background 0.3s;
|
|
56
|
-
}
|
|
57
|
-
.conn-dot.connected { background: var(--green); }
|
|
58
|
-
.conn-dot.disconnected { background: var(--gray); }
|
|
59
|
-
|
|
60
|
-
#conn-label { font-size: 12px; color: var(--text-dim); }
|
|
61
|
-
|
|
62
|
-
.toolbar-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
|
|
63
|
-
#last-updated { font-size: 11px; color: var(--text-dim); }
|
|
64
|
-
|
|
65
|
-
#btn-refresh {
|
|
66
|
-
background: none; border: 1px solid var(--border); border-radius: var(--radius);
|
|
67
|
-
color: var(--text); cursor: pointer; font-size: 16px; line-height: 1;
|
|
68
|
-
padding: 2px 8px; transition: background 0.15s;
|
|
69
|
-
}
|
|
70
|
-
#btn-refresh:hover { background: var(--bg-input); }
|
|
71
|
-
|
|
72
|
-
.auto-label {
|
|
73
|
-
display: flex; align-items: center; gap: 5px;
|
|
74
|
-
font-size: 12px; color: var(--text-dim); cursor: pointer; user-select: none;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* ── Screens ──────────────────────────────────── */
|
|
78
|
-
|
|
79
|
-
.hidden { display: none !important; }
|
|
80
|
-
|
|
81
|
-
#screen-waiting {
|
|
82
|
-
height: calc(100vh - var(--toolbar-h));
|
|
83
|
-
display: flex; align-items: center; justify-content: center;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.waiting-card {
|
|
87
|
-
max-width: 420px; padding: 28px 32px;
|
|
88
|
-
background: var(--bg-panel); border: 1px solid var(--border);
|
|
89
|
-
border-radius: 8px; text-align: center;
|
|
90
|
-
}
|
|
91
|
-
.waiting-title { font-size: 18px; font-weight: 600; color: var(--accent); margin-bottom: 14px; }
|
|
92
|
-
.waiting-card p { color: var(--text-dim); margin-bottom: 10px; line-height: 1.6; }
|
|
93
|
-
.waiting-card code {
|
|
94
|
-
font-family: var(--mono); background: var(--bg-input);
|
|
95
|
-
padding: 2px 6px; border-radius: 3px; color: var(--accent);
|
|
96
|
-
}
|
|
97
|
-
.waiting-card pre {
|
|
98
|
-
font-family: var(--mono); font-size: 12px;
|
|
99
|
-
background: var(--bg-row); border: 1px solid var(--border);
|
|
100
|
-
border-radius: var(--radius); padding: 10px 14px;
|
|
101
|
-
margin: 10px 0; text-align: left; color: var(--text);
|
|
102
|
-
}
|
|
103
|
-
.waiting-hint { font-size: 12px !important; }
|
|
104
|
-
|
|
105
|
-
/* ── Two-column main ──────────────────────────── */
|
|
106
|
-
|
|
107
|
-
#screen-main {
|
|
108
|
-
display: flex;
|
|
109
|
-
height: calc(100vh - var(--toolbar-h));
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.col {
|
|
113
|
-
flex: 1; display: flex; flex-direction: column;
|
|
114
|
-
min-width: 0; overflow: hidden;
|
|
115
|
-
border-right: 1px solid var(--border);
|
|
116
|
-
}
|
|
117
|
-
.col:last-child { border-right: none; }
|
|
118
|
-
|
|
119
|
-
/* Right column split into computeds + history */
|
|
120
|
-
#col-right { flex-direction: column; }
|
|
121
|
-
|
|
122
|
-
.col-section {
|
|
123
|
-
display: flex; flex-direction: column;
|
|
124
|
-
flex: 1; min-height: 0; overflow: hidden;
|
|
125
|
-
border-bottom: 1px solid var(--border);
|
|
126
|
-
}
|
|
127
|
-
.col-section:last-child { border-bottom: none; }
|
|
128
|
-
|
|
129
|
-
.col-section-history { flex: 0 0 220px; }
|
|
130
|
-
|
|
131
|
-
.col-body-flex { flex: 1; min-height: 0; overflow-y: auto; }
|
|
132
|
-
|
|
133
|
-
.col-header {
|
|
134
|
-
display: flex; align-items: center; gap: 7px;
|
|
135
|
-
height: 32px; padding: 0 14px; flex-shrink: 0;
|
|
136
|
-
background: var(--bg-panel); border-bottom: 1px solid var(--border);
|
|
137
|
-
font-size: 11px; font-weight: 700; text-transform: uppercase;
|
|
138
|
-
letter-spacing: 0.06em; color: var(--text-dim);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.badge {
|
|
142
|
-
background: var(--bg-input); color: var(--text-dim);
|
|
143
|
-
border-radius: 10px; padding: 0 7px;
|
|
144
|
-
font-size: 10px; font-weight: 700; letter-spacing: 0;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.col-body { overflow-y: auto; flex: 1; }
|
|
148
|
-
|
|
149
|
-
/* ── Collection rows ──────────────────────────── */
|
|
150
|
-
|
|
151
|
-
.c-row { border-bottom: 1px solid var(--border); }
|
|
152
|
-
|
|
153
|
-
.c-summary {
|
|
154
|
-
display: flex; align-items: center; gap: 8px;
|
|
155
|
-
padding: 7px 14px; cursor: pointer; user-select: none;
|
|
156
|
-
background: var(--bg-row); transition: background 0.1s;
|
|
157
|
-
}
|
|
158
|
-
.c-summary:hover { background: var(--bg-hover); }
|
|
159
|
-
|
|
160
|
-
.c-arrow {
|
|
161
|
-
font-size: 9px; color: var(--text-dim); width: 10px;
|
|
162
|
-
transition: transform 0.15s; flex-shrink: 0;
|
|
163
|
-
}
|
|
164
|
-
.c-arrow.open { transform: rotate(90deg); }
|
|
165
|
-
|
|
166
|
-
.c-name {
|
|
167
|
-
font-family: var(--mono); font-size: 13px;
|
|
168
|
-
font-weight: 600; color: var(--text-hi); flex: 1;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
.c-count { font-size: 11px; color: var(--text-dim); }
|
|
172
|
-
|
|
173
|
-
.c-detail {
|
|
174
|
-
display: none; padding: 8px 14px 0 32px;
|
|
175
|
-
background: var(--bg); border-top: 1px solid var(--border);
|
|
176
|
-
font-size: 11px; font-family: var(--mono);
|
|
177
|
-
}
|
|
178
|
-
.c-detail.open { display: block; }
|
|
179
|
-
|
|
180
|
-
.d-row {
|
|
181
|
-
display: flex; gap: 8px; margin-bottom: 4px;
|
|
182
|
-
flex-wrap: wrap; align-items: flex-start;
|
|
183
|
-
}
|
|
184
|
-
.d-label { color: var(--text-dim); min-width: 72px; flex-shrink: 0; }
|
|
185
|
-
|
|
186
|
-
.tag {
|
|
187
|
-
display: inline-block; background: var(--tag-bg);
|
|
188
|
-
color: var(--text); border-radius: 3px;
|
|
189
|
-
padding: 1px 7px; margin: 1px 2px 1px 0; font-size: 11px;
|
|
190
|
-
}
|
|
191
|
-
.tag-warn { background: var(--tag-warn); color: #ffaa80; }
|
|
192
|
-
.tag-rel-arrow { color: var(--accent); margin: 0 3px; }
|
|
193
|
-
|
|
194
|
-
/* ── Entity table ─────────────────────────────── */
|
|
195
|
-
|
|
196
|
-
.entity-wrap {
|
|
197
|
-
margin: 8px 0 0 -18px;
|
|
198
|
-
border-top: 1px solid var(--border);
|
|
199
|
-
padding: 8px 0 10px 0;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.entity-table-wrap {
|
|
203
|
-
overflow-x: auto;
|
|
204
|
-
max-height: 280px;
|
|
205
|
-
overflow-y: auto;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.entity-table {
|
|
209
|
-
width: 100%;
|
|
210
|
-
border-collapse: collapse;
|
|
211
|
-
font-size: 11px;
|
|
212
|
-
font-family: var(--mono);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
.entity-table th {
|
|
216
|
-
position: sticky; top: 0;
|
|
217
|
-
background: var(--bg-panel);
|
|
218
|
-
color: var(--text-dim);
|
|
219
|
-
font-weight: 600;
|
|
220
|
-
text-align: left;
|
|
221
|
-
padding: 4px 10px;
|
|
222
|
-
border-bottom: 1px solid var(--border);
|
|
223
|
-
white-space: nowrap;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
.entity-table td {
|
|
227
|
-
padding: 3px 10px;
|
|
228
|
-
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
229
|
-
color: var(--text);
|
|
230
|
-
white-space: nowrap;
|
|
231
|
-
max-width: 200px;
|
|
232
|
-
overflow: hidden;
|
|
233
|
-
text-overflow: ellipsis;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.entity-table tbody tr:hover td { background: var(--bg-hover); }
|
|
237
|
-
|
|
238
|
-
.entity-note {
|
|
239
|
-
padding: 4px 10px;
|
|
240
|
-
font-size: 10px;
|
|
241
|
-
color: var(--text-dim);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/* ── Computed rows ────────────────────────────── */
|
|
245
|
-
|
|
246
|
-
.comp-row {
|
|
247
|
-
padding: 8px 14px; border-bottom: 1px solid var(--border);
|
|
248
|
-
background: var(--bg-row); transition: background 0.1s;
|
|
249
|
-
}
|
|
250
|
-
.comp-row:hover { background: var(--bg-hover); }
|
|
251
|
-
|
|
252
|
-
.comp-top { display: flex; align-items: center; gap: 8px; }
|
|
253
|
-
|
|
254
|
-
.status-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
|
|
255
|
-
.status-dot.fresh { background: var(--green); }
|
|
256
|
-
.status-dot.stale { background: var(--yellow); }
|
|
257
|
-
.status-dot.pending { background: var(--gray); }
|
|
258
|
-
|
|
259
|
-
.comp-name {
|
|
260
|
-
font-family: var(--mono); font-size: 13px;
|
|
261
|
-
font-weight: 600; color: var(--text-hi); flex: 1;
|
|
262
|
-
min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
.status-pill {
|
|
266
|
-
font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
|
|
267
|
-
padding: 1px 8px; border-radius: 10px; flex-shrink: 0;
|
|
268
|
-
}
|
|
269
|
-
.status-pill.fresh { background: #1a3a1c; color: #81c784; }
|
|
270
|
-
.status-pill.stale { background: #3a2a10; color: #ffcc80; }
|
|
271
|
-
.status-pill.pending { background: #2a2a2a; color: #90a4ae; }
|
|
272
|
-
|
|
273
|
-
.comp-value {
|
|
274
|
-
font-family: var(--mono); font-size: 12px; color: var(--accent);
|
|
275
|
-
max-width: 200px; overflow: hidden; text-overflow: ellipsis;
|
|
276
|
-
white-space: nowrap; cursor: default;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.comp-deps {
|
|
280
|
-
display: flex; flex-wrap: wrap; align-items: center;
|
|
281
|
-
gap: 3px; margin-top: 5px; padding-left: 17px;
|
|
282
|
-
}
|
|
283
|
-
.comp-deps-label { font-size: 11px; color: var(--text-dim); margin-right: 4px; }
|
|
284
|
-
|
|
285
|
-
/* ── Flush history ────────────────────────────── */
|
|
286
|
-
|
|
287
|
-
.flush-row {
|
|
288
|
-
display: flex; align-items: center; gap: 8px;
|
|
289
|
-
padding: 4px 14px; border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
290
|
-
font-size: 11px; font-family: var(--mono);
|
|
291
|
-
}
|
|
292
|
-
.flush-row:hover { background: var(--bg-hover); }
|
|
293
|
-
|
|
294
|
-
.flush-time { color: var(--text-dim); flex-shrink: 0; }
|
|
295
|
-
|
|
296
|
-
.flush-tags { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
297
|
-
|
|
298
|
-
.flush-tag {
|
|
299
|
-
padding: 1px 6px; border-radius: 3px;
|
|
300
|
-
background: var(--bg-input); color: var(--text-dim);
|
|
301
|
-
font-size: 10px;
|
|
302
|
-
}
|
|
303
|
-
.flush-add { background: #1a3a1c; color: #81c784; }
|
|
304
|
-
.flush-del { background: #3a1a1a; color: #ef9a9a; }
|
|
305
|
-
.flush-no-change { color: var(--text-dim); background: none; }
|
|
306
|
-
|
|
307
|
-
/* ── Scrollbar ────────────────────────────────── */
|
|
308
|
-
|
|
309
|
-
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
310
|
-
::-webkit-scrollbar-track { background: var(--bg); }
|
|
311
|
-
::-webkit-scrollbar-thumb { background: #444; border-radius: 3px; }
|
|
312
|
-
::-webkit-scrollbar-thumb:hover { background: #555; }
|
|
313
|
-
|
|
314
|
-
/* ── Empty states ─────────────────────────────── */
|
|
315
|
-
|
|
316
|
-
.empty {
|
|
317
|
-
padding: 20px 16px; color: var(--text-dim);
|
|
318
|
-
font-size: 12px; text-align: center; line-height: 1.7;
|
|
319
|
-
}
|
|
320
|
-
.empty code {
|
|
321
|
-
font-family: var(--mono); background: var(--bg-input);
|
|
322
|
-
padding: 1px 5px; border-radius: 3px; color: var(--accent);
|
|
323
|
-
}
|