@happy-nut/monacori 0.1.25 → 0.1.26
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/dist/app-main.js +16 -28
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +3 -0
- package/dist/diff.js +9 -1
- package/dist/i18n.js +12 -6
- package/dist/render.js +3 -1
- package/dist/self-update.d.ts +8 -0
- package/dist/self-update.js +18 -0
- package/dist/viewer.client.js +470 -14
- package/dist/viewer.client.min.js +1 -1
- package/dist/viewer.css +16 -9
- package/package.json +1 -1
- package/scripts/patch-electron-name.mjs +76 -26
package/dist/viewer.css
CHANGED
|
@@ -503,8 +503,9 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
|
|
|
503
503
|
.d2h-code-line-ctn del { background: var(--del-strong); }
|
|
504
504
|
.d2h-code-side-linenumber.d2h-del, .d2h-code-linenumber.d2h-del { background: var(--del); }
|
|
505
505
|
.d2h-code-side-linenumber.d2h-ins, .d2h-code-linenumber.d2h-ins { background: var(--add); }
|
|
506
|
-
.d2h-diff-table tr.hunk, .d2h-diff-table tr.hunk-peer { scroll-margin-top: 76px; }
|
|
507
|
-
.d2h-diff-table tr.hunk.active td, .d2h-diff-table tr.hunk-peer.active td
|
|
506
|
+
.d2h-diff-table tr.hunk, .d2h-diff-table tr.hunk-peer, .d2h-diff-table tr.history-hunk, .d2h-diff-table tr.history-hunk-peer { scroll-margin-top: 76px; }
|
|
507
|
+
.d2h-diff-table tr.hunk.active td, .d2h-diff-table tr.hunk-peer.active td,
|
|
508
|
+
.d2h-diff-table tr.history-hunk.active td, .d2h-diff-table tr.history-hunk-peer.active td {
|
|
508
509
|
box-shadow: none;
|
|
509
510
|
}
|
|
510
511
|
.d2h-diff-table tr.diff-active-row td { background: rgba(74, 136, 199, 0.16) !important; }
|
|
@@ -903,7 +904,8 @@ h1 { margin: 0; font-size: 18px; }
|
|
|
903
904
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28);
|
|
904
905
|
overflow: hidden;
|
|
905
906
|
}
|
|
906
|
-
/* Question vs change-request is a small
|
|
907
|
+
/* Question vs change-request is a small monochrome pill: an icon (help-circle / pencil) carries the
|
|
908
|
+
distinction — no color, no heavy left bar. */
|
|
907
909
|
.mc-card-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px 6px; color: var(--muted); }
|
|
908
910
|
.mc-target { margin-left: auto; font: 11px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--muted); opacity: 0.9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 62%; }
|
|
909
911
|
/* While composing a comment, the textarea owns the only caret — hide the file's inline caret and the
|
|
@@ -920,12 +922,12 @@ body.mc-composing .source-row.cursor-line .num { color: inherit; }
|
|
|
920
922
|
body:has(.dock-panel:focus-within) .code-cursor,
|
|
921
923
|
body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
|
|
922
924
|
.mc-kind {
|
|
925
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
923
926
|
font-weight: 700; font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
|
|
924
927
|
padding: 2px 8px; border-radius: 0;
|
|
925
928
|
color: var(--muted); background: color-mix(in srgb, var(--muted) 16%, transparent);
|
|
926
929
|
}
|
|
927
|
-
.mc-
|
|
928
|
-
.mc-card.mc-c .mc-kind { color: var(--token-tag); background: color-mix(in srgb, var(--token-tag) 18%, transparent); }
|
|
930
|
+
.mc-kind-ic { flex: none; }
|
|
929
931
|
.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: 0; }
|
|
930
932
|
.mc-del:hover { color: var(--del-strong); background: color-mix(in srgb, var(--del-strong) 16%, transparent); }
|
|
931
933
|
.mc-card-body { padding: 2px 12px 11px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
@@ -947,7 +949,7 @@ body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
|
|
|
947
949
|
.mc-btn:hover { filter: brightness(1.1); }
|
|
948
950
|
.mc-btn.mc-ghost { background: transparent; border: 1px solid var(--border); color: var(--text); }
|
|
949
951
|
|
|
950
|
-
/* ===== Git history view (Cmd+9): full-screen overlay, commit list (graph lanes) |
|
|
952
|
+
/* ===== Git history view (Cmd+9): full-screen overlay, commit list (graph lanes) | changed files + single-file diff. ===== */
|
|
951
953
|
.history-view { position: fixed; inset: 0; z-index: 75; display: flex; flex-direction: column; background: var(--bg); }
|
|
952
954
|
.history-view.hidden { display: none; }
|
|
953
955
|
.history-bar { flex: none; display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: var(--sidebar); border-bottom: 1px solid var(--border); }
|
|
@@ -956,8 +958,8 @@ body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
|
|
|
956
958
|
.history-search:focus { border-color: var(--active); }
|
|
957
959
|
.history-bar .dock-btn { margin-left: auto; font-size: 16px; }
|
|
958
960
|
.history-body { flex: 1 1 auto; min-height: 0; display: flex; }
|
|
959
|
-
.history-list { flex:
|
|
960
|
-
.history-detail { flex: 1 1
|
|
961
|
+
.history-list { flex: 0 0 min(46vw, 760px); min-width: 320px; overflow: auto; padding: 4px 0; border-right: 1px solid var(--border); }
|
|
962
|
+
.history-detail { flex: 1 1 auto; min-width: 0; overflow: hidden; display: flex; flex-direction: column; }
|
|
961
963
|
/* Rows are a fixed 24px so the per-row graph SVG (also 24px) tiles seamlessly and the lanes connect. */
|
|
962
964
|
.hrow { display: grid; grid-template-columns: var(--hgraph-w, 60px) minmax(0, 1fr) auto auto; align-items: center; gap: 10px; width: 100%; height: 24px; padding: 0 12px 0 0; border: 0; background: transparent; color: var(--text); text-align: left; cursor: pointer; font-size: 12.5px; }
|
|
963
965
|
.hrow:hover { background: color-mix(in srgb, var(--active) 8%, transparent); }
|
|
@@ -975,10 +977,15 @@ body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
|
|
|
975
977
|
.href-branch { color: #7faf6b; border-color: #7faf6b; }
|
|
976
978
|
.href-remote { color: var(--muted); }
|
|
977
979
|
.href-tag { color: #d4a857; border-color: #d4a857; }
|
|
978
|
-
.history-detail-head { padding: 12px 14px; border-bottom: 1px solid var(--border); }
|
|
980
|
+
.history-detail-head { flex: none; padding: 12px 14px; border-bottom: 1px solid var(--border); }
|
|
979
981
|
.hd-msg { font-size: 13px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; margin-bottom: 8px; }
|
|
980
982
|
.hd-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 12px; color: var(--muted); }
|
|
981
983
|
.hd-hash { font-family: Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
984
|
+
.history-workspace { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(190px, 260px) minmax(0, 1fr); }
|
|
985
|
+
.history-files { min-width: 0; overflow: auto; padding: 6px; border-right: 1px solid var(--border); background: var(--sidebar); }
|
|
986
|
+
.history-file { width: 100%; }
|
|
987
|
+
.history-diff { min-width: 0; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
|
|
988
|
+
.history-diff:focus { outline: none; }
|
|
982
989
|
|
|
983
990
|
/* Go-to-line (Cmd/Ctrl+L): a small numeric prompt near the top, like a command palette. */
|
|
984
991
|
.goto-line {
|
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const APP_DISPLAY_NAME = "Monacori";
|
|
7
|
+
const APP_EXECUTABLE_NAME = "monacori";
|
|
8
|
+
const APP_BUNDLE_ID = "dev.happynut.monacori";
|
|
9
|
+
const OLD_APP_NAME = "Electron";
|
|
10
|
+
const APP_BUNDLE = APP_DISPLAY_NAME + ".app";
|
|
11
|
+
const LEGACY_APP_BUNDLES = [OLD_APP_NAME + ".app", APP_EXECUTABLE_NAME + ".app"];
|
|
7
12
|
|
|
8
13
|
// Electron ships Electron.app with bundle name + executable "Electron", which is what macOS shows in
|
|
9
14
|
// the Dock / Cmd+Tab. The npm `mo` model spawns node_modules/electron's executable directly (not a
|
|
10
15
|
// packaged .app), and a directly-spawned GUI process takes its switcher/Dock name from the *executable*
|
|
11
|
-
// name
|
|
12
|
-
//
|
|
16
|
+
// name and LaunchServices cache identity. So we rename Electron.app + its executable, patch the bundle
|
|
17
|
+
// id/name metadata, and repoint electron's path.txt at the branded binary.
|
|
13
18
|
function electronRoot() {
|
|
19
|
+
if (process.env.MONACORI_ELECTRON_ROOT) return process.env.MONACORI_ELECTRON_ROOT;
|
|
14
20
|
if (process.platform !== "darwin") return null;
|
|
15
21
|
const require = createRequire(import.meta.url);
|
|
16
22
|
try {
|
|
@@ -20,54 +26,98 @@ function electronRoot() {
|
|
|
20
26
|
}
|
|
21
27
|
}
|
|
22
28
|
|
|
29
|
+
function setPlistString(plist, key, value) {
|
|
30
|
+
const pattern = new RegExp("(<key>" + key + "</key>\\s*<string>)[^<]*(</string>)");
|
|
31
|
+
if (pattern.test(plist)) {
|
|
32
|
+
return plist.replace(pattern, (_match, prefix, suffix) => prefix + value + suffix);
|
|
33
|
+
}
|
|
34
|
+
return plist.replace("</dict>", "\t<key>" + key + "</key>\n\t<string>" + value + "</string>\n</dict>");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function registerBundle(appDir) {
|
|
38
|
+
if (process.env.MONACORI_SKIP_LSREGISTER === "1") return;
|
|
39
|
+
spawnSync(
|
|
40
|
+
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister",
|
|
41
|
+
["-f", appDir],
|
|
42
|
+
{ stdio: "ignore" },
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findAppBundleEntry(distDir) {
|
|
47
|
+
try {
|
|
48
|
+
const entries = readdirSync(distDir);
|
|
49
|
+
return [APP_BUNDLE, ...LEGACY_APP_BUNDLES].find((bundle) => entries.includes(bundle)) ?? null;
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
23
55
|
function main() {
|
|
24
56
|
const root = electronRoot();
|
|
25
57
|
if (!root) return; // not macOS, or electron missing — nothing to do
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const oldExe = join(macosDir, "Electron");
|
|
30
|
-
const newExe = join(macosDir, APP_NAME);
|
|
58
|
+
const distDir = join(root, "dist");
|
|
59
|
+
const newAppDir = join(root, "dist", APP_BUNDLE);
|
|
60
|
+
const appBundleEntry = findAppBundleEntry(distDir);
|
|
31
61
|
const pathTxt = join(root, "path.txt");
|
|
32
|
-
if (!
|
|
33
|
-
console.warn('monacori: Electron.app not found
|
|
62
|
+
if (!appBundleEntry) {
|
|
63
|
+
console.warn('monacori: Electron.app not found under ' + distDir + ' — skipping rebrand (Dock/menu may show "Electron")');
|
|
34
64
|
return;
|
|
35
65
|
}
|
|
36
66
|
|
|
37
67
|
try {
|
|
38
68
|
let changed = false;
|
|
39
|
-
|
|
69
|
+
let appDir = join(distDir, appBundleEntry);
|
|
70
|
+
|
|
71
|
+
// 1. Rename the app bundle directory itself. Leaving Electron.app on disk can keep LaunchServices keyed
|
|
72
|
+
// to Electron even after CFBundleName is patched. The temp hop makes case-only renames reliable on
|
|
73
|
+
// macOS's common case-insensitive volumes (monacori.app -> Monacori.app).
|
|
74
|
+
if (appBundleEntry !== APP_BUNDLE) {
|
|
75
|
+
const tmpAppDir = join(distDir, ".monacori-app-rename-" + process.pid + "-" + Date.now());
|
|
76
|
+
renameSync(appDir, tmpAppDir);
|
|
77
|
+
renameSync(tmpAppDir, newAppDir);
|
|
78
|
+
appDir = newAppDir;
|
|
79
|
+
changed = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const plistPath = join(appDir, "Contents", "Info.plist");
|
|
83
|
+
const macosDir = join(appDir, "Contents", "MacOS");
|
|
84
|
+
const oldExe = join(macosDir, OLD_APP_NAME);
|
|
85
|
+
const newExe = join(macosDir, APP_EXECUTABLE_NAME);
|
|
86
|
+
if (!existsSync(plistPath)) {
|
|
87
|
+
console.warn('monacori: Info.plist not found at ' + plistPath + ' — skipping rebrand (Dock/menu may show "Electron")');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 2. Bundle metadata: display name -> Monacori, executable -> monacori, bundle id -> monacori.
|
|
40
92
|
const before = readFileSync(plistPath, "utf8");
|
|
41
|
-
const after =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
93
|
+
const after = [
|
|
94
|
+
["CFBundleName", APP_DISPLAY_NAME],
|
|
95
|
+
["CFBundleDisplayName", APP_DISPLAY_NAME],
|
|
96
|
+
["CFBundleExecutable", APP_EXECUTABLE_NAME],
|
|
97
|
+
["CFBundleIdentifier", APP_BUNDLE_ID],
|
|
98
|
+
].reduce((plist, [key, value]) => setPlistString(plist, key, value), before);
|
|
45
99
|
if (after !== before) { writeFileSync(plistPath, after); changed = true; }
|
|
46
100
|
|
|
47
|
-
//
|
|
101
|
+
// 3. Rename the executable so the directly-spawned process is "monacori" (idempotent).
|
|
48
102
|
if (existsSync(oldExe) && !existsSync(newExe)) { renameSync(oldExe, newExe); changed = true; }
|
|
49
103
|
|
|
50
|
-
//
|
|
104
|
+
// 4. Repoint electron's path.txt at the renamed binary so require("electron") resolves it.
|
|
51
105
|
if (existsSync(pathTxt)) {
|
|
52
106
|
const pt = readFileSync(pathTxt, "utf8");
|
|
53
|
-
const fixed =
|
|
107
|
+
const fixed = APP_BUNDLE + "/Contents/MacOS/" + APP_EXECUTABLE_NAME;
|
|
54
108
|
if (fixed !== pt) { writeFileSync(pathTxt, fixed); changed = true; }
|
|
55
109
|
}
|
|
56
110
|
|
|
57
111
|
// Only when something actually changed: refresh LaunchServices so the Dock / Cmd+Tab show "monacori"
|
|
58
112
|
// instead of a cached "Electron". Skipping it when already-branded keeps the startup re-run cheap.
|
|
59
113
|
if (changed) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
["-f", appDir],
|
|
63
|
-
{ stdio: "ignore" },
|
|
64
|
-
);
|
|
65
|
-
console.log('monacori: branded Electron app + executable as "' + APP_NAME + '"');
|
|
114
|
+
registerBundle(appDir);
|
|
115
|
+
console.log('monacori: branded Electron app as "' + APP_DISPLAY_NAME + '"');
|
|
66
116
|
}
|
|
67
117
|
} catch (e) {
|
|
68
118
|
// Surface the reason (perms / read-only) instead of failing SILENTLY — otherwise the Dock/Cmd+Tab/menu
|
|
69
119
|
// keep showing "Electron" with no hint why. Non-fatal: app-main.ts re-runs this at startup.
|
|
70
|
-
console.warn('monacori: could not rebrand the Electron app to "' +
|
|
120
|
+
console.warn('monacori: could not rebrand the Electron app to "' + APP_DISPLAY_NAME + '". Dock/Cmd+Tab/menu may stay "Electron". Reason: ' + (e && e.message ? e.message : e));
|
|
71
121
|
}
|
|
72
122
|
}
|
|
73
123
|
|