@evandu/super-pi 0.1.113 → 0.1.115

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.
Files changed (28) hide show
  1. package/README.md +16 -0
  2. package/bin/super-pi.js +95 -3
  3. package/dist/client/.super-pi-client-sources.json +3 -3
  4. package/dist/client/assets/{CodeMirrorEditor-moFTk5SE.js → CodeMirrorEditor-DNLm2zT6.js} +2 -2
  5. package/dist/client/assets/{dist-DQjJMys5.js → dist-2zLLUXCo.js} +1 -1
  6. package/dist/client/assets/{dist-BsO40qxQ.js → dist-4qEFEbMF.js} +1 -1
  7. package/dist/client/assets/{dist-DuWhzonJ.js → dist-BLldidtK.js} +1 -1
  8. package/dist/client/assets/{dist-DrbUrVWB.js → dist-BO4YrDmO.js} +1 -1
  9. package/dist/client/assets/{dist-DIfmMr8s.js → dist-BTsfS8CA.js} +1 -1
  10. package/dist/client/assets/{dist-Dnr5BxAi.js → dist-BVCGM9Bd.js} +1 -1
  11. package/dist/client/assets/{dist-BR4s0dNg.js → dist-B_N2ELl5.js} +1 -1
  12. package/dist/client/assets/{dist-TgNJUr7p.js → dist-BoV9nE13.js} +1 -1
  13. package/dist/client/assets/{dist-DPDGd2jl.js → dist-CEJcHfEn.js} +1 -1
  14. package/dist/client/assets/{dist-D9m04q-s.js → dist-CW83qn3P.js} +1 -1
  15. package/dist/client/assets/{dist-CCYnr6ul.js → dist-CezTi1ET.js} +1 -1
  16. package/dist/client/assets/{dist-BUuPRG15.js → dist-DszqHTui.js} +1 -1
  17. package/dist/client/assets/{dist-rhPxFuD1.js → dist-DuHJr7vQ.js} +1 -1
  18. package/dist/client/assets/{dist-Bds_PUYK.js → dist-JI_7suRx.js} +1 -1
  19. package/dist/client/assets/{dist-CL65aMXY.js → dist-pJBZJJnA.js} +1 -1
  20. package/dist/client/assets/{dist-DPvy57Ph.js → dist-zwqOqWyp.js} +1 -1
  21. package/dist/client/assets/{index-BixdV7aQ.js → index-CLoO6IHy.js} +2 -2
  22. package/dist/client/index.html +1 -1
  23. package/dist/extension.js +1 -1
  24. package/dist/server/application/conversation-service.js +8 -0
  25. package/dist/server/index.js +14 -4
  26. package/dist/server/logging.d.ts +32 -0
  27. package/dist/server/logging.js +132 -0
  28. package/package.json +2 -1
package/README.md CHANGED
@@ -56,6 +56,22 @@ super-pi stop # Stop the background server
56
56
  super-pi restart # Restart the server
57
57
  ```
58
58
 
59
+ If the panel suddenly stops working and the browser only says "connecting", the server may have
60
+ died. Its log says why:
61
+
62
+ ```bash
63
+ super-pi logs # The last 200 lines of the server log
64
+ super-pi logs 50 # The last 50 lines
65
+ super-pi logs --follow # Keep printing new lines (Ctrl+C to stop)
66
+ super-pi logs --path # Where the log file is
67
+ super-pi logs --clear # Empty the log file
68
+ ```
69
+
70
+ The log lives in `<data directory>/logs/server.log` (`super-pi logs --path` prints the exact path;
71
+ `SUPER_PI_DATA_DIR` moves the whole data directory). A separate `logs/heartbeat.txt` is touched
72
+ every minute while the server lives, so `super-pi logs` can also tell you when the server was last
73
+ alive - which is how a crash that left no message at all still gets a time on it.
74
+
59
75
  To start Super Pi automatically when the current user signs in, run:
60
76
 
61
77
  ```bash
package/bin/super-pi.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFile, spawn } from "node:child_process";
3
- import { existsSync, readFileSync } from "node:fs";
3
+ import { existsSync, readFileSync, statSync, openSync, readSync, closeSync, truncateSync } from "node:fs";
4
4
  import { mkdir, rm, writeFile } from "node:fs/promises";
5
5
  import { homedir } from "node:os";
6
6
  import { dirname, join, resolve } from "node:path";
@@ -38,7 +38,7 @@ function ownVersion() {
38
38
  /** The line that names what is running, so two installations can be told apart at a glance. */
39
39
  function runningBanner(url) {
40
40
  const { version, location } = ownVersion();
41
- return `Super Pi v${version} is running at ${url}\n installed at ${location}`;
41
+ return `Super Pi v${version} is running at ${url}\n installed at ${location}\n log file: ${logFile()}`;
42
42
  }
43
43
 
44
44
  function options(args) {
@@ -63,7 +63,75 @@ async function running(port) {
63
63
  }
64
64
  async function stop(port) { try { const headers = process.env.SUPER_PI_ACCESS_TOKEN ? { authorization: `Bearer ${process.env.SUPER_PI_ACCESS_TOKEN}` } : {}; const response = await fetch(`http://127.0.0.1:${port}/api/shutdown`, { method: "POST", headers, signal: AbortSignal.timeout(3000) }); return response.ok || response.status === 202; } catch { return false; } }
65
65
  function openBrowser(url) { const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd.exe" : "xdg-open"; const args = platform === "darwin" ? [url] : platform === "win32" ? ["/c", "start", "", url] : [url]; spawn(command, args, { detached: true, stdio: "ignore", windowsHide: true }).unref(); }
66
- function usage() { console.log("Usage: super-pi|super_pi <start|stop|restart|update|diagnose|autostart> [options]"); console.log(" autostart enable|disable|status Configure startup at sign-in"); console.log(" diagnose Measure where a message spends its time"); console.log(" --port PORT Server port (default: 3080)"); console.log(" --host HOST Server host (default: 0.0.0.0)"); console.log(" --no-browser Do not open a browser"); }
66
+ function usage() { console.log("Usage: super-pi|super_pi <start|stop|restart|update|diagnose|logs|autostart> [options]"); console.log(" autostart enable|disable|status Configure startup at sign-in"); console.log(" diagnose Measure where a message spends its time"); console.log(" logs [N] [--follow] Show the server log (last N lines, default 200)"); console.log(" logs --path Print the log file's path"); console.log(" logs --clear Empty the log file"); console.log(" --port PORT Server port (default: 3080)"); console.log(" --host HOST Server host (default: 0.0.0.0)"); console.log(" --no-browser Do not open a browser"); }
67
+
68
+ /**
69
+ * WHERE THE SERVER KEEPS ITS LOG FILE.
70
+ *
71
+ * The same rule the server itself uses when it picks its data directory, mirrored here on purpose:
72
+ * the CLI has to find the file the server wrote, and the server may be a DIFFERENT installation of
73
+ * Super Pi than the CLI that is asking (the global install and the one the `/super_pi` extension
74
+ * loads are two separate installs by design). `SUPER_PI_DATA_DIR` overrides both, which is what a
75
+ * person with a custom data directory needs.
76
+ */
77
+ function dataDir() {
78
+ if (process.env.SUPER_PI_DATA_DIR) return resolve(process.env.SUPER_PI_DATA_DIR);
79
+ const local = join(root, ".super-pi");
80
+ if (!root.match(/[\\/]node_modules[\\/]/i) && existsSync(local)) return local;
81
+ return join(home, ".super-pi");
82
+ }
83
+ function logFile() { return join(dataDir(), "logs", "server.log"); }
84
+ function heartbeatFile() { return join(dataDir(), "logs", "heartbeat.txt"); }
85
+
86
+ /** "How long ago was the server alive?" - the answer a silent death cannot give by itself. */
87
+ function lastAlive() {
88
+ const file = heartbeatFile();
89
+ if (!existsSync(file)) return null;
90
+ try {
91
+ const at = statSync(file).mtimeMs;
92
+ const minutes = Math.max(0, Math.round((Date.now() - at) / 60000));
93
+ const when = new Date(at).toLocaleString();
94
+ return minutes < 1 ? `${when} (just now)` : `${when} (${minutes} minute${minutes === 1 ? "" : "s"} ago)`;
95
+ } catch { return null; }
96
+ }
97
+
98
+
99
+ /** The last `lines` lines of the log file, read from the end so a big file stays cheap to open. */
100
+ function readLogTail(file, lines) {
101
+ if (!existsSync(file)) return [];
102
+ const size = statSync(file).size;
103
+ if (size === 0) return [];
104
+ const length = Math.min(size, 512 * 1024);
105
+ const buffer = Buffer.alloc(length);
106
+ const fd = openSync(file, "r");
107
+ try { readSync(fd, buffer, 0, length, size - length); } finally { closeSync(fd); }
108
+ const all = buffer.toString("utf8").split(/\r?\n/);
109
+ if (all.length > 0 && all[all.length - 1] === "") all.pop();
110
+ return all.slice(Math.max(0, all.length - lines));
111
+ }
112
+
113
+ /** Print whatever the log file gains from now on, until Ctrl+C. */
114
+ function followLog(file) {
115
+ let offset = existsSync(file) ? statSync(file).size : 0;
116
+ const tick = () => {
117
+ try {
118
+ if (!existsSync(file)) return;
119
+ const size = statSync(file).size;
120
+ // A SMALLER FILE MEANS THE LOG WAS ROTATED (or cleared): start over from the top.
121
+ if (size < offset) offset = 0;
122
+ if (size <= offset) return;
123
+ const buffer = Buffer.alloc(size - offset);
124
+ const fd = openSync(file, "r");
125
+ try { readSync(fd, buffer, 0, buffer.length, offset); } finally { closeSync(fd); }
126
+ offset = size;
127
+ process.stdout.write(buffer.toString("utf8"));
128
+ } catch { /* the file is being rotated under us; the next tick picks it up */ }
129
+ };
130
+ tick();
131
+ const timer = setInterval(tick, 400);
132
+ process.on("SIGINT", () => { clearInterval(timer); process.exit(0); });
133
+ }
134
+
67
135
  function paths() { if (platform === "win32") return { task: "Super Pi" }; if (platform === "darwin") return { file: join(home, "Library", "LaunchAgents", "com.evandu.super-pi.plist") }; return { file: join(process.env.XDG_CONFIG_HOME ?? join(home, ".config"), "systemd", "user", "super-pi.service") }; }
68
136
  async function system(command, args) { if (process.env.SUPER_PI_AUTOSTART_DRY_RUN === "1") { console.log(`[dry-run] ${command} ${args.join(" ")}`); return; } await execFileAsync(command, args, { windowsHide: true }); }
69
137
  async function enable(value) {
@@ -104,6 +172,30 @@ try {
104
172
  console.log(renderReport(result));
105
173
  process.exit(result.error ? 1 : 0);
106
174
  }
175
+ if (command === "logs" || command === "log") {
176
+ // HOW THE SERVER DIED, IN ONE COMMAND.
177
+ //
178
+ // The server runs detached with its console thrown away, so this file is the only record of it.
179
+ // It is written synchronously as the server speaks, so the last lines are always the crash.
180
+ const file = logFile();
181
+ const count = Number.parseInt(args.find((a) => /^\d+$/.test(a)) ?? "200", 10);
182
+ const follow = args.some((a) => a === "--follow" || a === "-f");
183
+ if (args.includes("--path")) { console.log(file); process.exit(0); }
184
+ if (args.includes("--clear")) { if (existsSync(file)) truncateSync(file, 0); console.log(`Cleared ${file}`); process.exit(0); }
185
+ if (!existsSync(file)) { console.log(`No log file yet at ${file}\nStart Super Pi with: super-pi start`); process.exit(0); }
186
+ console.log(`Log file: ${file}`);
187
+ const alive = lastAlive();
188
+ console.log(alive ? `Last alive: ${alive}` : "Last alive: unknown (no heartbeat file - the server may never have started)");
189
+ for (const line of readLogTail(file, Number.isInteger(count) && count > 0 ? count : 200)) console.log(line);
190
+ if (follow) {
191
+ // FOLLOWING MEANS THIS COMMAND DOES NOT END. The promise below never settles; `followLog` ends
192
+ // the process on Ctrl+C. Without it this branch would fall through to the "unknown command"
193
+ // check below and take the tail down with it.
194
+ followLog(file);
195
+ await new Promise(() => {});
196
+ }
197
+ process.exit(0);
198
+ }
107
199
  if (!["start", "stop", "restart", "update"].includes(command)) throw new Error(`Unknown command: ${command}`);
108
200
  if (command === "update") { const npm = platform === "win32" ? "npm.cmd" : "npm"; const args = prefix ? ["install", "--prefix", prefix, "@evandu/super-pi"] : ["install", "-g", "@evandu/super-pi"]; const child = spawn(npm, args, { stdio: "inherit", shell: platform === "win32", env: process.env }); const code = await new Promise((resolve) => child.on("close", resolve)); if (code !== 0) process.exit(code ?? 1); }
109
201
  const value = options(args);
@@ -1,7 +1,7 @@
1
1
  {
2
- "hash": "15e1b290813d3bd00c8d71222c3f91a0966d4149359e860b5f9d6e5134dc5662",
2
+ "hash": "5e32194500b5aa38475456bd13d6b7c43665bff2eec3bb51948e105965e94f17",
3
3
  "files": {
4
- "src/client/App.tsx": "a73f19a7001bcc2cee5c1359fe03b65e3ca76a4bce9f2f6a4d5e92ba0fcb70bf",
4
+ "src/client/App.tsx": "9de9a4876ad5706017e2eefaa72cfbc2eded3442165320699db1e57ad196968c",
5
5
  "src/client/CodeMirrorEditor.tsx": "0434cb534d521d1ac76101f84af1dd02eea11b6b609d962b7ce519c6b28cc1fe",
6
6
  "src/client/FilesPanel.tsx": "44aa3f78c7016353cc8009820fa885c34bb250c0fd185fe435a8449bc6e64701",
7
7
  "src/client/GitPanel.tsx": "7c831348542435e02ddb99d3ae1ede072293bd82c1e53438ca7fe24629fb73b1",
@@ -28,5 +28,5 @@
28
28
  "src/client/types.ts": "fb2cf2889d695f102e0e7b02090ce0d96b351a4c6343e31fd8b88ac4b51a5781",
29
29
  "src/client/vite-env.d.ts": "65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5"
30
30
  },
31
- "recordedAt": "2026-10-23T03:40:19.344Z"
31
+ "recordedAt": "2026-10-23T04:13:57.736Z"
32
32
  }
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dist-Dnr5BxAi.js","assets/index-BixdV7aQ.js","assets/index-CGXMw9LP.css","assets/dist-CCYnr6ul.js","assets/dist-BsO40qxQ.js","assets/dist-DPDGd2jl.js","assets/dist-DPvy57Ph.js","assets/dist-DIfmMr8s.js","assets/dist-DQjJMys5.js","assets/dist-DrbUrVWB.js","assets/dist-Bds_PUYK.js","assets/dist-CL65aMXY.js","assets/dist-BUuPRG15.js","assets/dist-D9m04q-s.js","assets/dist-BR4s0dNg.js","assets/dist-DuWhzonJ.js","assets/dist-rhPxFuD1.js","assets/dist-TgNJUr7p.js"])))=>i.map(i=>d[i]);
2
- import{a as e,n as t,r as n,t as r}from"./index-BixdV7aQ.js";var i=e(n(),1),a=t(),o=262144,s=131072;function c(e){return e.split(`.`).pop()?.toLowerCase()??``}function l(e){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()}function u(e,t){return e.HighlightStyle.define([{tag:t.tags.keyword,color:l(`--cm-keyword`)},{tag:t.tags.string,color:l(`--cm-string`)},{tag:t.tags.number,color:l(`--cm-number`)},{tag:t.tags.comment,color:l(`--cm-comment`),fontStyle:`italic`},{tag:t.tags.function(t.tags.variableName),color:l(`--cm-function`)},{tag:t.tags.typeName,color:l(`--cm-type`)},{tag:t.tags.className,color:l(`--cm-type`)},{tag:t.tags.propertyName,color:l(`--cm-property`)},{tag:t.tags.operator,color:l(`--cm-operator`)},{tag:t.tags.variableName,color:l(`--cm-variable`)}])}function d({path:e,value:t,onChange:n,jumpToLine:l,onSave:d}){let f=(0,i.useRef)(null),p=(0,i.useRef)(null),m=(0,i.useRef)(null),h=(0,i.useRef)(null),g=(0,i.useRef)(null),_=(0,i.useRef)(n),v=(0,i.useRef)(d);_.current=n,v.current=d;let[y,b]=(0,i.useState)(!1),[x,S]=(0,i.useState)(!1),[C,w]=(0,i.useState)(`0,0`);(0,i.useEffect)(()=>{let n=!1,i,a,s,l;return(async()=>{let[d,y,x,C,T,E,D,O,k,A,j,M,N,P]=await Promise.all([r(()=>import(`./dist-Dnr5BxAi.js`).then(e=>e.x),__vite__mapDeps([0,1,2])),r(()=>import(`./dist-CCYnr6ul.js`).then(e=>e.s),__vite__mapDeps([3,1,2,0])),r(()=>import(`./dist-BsO40qxQ.js`),__vite__mapDeps([4,0,1,2,3,5,6])),r(()=>import(`./dist-DIfmMr8s.js`),__vite__mapDeps([7,0,1,2,3])),r(()=>import(`./dist-DPvy57Ph.js`),__vite__mapDeps([6,0,1,2,3,5])),r(()=>import(`./dist-DPDGd2jl.js`).then(e=>e.n),__vite__mapDeps([5,1,2])),r(()=>import(`./dist-DQjJMys5.js`).then(e=>e.t),__vite__mapDeps([8,1,2,0,3,5,6,9,10])),r(()=>import(`./dist-CL65aMXY.js`),__vite__mapDeps([11,5,1,2,6,0,3,9,10])),r(()=>import(`./dist-BUuPRG15.js`),__vite__mapDeps([12,5,1,2,6,0,3,9])),r(()=>import(`./dist-D9m04q-s.js`),__vite__mapDeps([13,0,1,2,3,5,6,10,14,9,15,8])),r(()=>import(`./dist-DuWhzonJ.js`).then(e=>e.r),__vite__mapDeps([15,1,2,5,6,0,3,9])),r(()=>import(`./dist-BR4s0dNg.js`),__vite__mapDeps([14,0,1,2,3,5,6,9,15,8,10])),r(()=>import(`./dist-rhPxFuD1.js`),__vite__mapDeps([16,5,1,2,6,0,3,9])),r(()=>import(`./dist-TgNJUr7p.js`),__vite__mapDeps([17,5,1,2,6,0,3,9,10]))]);if(n||!f.current)return;s=T,l=E,h.current=d.Annotation.define(),g.current=d.Transaction.addToHistory;let F=c(e),I=F===`js`||F===`jsx`||F===`mjs`||F===`cjs`?D.javascript():F===`ts`||F===`tsx`?D.javascript({typescript:!0,jsx:F===`tsx`}):F===`py`?O.python():F===`json`?k.json():F===`md`||F===`markdown`?A.markdown():F===`css`?j.css():F===`html`||F===`htm`?M.html():F===`rs`?N.rust():F===`go`?P.go():null,L=t.length<=o&&I!==null;a=new d.Compartment;let R=[y.lineNumbers(),y.highlightActiveLine(),y.drawSelection(),x.history(),y.keymap.of([x.indentWithTab,...x.defaultKeymap,...x.historyKeymap,...C.searchKeymap,{key:`Mod-s`,run:()=>(v.current(),!0)}]),y.EditorView.updateListener.of(e=>{e.docChanged&&!(h.current&&e.transactions.some(e=>e.annotation(h.current)===!0))&&_.current(e.state.doc.toString()),e.selectionSet&&w(`${e.state.selection.main.from},${e.state.selection.main.to}`)}),y.EditorView.domEventHandlers({mousedown:(e,t)=>(t.focus(),!1)})];if(I&&R.push(I),L&&a&&s&&l&&R.push(a.of(s.syntaxHighlighting(u(s,l)))),i=new y.EditorView({state:d.EditorState.create({doc:t,extensions:R}),parent:f.current}),n){i.destroy();return}p.current=i,b(L),S(!0);let z=new MutationObserver(()=>{let e=p.current;e&&L&&a&&s&&l&&e.dispatch({effects:a.reconfigure(s.syntaxHighlighting(u(s,l)))})});m.current=z,z.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]})})(),()=>{n=!0,m.current?.disconnect(),m.current=null,i?.destroy(),p.current=null,S(!1),f.current&&(f.current.textContent=``)}},[e]),(0,i.useEffect)(()=>{let e=p.current;if(!e)return;let n=e.state.doc.toString();n!==t&&e.dispatch({changes:{from:0,to:n.length,insert:t},annotations:h.current?h.current.of(!0):void 0})},[t]),(0,i.useEffect)(()=>{let e=p.current;if(!e||!l)return;let t=e.state.doc.line(Math.min(Math.max(1,l.line),e.state.doc.lines));e.dispatch({selection:{anchor:t.from,head:t.to},scrollIntoView:!0}),e.focus()},[l,x]);let T=p.current?.state.doc.toString()??t,E=T.length<=s?T:T.slice(0,s);return(0,a.jsxs)(`div`,{className:`file-cm-wrap`,"data-file-text":e,"data-file-content":E,"data-file-content-truncated":T.length>s?`1`:`0`,"data-file-selection":C,"data-file-editor-ready":x?`1`:`0`,onMouseDown:()=>p.current?.focus(),children:[(0,a.jsx)(`div`,{className:`file-cm`,ref:f,"aria-label":`编辑 ${e}`}),!x&&(0,a.jsx)(`span`,{className:`file-cm-status`,"data-file-editor-loading":`1`,children:`⌛ 正在加载编辑器…`}),x&&!y&&(0,a.jsx)(`span`,{className:`file-cm-status`,"data-file-highlight-status":`plain`,children:`纯文本`})]})}export{d as CodeMirrorEditor};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dist-BVCGM9Bd.js","assets/index-CLoO6IHy.js","assets/index-CGXMw9LP.css","assets/dist-CezTi1ET.js","assets/dist-4qEFEbMF.js","assets/dist-CEJcHfEn.js","assets/dist-zwqOqWyp.js","assets/dist-BTsfS8CA.js","assets/dist-2zLLUXCo.js","assets/dist-BO4YrDmO.js","assets/dist-JI_7suRx.js","assets/dist-pJBZJJnA.js","assets/dist-DszqHTui.js","assets/dist-CW83qn3P.js","assets/dist-B_N2ELl5.js","assets/dist-BLldidtK.js","assets/dist-DuHJr7vQ.js","assets/dist-BoV9nE13.js"])))=>i.map(i=>d[i]);
2
+ import{a as e,n as t,r as n,t as r}from"./index-CLoO6IHy.js";var i=e(n(),1),a=t(),o=262144,s=131072;function c(e){return e.split(`.`).pop()?.toLowerCase()??``}function l(e){return getComputedStyle(document.documentElement).getPropertyValue(e).trim()}function u(e,t){return e.HighlightStyle.define([{tag:t.tags.keyword,color:l(`--cm-keyword`)},{tag:t.tags.string,color:l(`--cm-string`)},{tag:t.tags.number,color:l(`--cm-number`)},{tag:t.tags.comment,color:l(`--cm-comment`),fontStyle:`italic`},{tag:t.tags.function(t.tags.variableName),color:l(`--cm-function`)},{tag:t.tags.typeName,color:l(`--cm-type`)},{tag:t.tags.className,color:l(`--cm-type`)},{tag:t.tags.propertyName,color:l(`--cm-property`)},{tag:t.tags.operator,color:l(`--cm-operator`)},{tag:t.tags.variableName,color:l(`--cm-variable`)}])}function d({path:e,value:t,onChange:n,jumpToLine:l,onSave:d}){let f=(0,i.useRef)(null),p=(0,i.useRef)(null),m=(0,i.useRef)(null),h=(0,i.useRef)(null),g=(0,i.useRef)(null),_=(0,i.useRef)(n),v=(0,i.useRef)(d);_.current=n,v.current=d;let[y,b]=(0,i.useState)(!1),[x,S]=(0,i.useState)(!1),[C,w]=(0,i.useState)(`0,0`);(0,i.useEffect)(()=>{let n=!1,i,a,s,l;return(async()=>{let[d,y,x,C,T,E,D,O,k,A,j,M,N,P]=await Promise.all([r(()=>import(`./dist-BVCGM9Bd.js`).then(e=>e.x),__vite__mapDeps([0,1,2])),r(()=>import(`./dist-CezTi1ET.js`).then(e=>e.s),__vite__mapDeps([3,1,2,0])),r(()=>import(`./dist-4qEFEbMF.js`),__vite__mapDeps([4,0,1,2,3,5,6])),r(()=>import(`./dist-BTsfS8CA.js`),__vite__mapDeps([7,0,1,2,3])),r(()=>import(`./dist-zwqOqWyp.js`),__vite__mapDeps([6,0,1,2,3,5])),r(()=>import(`./dist-CEJcHfEn.js`).then(e=>e.n),__vite__mapDeps([5,1,2])),r(()=>import(`./dist-2zLLUXCo.js`).then(e=>e.t),__vite__mapDeps([8,1,2,0,3,5,6,9,10])),r(()=>import(`./dist-pJBZJJnA.js`),__vite__mapDeps([11,5,1,2,6,0,3,9,10])),r(()=>import(`./dist-DszqHTui.js`),__vite__mapDeps([12,5,1,2,6,0,3,9])),r(()=>import(`./dist-CW83qn3P.js`),__vite__mapDeps([13,0,1,2,3,5,6,10,14,9,15,8])),r(()=>import(`./dist-BLldidtK.js`).then(e=>e.r),__vite__mapDeps([15,1,2,5,6,0,3,9])),r(()=>import(`./dist-B_N2ELl5.js`),__vite__mapDeps([14,0,1,2,3,5,6,9,15,8,10])),r(()=>import(`./dist-DuHJr7vQ.js`),__vite__mapDeps([16,5,1,2,6,0,3,9])),r(()=>import(`./dist-BoV9nE13.js`),__vite__mapDeps([17,5,1,2,6,0,3,9,10]))]);if(n||!f.current)return;s=T,l=E,h.current=d.Annotation.define(),g.current=d.Transaction.addToHistory;let F=c(e),I=F===`js`||F===`jsx`||F===`mjs`||F===`cjs`?D.javascript():F===`ts`||F===`tsx`?D.javascript({typescript:!0,jsx:F===`tsx`}):F===`py`?O.python():F===`json`?k.json():F===`md`||F===`markdown`?A.markdown():F===`css`?j.css():F===`html`||F===`htm`?M.html():F===`rs`?N.rust():F===`go`?P.go():null,L=t.length<=o&&I!==null;a=new d.Compartment;let R=[y.lineNumbers(),y.highlightActiveLine(),y.drawSelection(),x.history(),y.keymap.of([x.indentWithTab,...x.defaultKeymap,...x.historyKeymap,...C.searchKeymap,{key:`Mod-s`,run:()=>(v.current(),!0)}]),y.EditorView.updateListener.of(e=>{e.docChanged&&!(h.current&&e.transactions.some(e=>e.annotation(h.current)===!0))&&_.current(e.state.doc.toString()),e.selectionSet&&w(`${e.state.selection.main.from},${e.state.selection.main.to}`)}),y.EditorView.domEventHandlers({mousedown:(e,t)=>(t.focus(),!1)})];if(I&&R.push(I),L&&a&&s&&l&&R.push(a.of(s.syntaxHighlighting(u(s,l)))),i=new y.EditorView({state:d.EditorState.create({doc:t,extensions:R}),parent:f.current}),n){i.destroy();return}p.current=i,b(L),S(!0);let z=new MutationObserver(()=>{let e=p.current;e&&L&&a&&s&&l&&e.dispatch({effects:a.reconfigure(s.syntaxHighlighting(u(s,l)))})});m.current=z,z.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]})})(),()=>{n=!0,m.current?.disconnect(),m.current=null,i?.destroy(),p.current=null,S(!1),f.current&&(f.current.textContent=``)}},[e]),(0,i.useEffect)(()=>{let e=p.current;if(!e)return;let n=e.state.doc.toString();n!==t&&e.dispatch({changes:{from:0,to:n.length,insert:t},annotations:h.current?h.current.of(!0):void 0})},[t]),(0,i.useEffect)(()=>{let e=p.current;if(!e||!l)return;let t=e.state.doc.line(Math.min(Math.max(1,l.line),e.state.doc.lines));e.dispatch({selection:{anchor:t.from,head:t.to},scrollIntoView:!0}),e.focus()},[l,x]);let T=p.current?.state.doc.toString()??t,E=T.length<=s?T:T.slice(0,s);return(0,a.jsxs)(`div`,{className:`file-cm-wrap`,"data-file-text":e,"data-file-content":E,"data-file-content-truncated":T.length>s?`1`:`0`,"data-file-selection":C,"data-file-editor-ready":x?`1`:`0`,onMouseDown:()=>p.current?.focus(),children:[(0,a.jsx)(`div`,{className:`file-cm`,ref:f,"aria-label":`编辑 ${e}`}),!x&&(0,a.jsx)(`span`,{className:`file-cm-status`,"data-file-editor-loading":`1`,children:`⌛ 正在加载编辑器…`}),x&&!y&&(0,a.jsx)(`span`,{className:`file-cm-status`,"data-file-highlight-status":`plain`,children:`纯文本`})]})}export{d as CodeMirrorEditor};