@happy-nut/monacori 0.1.2 → 0.1.5
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 -147
- package/dist/app-main.js +205 -14
- package/dist/assets.d.ts +2 -0
- package/dist/assets.js +21 -0
- package/dist/build.d.ts +1 -0
- package/dist/build.js +30 -5
- package/dist/commands.js +12 -326
- package/dist/diff.js +41 -0
- package/dist/i18n.d.ts +1 -0
- package/dist/i18n.js +266 -0
- package/dist/preload.cjs +70 -0
- package/dist/render.d.ts +12 -0
- package/dist/render.js +102 -22
- package/dist/server.js +6 -0
- package/dist/types.d.ts +14 -0
- package/dist/viewer.client.js +950 -125
- package/dist/viewer.css +248 -44
- package/package.json +6 -2
- package/scripts/patch-electron-name.mjs +8 -0
package/dist/viewer.css
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
|
|
2
2
|
:root {
|
|
3
3
|
color-scheme: dark;
|
|
4
|
-
--bg: #
|
|
5
|
-
--panel: #
|
|
4
|
+
--bg: #161616;
|
|
5
|
+
--panel: #1b1b1b;
|
|
6
6
|
--text: #a9b7c6;
|
|
7
7
|
--muted: #808080;
|
|
8
8
|
--border: #393b3d;
|
|
9
9
|
--line: #313335;
|
|
10
|
-
--add: #
|
|
11
|
-
--del: #
|
|
12
|
-
--add-strong: #
|
|
13
|
-
--del-strong: #
|
|
10
|
+
--add: #16351f;
|
|
11
|
+
--del: #3f1d1d;
|
|
12
|
+
--add-strong: #1f5b34;
|
|
13
|
+
--del-strong: #6e2c2c;
|
|
14
14
|
--active: #4a88c7;
|
|
15
|
-
--sidebar: #
|
|
15
|
+
--sidebar: #1c1c1c;
|
|
16
16
|
--token-comment: #808080;
|
|
17
17
|
--token-keyword: #cc7832;
|
|
18
18
|
--token-string: #6a8759;
|
|
@@ -127,6 +127,10 @@ body {
|
|
|
127
127
|
}
|
|
128
128
|
.tab.active, .plain-button:hover { border-color: var(--active); color: var(--active); }
|
|
129
129
|
.hidden { display: none !important; }
|
|
130
|
+
/* IntelliJ-style git status on sidebar file names: untracked(new)=red, modified=blue, staged(git add)=green. */
|
|
131
|
+
.vcs-new.source-link .path, .vcs-new.change-row .change-name { color: #d36c6c; }
|
|
132
|
+
.vcs-edited.source-link .path, .vcs-edited.change-row .change-name { color: #6c9fd4; }
|
|
133
|
+
.vcs-staged.source-link .path, .vcs-staged.change-row .change-name { color: #7faf6b; }
|
|
130
134
|
.sidebar-footer {
|
|
131
135
|
flex: 0 0 auto;
|
|
132
136
|
padding: 8px 12px;
|
|
@@ -138,10 +142,9 @@ body {
|
|
|
138
142
|
font-size: 11px;
|
|
139
143
|
color: var(--muted);
|
|
140
144
|
}
|
|
141
|
-
.sidebar-footer .app-version { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
145
|
+
.sidebar-footer .app-version { margin-right: auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
142
146
|
.app-update-flag { color: var(--active); font-weight: 600; cursor: pointer; white-space: nowrap; }
|
|
143
147
|
.settings-btn {
|
|
144
|
-
margin-left: auto;
|
|
145
148
|
flex: none;
|
|
146
149
|
border: 1px solid transparent;
|
|
147
150
|
border-radius: 6px;
|
|
@@ -152,7 +155,7 @@ body {
|
|
|
152
155
|
padding: 3px 6px;
|
|
153
156
|
cursor: pointer;
|
|
154
157
|
}
|
|
155
|
-
.settings-btn:hover { color: var(--
|
|
158
|
+
.settings-btn:hover { color: var(--text); background: color-mix(in srgb, var(--active) 12%, transparent); }
|
|
156
159
|
.app-info {
|
|
157
160
|
position: fixed;
|
|
158
161
|
left: 12px;
|
|
@@ -174,24 +177,58 @@ body {
|
|
|
174
177
|
.app-info-head .app-info-ver { color: var(--muted); font-weight: 500; }
|
|
175
178
|
.app-info-status { color: var(--muted); margin-bottom: 10px; }
|
|
176
179
|
.app-info-status.has-update { color: var(--active); font-weight: 600; }
|
|
177
|
-
.app-info-
|
|
178
|
-
.app-info-
|
|
179
|
-
|
|
180
|
-
min-width: 0;
|
|
181
|
-
overflow: hidden;
|
|
182
|
-
text-overflow: ellipsis;
|
|
183
|
-
white-space: nowrap;
|
|
184
|
-
padding: 5px 8px;
|
|
185
|
-
border-radius: 6px;
|
|
186
|
-
background: var(--bg);
|
|
187
|
-
border: 1px solid var(--border);
|
|
188
|
-
font: 11px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
189
|
-
color: var(--text);
|
|
190
|
-
}
|
|
191
|
-
.app-info-cmd .plain-button { padding: 5px 9px; font-size: 11px; }
|
|
180
|
+
.app-info-update { width: 100%; margin: 0 0 10px; border-color: var(--active); color: var(--active); font-weight: 600; }
|
|
181
|
+
.app-info-update:hover { background: color-mix(in srgb, var(--active) 14%, transparent); color: var(--active); }
|
|
182
|
+
.app-info-update:disabled { opacity: 0.55; cursor: default; }
|
|
192
183
|
.app-info-keys { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }
|
|
184
|
+
|
|
185
|
+
/* Settings modal (Cmd+Shift+/ merge prompts, etc.) — sidebar categories + form, like a desktop app. */
|
|
186
|
+
.settings-modal {
|
|
187
|
+
position: fixed; inset: 0; z-index: 70;
|
|
188
|
+
display: flex; align-items: center; justify-content: center;
|
|
189
|
+
background: rgba(0, 0, 0, 0.6); padding: 32px;
|
|
190
|
+
}
|
|
191
|
+
.settings-modal.hidden { display: none; }
|
|
192
|
+
.settings-panel {
|
|
193
|
+
display: flex;
|
|
194
|
+
width: 980px; max-width: 90vw; height: 700px; max-height: 88vh;
|
|
195
|
+
background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
|
|
196
|
+
overflow: hidden; box-shadow: 0 12px 48px rgba(0, 0, 0, 0.55);
|
|
197
|
+
}
|
|
198
|
+
.settings-nav {
|
|
199
|
+
flex: 0 0 200px; padding: 16px 10px;
|
|
200
|
+
background: var(--sidebar); border-right: 1px solid var(--border);
|
|
201
|
+
display: flex; flex-direction: column; gap: 4px;
|
|
202
|
+
}
|
|
203
|
+
.settings-nav-title { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); padding: 4px 10px 8px; }
|
|
204
|
+
.settings-cat { text-align: left; border: 0; background: transparent; color: var(--text); padding: 7px 10px; border-radius: 6px; font-size: 13px; cursor: pointer; }
|
|
205
|
+
.settings-cat:hover { background: color-mix(in srgb, var(--active) 12%, transparent); }
|
|
206
|
+
.settings-cat.active { background: color-mix(in srgb, var(--active) 20%, transparent); color: var(--active); font-weight: 600; }
|
|
207
|
+
.settings-body { flex: 1 1 auto; min-width: 0; padding: 24px 28px; overflow: auto; }
|
|
208
|
+
.settings-h { font-size: 16px; font-weight: 650; color: var(--text); margin-bottom: 6px; }
|
|
209
|
+
.settings-ver { color: var(--muted); font-weight: 500; font-size: 0.62em; letter-spacing: 0.02em; }
|
|
210
|
+
.settings-desc { font-size: 12px; color: var(--muted); line-height: 1.6; margin-bottom: 18px; }
|
|
211
|
+
.settings-label { display: block; font-size: 12px; font-weight: 600; color: var(--text); margin: 14px 0 6px; }
|
|
212
|
+
.settings-textarea {
|
|
213
|
+
width: 100%; box-sizing: border-box; resize: vertical; min-height: 70px;
|
|
214
|
+
background: var(--bg); color: var(--text);
|
|
215
|
+
border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px;
|
|
216
|
+
font: 12px/1.55 ui-sans-serif, system-ui, sans-serif;
|
|
217
|
+
}
|
|
218
|
+
.settings-textarea:focus { outline: none; border-color: var(--active); }
|
|
219
|
+
.settings-select {
|
|
220
|
+
width: auto; box-sizing: border-box;
|
|
221
|
+
background: var(--bg); color: var(--text);
|
|
222
|
+
border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px;
|
|
223
|
+
font: 12px/1.55 ui-sans-serif, system-ui, sans-serif;
|
|
224
|
+
}
|
|
225
|
+
.settings-select:focus { outline: none; border-color: var(--active); }
|
|
226
|
+
.settings-actions { display: flex; align-items: center; gap: 12px; margin-top: 18px; }
|
|
227
|
+
.settings-saved { font-size: 12px; color: var(--active); }
|
|
193
228
|
.app-info-keys-h { font-weight: 600; color: var(--text); margin-bottom: 8px; }
|
|
194
|
-
.keys-
|
|
229
|
+
.keys-cat { font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin: 14px 0 6px; }
|
|
230
|
+
.app-info-keys .keys-cat:first-of-type { margin-top: 4px; }
|
|
231
|
+
.keys-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 5px 10px; align-items: center; margin-bottom: 2px; }
|
|
195
232
|
.keys-grid kbd {
|
|
196
233
|
justify-self: start;
|
|
197
234
|
font: 10px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
@@ -299,6 +336,10 @@ body {
|
|
|
299
336
|
-webkit-user-select: text;
|
|
300
337
|
user-select: text;
|
|
301
338
|
}
|
|
339
|
+
/* Changed lines: lift the base text brighter than the gray context so additions/deletions read as
|
|
340
|
+
edits, not the same gray. hljs tokens keep their own colors; this only affects unhighlighted text. */
|
|
341
|
+
td.d2h-ins:not(.d2h-code-side-linenumber),
|
|
342
|
+
td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
|
|
302
343
|
.d2h-code-line-prefix { -webkit-user-select: none; user-select: none; }
|
|
303
344
|
.d2h-code-side-linenumber, .d2h-code-linenumber { -webkit-user-select: none; user-select: none; }
|
|
304
345
|
.d2h-code-line-ctn .hljs-keyword,
|
|
@@ -424,14 +465,16 @@ body {
|
|
|
424
465
|
}
|
|
425
466
|
.tree-dir summary::-webkit-details-marker { display: none; }
|
|
426
467
|
.tree-dir summary:hover { background: var(--bg); }
|
|
427
|
-
.tree-dir:not([open]) .folder-icon { transform: rotate(-90deg); }
|
|
428
468
|
.folder-icon {
|
|
429
469
|
display: inline-grid;
|
|
430
470
|
place-items: center;
|
|
431
|
-
font-size: 9px;
|
|
432
471
|
color: var(--muted);
|
|
433
|
-
transition: transform 120ms ease;
|
|
434
472
|
}
|
|
473
|
+
.folder-icon .folder-ic { width: 14px; height: 14px; display: block; }
|
|
474
|
+
/* Closed vs open folder glyph (replaces the old rotated "v" chevron). */
|
|
475
|
+
.tree-dir > summary .fi-open { display: none; }
|
|
476
|
+
.tree-dir[open] > summary .fi-closed { display: none; }
|
|
477
|
+
.tree-dir[open] > summary .fi-open { display: block; }
|
|
435
478
|
.file-link.tree-file { padding-left: calc(8px + (var(--depth) * 14px)); }
|
|
436
479
|
.tree-focus { box-shadow: inset 0 0 0 1px var(--active); border-radius: 6px; }
|
|
437
480
|
summary.tree-focus { background: var(--bg); }
|
|
@@ -483,7 +526,20 @@ summary.tree-focus { background: var(--bg); }
|
|
|
483
526
|
.status-deleted { background: var(--del); color: #cf222e; }
|
|
484
527
|
.status-renamed { background: #fff8c5; color: #9a6700; }
|
|
485
528
|
.status-source { background: var(--line); color: var(--muted); }
|
|
486
|
-
.content { min-width: 0; padding: 0; }
|
|
529
|
+
.content { min-width: 0; padding: 0; display: flex; flex-direction: column; min-height: 100vh; }
|
|
530
|
+
/* Pin the diff's horizontal scrollbar to the viewport bottom instead of letting it float
|
|
531
|
+
mid-screen when a file's diff is short: fill the content column vertically so the last
|
|
532
|
+
file's diff body extends all the way down. */
|
|
533
|
+
#diff-view:not(.hidden) { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
|
|
534
|
+
#diff-view .diff2html-container { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
|
|
535
|
+
.diff2html-container .d2h-wrapper { flex: 1 1 auto; display: flex; flex-direction: column; }
|
|
536
|
+
.diff2html-container .d2h-file-wrapper:last-child { flex: 1 1 auto; }
|
|
537
|
+
.diff2html-container .d2h-file-wrapper:last-child .d2h-files-diff { height: 100%; }
|
|
538
|
+
/* Slimmer scrollbars — the default overlay bars read as chunky on the dark UI. */
|
|
539
|
+
::-webkit-scrollbar { width: 9px; height: 9px; }
|
|
540
|
+
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 32%, transparent); border-radius: 5px; }
|
|
541
|
+
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 52%, transparent); }
|
|
542
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
487
543
|
.toolbar {
|
|
488
544
|
position: sticky;
|
|
489
545
|
top: 0;
|
|
@@ -547,6 +603,40 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
547
603
|
text-overflow: ellipsis;
|
|
548
604
|
white-space: nowrap;
|
|
549
605
|
}
|
|
606
|
+
/* Files-mode tabs: one row of tabs above the source toolbar (open files, click to switch, × to close). */
|
|
607
|
+
.source-tabs {
|
|
608
|
+
display: flex;
|
|
609
|
+
overflow-x: auto;
|
|
610
|
+
gap: 1px;
|
|
611
|
+
margin-bottom: 8px;
|
|
612
|
+
background: var(--sidebar);
|
|
613
|
+
border: 1px solid var(--border);
|
|
614
|
+
border-radius: 8px;
|
|
615
|
+
scrollbar-width: thin;
|
|
616
|
+
}
|
|
617
|
+
.source-tab {
|
|
618
|
+
display: inline-flex;
|
|
619
|
+
align-items: center;
|
|
620
|
+
gap: 6px;
|
|
621
|
+
flex: 0 0 auto;
|
|
622
|
+
max-width: 220px;
|
|
623
|
+
padding: 6px 8px 6px 12px;
|
|
624
|
+
border-right: 1px solid var(--border);
|
|
625
|
+
background: var(--panel);
|
|
626
|
+
color: var(--muted);
|
|
627
|
+
font-size: 12px;
|
|
628
|
+
cursor: pointer;
|
|
629
|
+
white-space: nowrap;
|
|
630
|
+
}
|
|
631
|
+
.source-tab:first-child { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }
|
|
632
|
+
.source-tab:hover { color: var(--text); }
|
|
633
|
+
.source-tab.active { color: var(--text); background: var(--bg); box-shadow: inset 0 -2px 0 var(--active); }
|
|
634
|
+
.source-tab-name { overflow: hidden; text-overflow: ellipsis; }
|
|
635
|
+
.source-tab-close {
|
|
636
|
+
flex: none; border: 0; background: transparent; color: var(--muted);
|
|
637
|
+
font-size: 14px; line-height: 1; padding: 0 3px; cursor: pointer; border-radius: 3px;
|
|
638
|
+
}
|
|
639
|
+
.source-tab-close:hover { background: var(--line); color: var(--text); }
|
|
550
640
|
.source-body {
|
|
551
641
|
border: 1px solid var(--border);
|
|
552
642
|
border-radius: 8px;
|
|
@@ -554,6 +644,31 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
554
644
|
background: var(--panel);
|
|
555
645
|
user-select: text;
|
|
556
646
|
}
|
|
647
|
+
/* Extend the line-number gutter (and its divider) to the bottom of the panel so it never stops at the
|
|
648
|
+
last line with an empty strip + cut-off border below it — one continuous gutter. The .num cell is 58px
|
|
649
|
+
wide + 8px padding each side + 1px border ≈ 75px; the gradient mirrors that. (pre-wrap = no h-scroll, so
|
|
650
|
+
a fixed background stays aligned.) */
|
|
651
|
+
.source-body:not(.empty):not(.image-body) {
|
|
652
|
+
background-image: linear-gradient(to right, var(--line) 0 74px, var(--border) 74px 75px, var(--panel) 75px);
|
|
653
|
+
background-repeat: no-repeat;
|
|
654
|
+
}
|
|
655
|
+
/* Boot overlay: painted the instant the review HTML loads, removed once the renderer's bootstrap has drawn
|
|
656
|
+
the diff/tree — so there's no blank screen between the startup spinner and first render. Mirrors
|
|
657
|
+
app-main's LOADING_HTML spinner exactly so the hand-off from the loading screen is seamless. */
|
|
658
|
+
#boot-overlay {
|
|
659
|
+
position: fixed; inset: 0; z-index: 200;
|
|
660
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
|
|
661
|
+
background: #2b2b2b; color: #9aa4af;
|
|
662
|
+
font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
663
|
+
transition: opacity 0.22s ease;
|
|
664
|
+
}
|
|
665
|
+
#boot-overlay.hide { opacity: 0; pointer-events: none; }
|
|
666
|
+
.boot-spinner {
|
|
667
|
+
width: 34px; height: 34px;
|
|
668
|
+
border: 3px solid #3a3a3a; border-top-color: #4a9eff; border-radius: 50%;
|
|
669
|
+
animation: boot-spin 0.8s linear infinite;
|
|
670
|
+
}
|
|
671
|
+
@keyframes boot-spin { to { transform: rotate(360deg); } }
|
|
557
672
|
/* Empty state ("Select a file…") centered in the available space, not top-left. */
|
|
558
673
|
.source-body.empty {
|
|
559
674
|
display: flex;
|
|
@@ -578,6 +693,10 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
578
693
|
gracefully where unsupported. contain-intrinsic-size keeps the scrollbar stable. */
|
|
579
694
|
.source-row { content-visibility: auto; contain-intrinsic-size: auto 19px; }
|
|
580
695
|
.d2h-diff-table tr { content-visibility: auto; contain-intrinsic-size: auto 18px; }
|
|
696
|
+
/* Comment/composer rows are tall and interactive (a textarea lives here). Skip-rendering them
|
|
697
|
+
with a tiny 18px placeholder made the browser re-evaluate their render state on every
|
|
698
|
+
keystroke, so typing in the composer stuttered — keep these rows always rendered. */
|
|
699
|
+
.d2h-diff-table tr.mc-comment-row, .d2h-diff-table tr.mc-spacer-row { content-visibility: visible; contain-intrinsic-size: auto; }
|
|
581
700
|
.source-row.search-hit .source-code { background: color-mix(in srgb, var(--active) 14%, transparent); }
|
|
582
701
|
.source-row.changed-line .source-code { background: color-mix(in srgb, var(--active) 9%, transparent); box-shadow: inset 2px 0 0 color-mix(in srgb, var(--active) 55%, transparent); }
|
|
583
702
|
.source-row.symbol-target .source-code {
|
|
@@ -601,8 +720,16 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
601
720
|
@keyframes cursor-blink {
|
|
602
721
|
50% { opacity: 0; }
|
|
603
722
|
}
|
|
723
|
+
/* Keep the caret solid while it is actively moving (held arrow key / typing); blink only when idle. */
|
|
724
|
+
.caret-busy .code-cursor { animation: none; opacity: 1; }
|
|
725
|
+
/* Markdown/CSV rendered rows have no inline caret span — mark the whole cursor row instead. */
|
|
726
|
+
.source-row.md-row.cursor-line .md-cell,
|
|
727
|
+
.source-row.csv-row.cursor-line .csv-cell { background: color-mix(in srgb, #000 26%, transparent); }
|
|
728
|
+
.source-row.md-row.cursor-line .num,
|
|
729
|
+
.source-row.csv-row.cursor-line .num { color: var(--active); }
|
|
604
730
|
.num {
|
|
605
|
-
width:
|
|
731
|
+
width: 75px;
|
|
732
|
+
box-sizing: border-box; /* fixed 75px total so the .source-body gutter gradient lines up exactly (no bleed) */
|
|
606
733
|
user-select: none;
|
|
607
734
|
text-align: right;
|
|
608
735
|
color: var(--muted);
|
|
@@ -631,29 +758,41 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
631
758
|
.mc-thread-cell { padding: 4px 12px 8px 64px; }
|
|
632
759
|
.source-table .mc-thread-cell { padding: 4px 12px 8px 66px; }
|
|
633
760
|
.mc-card {
|
|
634
|
-
border: 1px solid var(--border);
|
|
635
|
-
border-radius:
|
|
761
|
+
border: 1px solid var(--border);
|
|
762
|
+
border-radius: 8px; background: var(--panel); margin: 8px 0; max-width: 760px;
|
|
636
763
|
font: 12px/1.5 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
764
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28);
|
|
765
|
+
overflow: hidden;
|
|
637
766
|
}
|
|
638
|
-
|
|
639
|
-
.mc-card
|
|
640
|
-
.mc-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
767
|
+
/* Question vs change-request is a small colored pill on the kind label — no heavy left bar. */
|
|
768
|
+
.mc-card-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px 6px; color: var(--muted); }
|
|
769
|
+
.mc-kind {
|
|
770
|
+
font-weight: 700; font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
|
|
771
|
+
padding: 2px 8px; border-radius: 999px;
|
|
772
|
+
color: var(--muted); background: color-mix(in srgb, var(--muted) 16%, transparent);
|
|
773
|
+
}
|
|
774
|
+
.mc-card.mc-q .mc-kind { color: var(--token-number); background: color-mix(in srgb, var(--token-number) 18%, transparent); }
|
|
775
|
+
.mc-card.mc-c .mc-kind { color: var(--token-tag); background: color-mix(in srgb, var(--token-tag) 18%, transparent); }
|
|
776
|
+
.mc-del { margin-left: auto; background: transparent; border: 0; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 1px 5px; border-radius: 5px; }
|
|
777
|
+
.mc-del:hover { color: var(--del-strong); background: color-mix(in srgb, var(--del-strong) 16%, transparent); }
|
|
778
|
+
.mc-card-body { padding: 2px 12px 11px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
645
779
|
.mc-input {
|
|
646
780
|
display: block; box-sizing: border-box; resize: vertical;
|
|
647
|
-
margin:
|
|
781
|
+
margin: 0 10px 10px; width: calc(100% - 20px); min-height: 60px;
|
|
648
782
|
background: var(--bg); color: var(--text);
|
|
649
|
-
border: 1px solid var(--border); border-radius:
|
|
650
|
-
font: 12px/1.
|
|
783
|
+
border: 1px solid var(--border); border-radius: 7px; padding: 9px 11px;
|
|
784
|
+
font: 12px/1.55 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
785
|
+
transition: border-color 120ms ease, box-shadow 120ms ease;
|
|
651
786
|
}
|
|
652
|
-
.mc-input:focus { outline: none; border-color: var(--active); }
|
|
787
|
+
.mc-input:focus { outline: none; border-color: var(--active); box-shadow: 0 0 0 3px color-mix(in srgb, var(--active) 22%, transparent); }
|
|
653
788
|
.mc-actions { display: flex; align-items: center; gap: 8px; padding: 0 10px 9px; }
|
|
654
789
|
.mc-btn { background: var(--active); color: #fff; border: 0; border-radius: 6px; padding: 5px 12px; font-size: 12px; cursor: pointer; }
|
|
655
790
|
.mc-btn:hover { filter: brightness(1.1); }
|
|
656
791
|
.mc-btn.mc-ghost { background: transparent; border: 1px solid var(--border); color: var(--text); }
|
|
792
|
+
/* Terminal-send buttons in the merged modal: green to read as "send to the live session", with a clear
|
|
793
|
+
focus ring so arrow-key selection between split panes is visible. */
|
|
794
|
+
.mc-send-term { background: #2f8f46; }
|
|
795
|
+
.mc-send-term:focus, .mc-send-term:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
|
|
657
796
|
.mc-hint { color: var(--muted); font-size: 11px; }
|
|
658
797
|
.mc-modal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: start center; padding-top: min(10vh, 80px); background: color-mix(in srgb, #000 32%, transparent); }
|
|
659
798
|
.mc-modal.hidden { display: none; }
|
|
@@ -662,6 +801,12 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
662
801
|
.mc-modal-head span { margin-right: auto; }
|
|
663
802
|
.mc-modal-text { width: 100%; height: 100%; box-sizing: border-box; resize: none; border: 0; padding: 12px; background: var(--bg); color: var(--text); font: 12px/1.55 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
664
803
|
.mc-modal-text:focus { outline: none; }
|
|
804
|
+
/* Prompt memo: split editor | live Markdown preview inside the standard modal shell. */
|
|
805
|
+
.mc-memo-body { display: grid; grid-template-columns: 1fr 1fr; min-height: 0; height: 100%; }
|
|
806
|
+
.mc-memo-edit { height: 100%; border-right: 1px solid var(--border); }
|
|
807
|
+
.mc-memo-preview { height: 100%; overflow: auto; padding: 12px 16px; background: var(--panel); color: var(--text); }
|
|
808
|
+
.mc-memo-preview > :first-child { margin-top: 0; }
|
|
809
|
+
.mc-memo-empty { color: var(--muted); font-size: 12px; font-style: italic; }
|
|
665
810
|
.tok-comment { color: var(--token-comment); font-style: italic; }
|
|
666
811
|
.tok-keyword { color: var(--token-keyword); font-weight: 650; }
|
|
667
812
|
.tok-string { color: var(--token-string); }
|
|
@@ -937,3 +1082,62 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
937
1082
|
.csv-head .csv-cell { background: var(--line); color: #d7e0ea; font-weight: 650; }
|
|
938
1083
|
.csv-row:nth-child(even) .csv-cell { background: rgba(255, 255, 255, 0.018); }
|
|
939
1084
|
.csv-empty { color: var(--muted); font-style: italic; padding: 16px; }
|
|
1085
|
+
|
|
1086
|
+
/* --- Integrated terminal panel (Electron only): fixed to the content column's bottom, height-resizable.
|
|
1087
|
+
The active border-top marks it as the merged-prompt send target ("highlighted while it's open"). --- */
|
|
1088
|
+
.terminal-panel {
|
|
1089
|
+
position: fixed;
|
|
1090
|
+
left: var(--sidebar-width, 280px);
|
|
1091
|
+
right: 0;
|
|
1092
|
+
bottom: 0;
|
|
1093
|
+
height: var(--terminal-height, 320px);
|
|
1094
|
+
z-index: 40;
|
|
1095
|
+
display: flex;
|
|
1096
|
+
flex-direction: column;
|
|
1097
|
+
background: var(--bg);
|
|
1098
|
+
border-top: 2px solid var(--active);
|
|
1099
|
+
box-shadow: 0 -10px 28px rgba(0, 0, 0, 0.45);
|
|
1100
|
+
}
|
|
1101
|
+
.terminal-resizer { flex: none; height: 6px; margin-top: -3px; cursor: row-resize; }
|
|
1102
|
+
.terminal-resizer:hover, .terminal-resizer.resizing { background: var(--active); }
|
|
1103
|
+
.terminal-bar {
|
|
1104
|
+
flex: none; display: flex; align-items: center; justify-content: space-between;
|
|
1105
|
+
padding: 4px 10px; background: var(--sidebar); border-bottom: 1px solid var(--border);
|
|
1106
|
+
font-size: 11px; color: var(--muted);
|
|
1107
|
+
}
|
|
1108
|
+
.terminal-title { letter-spacing: 0.08em; text-transform: uppercase; }
|
|
1109
|
+
.terminal-x { border: 0; background: transparent; color: var(--muted); font-size: 16px; line-height: 1; padding: 0 4px; cursor: pointer; }
|
|
1110
|
+
.terminal-x:hover { color: var(--text); }
|
|
1111
|
+
/* Split panes sit side by side (no tabs); the 1px gap shows the --border underneath as a divider. */
|
|
1112
|
+
.terminal-host { flex: 1 1 auto; min-height: 0; display: flex; gap: 1px; overflow: hidden; background: var(--border); }
|
|
1113
|
+
.terminal-pane { flex: 1 1 0; min-width: 0; background: var(--bg); overflow: hidden; display: flex; flex-direction: column; }
|
|
1114
|
+
/* Per-pane name strip at the top; double-click or Cmd/Ctrl+Alt+R to rename inline. */
|
|
1115
|
+
.terminal-pane-label {
|
|
1116
|
+
flex: none; padding: 2px 10px; font-size: 10px; letter-spacing: 0.04em;
|
|
1117
|
+
color: var(--muted); background: var(--sidebar); border-bottom: 1px solid var(--border);
|
|
1118
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: text;
|
|
1119
|
+
}
|
|
1120
|
+
.terminal-pane-label:hover { color: var(--text); }
|
|
1121
|
+
.terminal-pane-label[contenteditable="true"] { color: var(--text); background: var(--bg); outline: none; }
|
|
1122
|
+
.terminal-pane.is-active .terminal-pane-label { color: var(--text); }
|
|
1123
|
+
.terminal-pane-host { flex: 1 1 auto; min-width: 0; min-height: 0; padding: 4px 0 4px 8px; }
|
|
1124
|
+
/* No border on the active pane — the inactive panes dim back instead, so the focused one stands out
|
|
1125
|
+
cleanly without an outline. Only applies with 2+ panes (a lone pane is never dimmed; see setActive). */
|
|
1126
|
+
.terminal-pane { transition: opacity 120ms ease; }
|
|
1127
|
+
.terminal-panel:not(.send-mode) .terminal-pane.is-inactive { opacity: 0.4; }
|
|
1128
|
+
/* Pane-pick mode (merged "Send to terminal"): chosen pane ringed + full opacity, the rest dimmed. */
|
|
1129
|
+
.terminal-pane.is-dimmed { opacity: 0.3; }
|
|
1130
|
+
.terminal-pane.is-send-target { box-shadow: inset 0 0 0 2px var(--active); opacity: 1; position: relative; }
|
|
1131
|
+
/* Faint ⏎ hint floating over the chosen pane; it vanishes the instant Enter exits send mode. */
|
|
1132
|
+
.terminal-pane.is-send-target::after {
|
|
1133
|
+
content: "⏎";
|
|
1134
|
+
position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
|
1135
|
+
font-size: 56px; color: var(--active); opacity: 0.32; pointer-events: none; z-index: 5;
|
|
1136
|
+
}
|
|
1137
|
+
/* Send mode dims the rest of the app (sidebar + file/diff view) so only the terminal pops. */
|
|
1138
|
+
body.terminal-send-mode .sidebar,
|
|
1139
|
+
body.terminal-send-mode .content,
|
|
1140
|
+
body.terminal-send-mode .sidebar-resizer { opacity: 0.25; pointer-events: none; }
|
|
1141
|
+
/* Pad the content tail so it isn't hidden behind the fixed panel while the terminal is open. */
|
|
1142
|
+
body.terminal-open .content { padding-bottom: var(--terminal-height, 320px); }
|
|
1143
|
+
.terminal-toggle.is-active { color: var(--active); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happy-nut/monacori",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Validation control plane for AI-generated code changes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -50,8 +50,12 @@
|
|
|
50
50
|
"node": ">=20"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"@electron/rebuild": "^4.0.4",
|
|
54
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
55
|
+
"@xterm/xterm": "^6.0.0",
|
|
53
56
|
"diff2html": "^3.4.56",
|
|
54
57
|
"electron": "^42.4.1",
|
|
55
|
-
"highlight.js": "^11.11.1"
|
|
58
|
+
"highlight.js": "^11.11.1",
|
|
59
|
+
"node-pty": "^1.1.0"
|
|
56
60
|
}
|
|
57
61
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import { dirname, join } from "node:path";
|
|
4
5
|
|
|
@@ -48,6 +49,13 @@ function main() {
|
|
|
48
49
|
const fixed = pt.replace("MacOS/Electron", "MacOS/" + APP_NAME);
|
|
49
50
|
if (fixed !== pt) writeFileSync(pathTxt, fixed);
|
|
50
51
|
}
|
|
52
|
+
// Refresh LaunchServices so the Dock / Cmd+Tab show "monacori" instead of a cached "Electron".
|
|
53
|
+
// Without this, macOS keeps the previously-registered bundle name even after the plist is patched.
|
|
54
|
+
spawnSync(
|
|
55
|
+
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister",
|
|
56
|
+
["-f", appDir],
|
|
57
|
+
{ stdio: "ignore" },
|
|
58
|
+
);
|
|
51
59
|
console.log('monacori: branded Electron app + executable as "' + APP_NAME + '"');
|
|
52
60
|
} catch {
|
|
53
61
|
// read-only / permission-denied environments — harmless, this is a convenience step
|