ework-web 0.10.38 → 0.10.39
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/package.json +1 -1
- package/src/remote-file.ts +79 -12
package/package.json
CHANGED
package/src/remote-file.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
import { THEME_CSS, escapeHtml, tabNavHTML } from "./render/layout";
|
|
2
|
+
import hljs from "highlight.js";
|
|
3
|
+
import { renderMarkdown } from "./render/markdown";
|
|
4
|
+
|
|
5
|
+
// Extension → hljs language map (mirrors fileview.ts for parity).
|
|
6
|
+
const EXT_LANG: Record<string, string> = {
|
|
7
|
+
js: "javascript", mjs: "javascript", cjs: "javascript", jsx: "javascript",
|
|
8
|
+
ts: "typescript", tsx: "typescript", mts: "typescript", cts: "typescript",
|
|
9
|
+
py: "python", rb: "ruby", go: "go", rs: "rust", java: "java", kt: "kotlin",
|
|
10
|
+
c: "c", h: "c", cpp: "cpp", cc: "cpp", cxx: "cpp", hpp: "cpp", hxx: "cpp",
|
|
11
|
+
cs: "csharp", php: "php", swift: "swift", scala: "scala", sh: "bash",
|
|
12
|
+
bash: "bash", zsh: "bash", fish: "bash", yml: "yaml", yaml: "yaml",
|
|
13
|
+
json: "json", json5: "json", toml: "toml", xml: "xml", html: "xml",
|
|
14
|
+
htm: "xml", css: "css", scss: "scss", less: "less", sql: "sql",
|
|
15
|
+
dockerfile: "dockerfile", makefile: "makefile", lua: "lua", pl: "perl",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function extToLang(p: string): string {
|
|
19
|
+
const base = (p.split("/").pop() || "").toLowerCase();
|
|
20
|
+
if (base === "dockerfile" || base.endsWith(".dockerfile")) return "dockerfile";
|
|
21
|
+
if (base === "makefile" || base.endsWith(".mk")) return "makefile";
|
|
22
|
+
const m = base.match(/\.([a-z0-9]+)$/);
|
|
23
|
+
const ext = m && m[1];
|
|
24
|
+
return ext ? (EXT_LANG[ext] || "") : "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function hljsHighlight(text: string, lang: string): string {
|
|
28
|
+
try {
|
|
29
|
+
return hljs.highlight(text, { language: lang }).value;
|
|
30
|
+
} catch {
|
|
31
|
+
return escapeHtml(text);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
2
34
|
|
|
3
35
|
export class RemoteFileError extends Error {
|
|
4
36
|
status: number;
|
|
@@ -154,31 +186,66 @@ function renderFileContent(
|
|
|
154
186
|
const enc = encodeURIComponent;
|
|
155
187
|
const daemonParam = `&daemon=${enc(endpoint)}`;
|
|
156
188
|
const user = viewerLogin ? { login: viewerLogin, is_admin: 0 } : undefined;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
189
|
+
|
|
190
|
+
const ext = (data.path.split(".").pop() || "").toLowerCase();
|
|
191
|
+
const isMd = ext === "md" || ext === "markdown";
|
|
192
|
+
const lang = extToLang(data.path);
|
|
193
|
+
const fullText = data.rows.map((r) => r.t).join("\n");
|
|
194
|
+
const shownBytes = data.rows.reduce((s, r) => s + r.t.length + 1, 0);
|
|
195
|
+
|
|
196
|
+
let body: string;
|
|
197
|
+
if (isMd) {
|
|
198
|
+
body = `<div class="md-render">${renderMarkdown(fullText, "")}</div>`;
|
|
199
|
+
} else if (lang && shownBytes <= 100000) {
|
|
200
|
+
const nums = data.rows.map((r) => r.n).join("\n");
|
|
201
|
+
body = `<div class="fv-code"><pre class="fv-gutter">${escapeHtml(nums)}</pre><pre class="fv-src"><code class="hljs language-${escapeHtml(lang)}">${hljsHighlight(fullText, lang)}</code></pre></div>`;
|
|
202
|
+
} else {
|
|
203
|
+
body = `<pre class="fv-plain"><code>${data.rows.map((r) => `<span class="ln"><span class="lnn">${r.n}</span><span class="lnc">${escapeHtml(r.t)}</span></span>`).join("")}</code></pre>`;
|
|
204
|
+
}
|
|
160
205
|
|
|
161
206
|
return `<!doctype html>
|
|
162
207
|
<html lang="zh"><head><meta charset="utf-8">
|
|
163
208
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
164
209
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
165
210
|
<title>ework-web · ${escapeHtml(data.path)}</title>
|
|
211
|
+
<link rel="stylesheet" href="/static/highlight.css">
|
|
166
212
|
<style>${THEME_CSS}
|
|
167
213
|
.nav{display:flex;align-items:center;gap:.5rem;padding:.55rem 1rem;background:var(--header-bg);color:var(--header-text);font-size:13px}
|
|
168
214
|
.nav a{color:var(--header-text);opacity:.95}
|
|
169
|
-
.wrap{max-width:
|
|
215
|
+
.wrap{max-width:1100px;margin:0 auto;padding:1rem}
|
|
170
216
|
h1{font-size:14px;margin:0 0 .3rem;font-family:ui-monospace,monospace;word-break:break-all}
|
|
171
217
|
.remote-badge{display:inline-block;background:#1f6feb33;color:#58a6ff;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;margin-left:.5rem}
|
|
172
218
|
.note{color:var(--text-muted);font-size:12px;margin:0 0 .5rem}
|
|
173
219
|
.parent-link{font-size:13px;margin-bottom:.4rem}
|
|
174
220
|
.parent-link a{color:var(--text-muted)}
|
|
175
|
-
.
|
|
176
|
-
.
|
|
177
|
-
.
|
|
178
|
-
.
|
|
179
|
-
.
|
|
180
|
-
.
|
|
181
|
-
.
|
|
221
|
+
.fv-code{display:flex;border:1px solid var(--border);border-radius:8px;overflow:auto;font-size:12.5px;line-height:1.5}
|
|
222
|
+
.fv-gutter{background:var(--bg-muted);color:var(--text-muted);text-align:right;padding:.6rem .7rem;user-select:none;white-space:pre;flex-shrink:0;border:none;margin:0}
|
|
223
|
+
.fv-src{margin:0;flex:1;overflow:auto;background:var(--bg-elev);padding:.6rem .8rem;border:none}
|
|
224
|
+
.fv-src code{background:none;padding:0;white-space:pre;font-size:12.5px}
|
|
225
|
+
.fv-plain{background:var(--bg-elev);border:1px solid var(--border);border-radius:8px;padding:.6rem 0;overflow:auto;font-size:12.5px;line-height:1.5}
|
|
226
|
+
.fv-plain .ln{display:flex}
|
|
227
|
+
.fv-plain .lnn{user-select:none;text-align:right;color:var(--text-muted);padding:0 .7rem 0 .8rem;min-width:3.5em;flex-shrink:0;border-right:1px solid var(--border);background:var(--bg-muted)}
|
|
228
|
+
.fv-plain .lnc{padding:0 .8rem;white-space:pre;overflow-wrap:anywhere}
|
|
229
|
+
.md-render{max-width:820px;margin:0 auto;padding:1rem 1.5rem 5rem;font-size:14.5px;line-height:1.7;color:var(--text)}
|
|
230
|
+
.md-render h1,.md-render h2,.md-render h3,.md-render h4{line-height:1.3;margin:1.4em 0 .6em;font-weight:600}
|
|
231
|
+
.md-render h1{font-size:1.7em;border-bottom:1px solid var(--border);padding-bottom:.3em}
|
|
232
|
+
.md-render h2{font-size:1.4em;border-bottom:1px solid var(--border);padding-bottom:.3em}
|
|
233
|
+
.md-render h3{font-size:1.2em}
|
|
234
|
+
.md-render h4{font-size:1.05em}
|
|
235
|
+
.md-render p{margin:.6em 0}
|
|
236
|
+
.md-render ul,.md-render ol{margin:.6em 0;padding-left:1.6em}
|
|
237
|
+
.md-render li{margin:.25em 0}
|
|
238
|
+
.md-render a{color:var(--accent);text-decoration:none}
|
|
239
|
+
.md-render a:hover{text-decoration:underline}
|
|
240
|
+
.md-render code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.88em;background:var(--bg-muted);padding:.15em .35em;border-radius:4px}
|
|
241
|
+
.md-render pre{background:var(--bg-elev);border:1px solid var(--border);border-radius:8px;padding:.7rem 1rem;overflow:auto;margin:.8em 0}
|
|
242
|
+
.md-render pre code{background:none;padding:0;font-size:13px}
|
|
243
|
+
.md-render blockquote{border-left:3px solid var(--border);margin:.8em 0;padding:.2em 0 .2em 1em;color:var(--text-muted)}
|
|
244
|
+
.md-render table{border-collapse:collapse;margin:.8em 0;width:100%}
|
|
245
|
+
.md-render th,.md-render td{border:1px solid var(--border);padding:.4em .7em;text-align:left}
|
|
246
|
+
.md-render th{background:var(--bg-muted);font-weight:600}
|
|
247
|
+
.md-render img{max-width:100%}
|
|
248
|
+
.md-render hr{border:none;border-top:1px solid var(--border);margin:1.4em 0}
|
|
182
249
|
</style></head><body>
|
|
183
250
|
<header class="nav"><a href="/" style="color:var(--header-text)">🏠 ework-web</a></header>
|
|
184
251
|
${tabNavHTML("sessions", user)}
|
|
@@ -186,7 +253,7 @@ ${tabNavHTML("sessions", user)}
|
|
|
186
253
|
<div class="parent-link">📁 <a href="/file?path=${enc(data.path.split("/").slice(0, -1).join("/") || "/")}${daemonParam}">..</a></div>
|
|
187
254
|
<h1>${escapeHtml(data.path)}<span class="remote-badge">远程 ${daemonLabel}</span></h1>
|
|
188
255
|
${data.note ? `<p class="note">${escapeHtml(data.note)}</p>` : ""}
|
|
189
|
-
|
|
256
|
+
${body}
|
|
190
257
|
</main></body></html>`;
|
|
191
258
|
}
|
|
192
259
|
|