@lyhue1991/dsh-soup 0.5.5 → 0.5.6

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.
@@ -65,6 +65,7 @@ export var DICT = {
65
65
  'files.readFail': '读取文件失败',
66
66
  'files.reload': '重载',
67
67
  'files.reloadTitle': '从磁盘重新读取(刷新预览)',
68
+ 'files.downloadTitle': '下载当前文件',
68
69
  'files.binary': '二进制文件({size}),请在资源管理器中用系统打开',
69
70
  'files.imageTooLarge': '图片过大({size},上限 {limit})',
70
71
  'files.pdfTooLarge': 'PDF 过大({size},上限 {limit}),请用系统打开',
@@ -86,6 +87,7 @@ export var DICT = {
86
87
  'files.notEditable': '当前文件类型不支持编辑',
87
88
  'files.truncatedEdit': '文件超过 8 MB,已截断,不能编辑保存。',
88
89
  'files.jsonFail': 'JSON 解析失败,按纯文本显示',
90
+ 'files.jsonTruncated': 'JSON 文件过大,仅预览前 {n} 个字符;完整内容请用编辑器打开。',
89
91
  'files.nbFail': 'ipynb 解析失败,按纯文本显示',
90
92
  'files.nbEmpty': '(空笔记本)',
91
93
  'files.nbCells': '共 {n} 个单元格',
@@ -152,6 +154,7 @@ export var DICT = {
152
154
  'files.readFail': 'Failed to read file',
153
155
  'files.reload': 'Reload',
154
156
  'files.reloadTitle': 'Re-read from disk (refresh preview)',
157
+ 'files.downloadTitle': 'Download this file',
155
158
  'files.binary': 'Binary file ({size}) — open with the system explorer',
156
159
  'files.imageTooLarge': 'Image too large ({size}, limit {limit})',
157
160
  'files.pdfTooLarge': 'PDF too large ({size}, limit {limit}) — open with the system viewer',
@@ -173,6 +176,7 @@ export var DICT = {
173
176
  'files.notEditable': 'Editing is not supported for this file type',
174
177
  'files.truncatedEdit': 'The file exceeds 8 MB and was truncated, so it cannot be safely edited.',
175
178
  'files.jsonFail': 'JSON parse failed — shown as plain text',
179
+ 'files.jsonTruncated': 'JSON file is too large — showing the first {n} characters; open the full content in an editor.',
176
180
  'files.nbFail': 'ipynb parse failed — shown as plain text',
177
181
  'files.nbEmpty': '(empty notebook)',
178
182
  'files.nbCells': '{n} cells',
@@ -189,4 +193,3 @@ export var DICT = {
189
193
  },
190
194
  }
191
195
  /** 模块级翻译函数(apply 里由 ctx.locale.bind 填充)。 */
192
-
@@ -109,6 +109,7 @@ export function createPreviewRenderers(ctx) {
109
109
  var startEditing = ctx.startEditing
110
110
  var stopEditing = ctx.stopEditing
111
111
  var reloadFile = ctx.reloadFile
112
+ var downloadFile = ctx.downloadFile
112
113
 
113
114
  function codeMirrorLanguage(path) {
114
115
  var ext = extOfName(path)
@@ -232,6 +233,8 @@ export function createPreviewRenderers(ctx) {
232
233
 
233
234
  /** 超过该字符数的代码文件不做高亮(Shiki 首次高亮的耗时保护)。 */
234
235
  var CODE_HIGHLIGHT_MAX_CHARS = 400000
236
+ /** 超过该字符数的 JSON 直接按纯文本预览,避免解析和行号 DOM 开销。 */
237
+ var JSON_PREVIEW_MAX_CHARS = 300000
235
238
 
236
239
  /** 把 pretty JSON 切成着色 token 数组(纯文本/React 节点,无 innerHTML)。 */
237
240
  function jsonColorNodes(pretty) {
@@ -710,11 +713,19 @@ export function createPreviewRenderers(ctx) {
710
713
  var text = entry.dirty ? entry.draft : entry.content
711
714
  var pk = previewKind(entry.path)
712
715
  var view = null
716
+ var jsonPreviewTruncated = false
713
717
  if (pk === 'markdown') view = create(MarkdownPreview, { text: text, baseDir: parentOf(entry.path) })
714
718
  else if (pk === 'html') view = create(HtmlPreview, {
715
719
  text: text, path: entry.path, sessionId: getActiveSessionId(), title: entry.name,
716
720
  })
717
- else if (pk === 'json') view = create(CodeWithLines, { text: text }, create(JsonPreview, { text: text }))
721
+ else if (pk === 'json') {
722
+ if (text.length > JSON_PREVIEW_MAX_CHARS) {
723
+ jsonPreviewTruncated = true
724
+ view = create('pre', { className: 'dfv-json dfv-code' }, text.slice(0, JSON_PREVIEW_MAX_CHARS))
725
+ } else {
726
+ view = create(CodeWithLines, { text: text }, create(JsonPreview, { text: text }))
727
+ }
728
+ }
718
729
  else if (pk === 'notebook') view = create(NotebookPreview, { text: text })
719
730
  else if (pk === 'csv' || pk === 'tsv') view = create(DelimitedPreview, { text: text, delim: pk === 'tsv' ? '\t' : ',' })
720
731
  else {
@@ -731,6 +742,8 @@ export function createPreviewRenderers(ctx) {
731
742
  return create(React.Fragment, null,
732
743
  entry.truncated ? create('div', { className: 'dfv-cap' },
733
744
  T('files.truncated')) : null,
745
+ jsonPreviewTruncated ? create('div', { className: 'dfv-cap' },
746
+ T('files.jsonTruncated', { n: JSON_PREVIEW_MAX_CHARS })) : null,
734
747
  view,
735
748
  )
736
749
  }
@@ -762,6 +775,16 @@ export function createPreviewRenderers(ctx) {
762
775
  ))
763
776
  }
764
777
  }
778
+ if (active.loaded && !active.editing && !active.dirty && !active.saving) {
779
+ buttons.push(create('button', {
780
+ type: 'button',
781
+ className: 'dfv-btn',
782
+ title: T('files.downloadTitle'),
783
+ onClick: function () { downloadFile(active.path) },
784
+ },
785
+ T('menu.download'),
786
+ ))
787
+ }
765
788
  buttons.push(active.loaded ? create('button', {
766
789
  type: 'button',
767
790
  className: 'dfv-btn',
@@ -799,4 +822,3 @@ export function createPreviewRenderers(ctx) {
799
822
  }
800
823
 
801
824
  if (typeof window !== 'undefined') window.__DSH_SOUP_PREVIEW_RENDERERS__ = { createPreviewRenderers }
802
-
package/lib/client.js CHANGED
@@ -30935,6 +30935,7 @@
30935
30935
  "files.readFail": "\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25",
30936
30936
  "files.reload": "\u91CD\u8F7D",
30937
30937
  "files.reloadTitle": "\u4ECE\u78C1\u76D8\u91CD\u65B0\u8BFB\u53D6\uFF08\u5237\u65B0\u9884\u89C8\uFF09",
30938
+ "files.downloadTitle": "\u4E0B\u8F7D\u5F53\u524D\u6587\u4EF6",
30938
30939
  "files.binary": "\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF08{size}\uFF09\uFF0C\u8BF7\u5728\u8D44\u6E90\u7BA1\u7406\u5668\u4E2D\u7528\u7CFB\u7EDF\u6253\u5F00",
30939
30940
  "files.imageTooLarge": "\u56FE\u7247\u8FC7\u5927\uFF08{size}\uFF0C\u4E0A\u9650 {limit}\uFF09",
30940
30941
  "files.pdfTooLarge": "PDF \u8FC7\u5927\uFF08{size}\uFF0C\u4E0A\u9650 {limit}\uFF09\uFF0C\u8BF7\u7528\u7CFB\u7EDF\u6253\u5F00",
@@ -30956,6 +30957,7 @@
30956
30957
  "files.notEditable": "\u5F53\u524D\u6587\u4EF6\u7C7B\u578B\u4E0D\u652F\u6301\u7F16\u8F91",
30957
30958
  "files.truncatedEdit": "\u6587\u4EF6\u8D85\u8FC7 8 MB\uFF0C\u5DF2\u622A\u65AD\uFF0C\u4E0D\u80FD\u7F16\u8F91\u4FDD\u5B58\u3002",
30958
30959
  "files.jsonFail": "JSON \u89E3\u6790\u5931\u8D25\uFF0C\u6309\u7EAF\u6587\u672C\u663E\u793A",
30960
+ "files.jsonTruncated": "JSON \u6587\u4EF6\u8FC7\u5927\uFF0C\u4EC5\u9884\u89C8\u524D {n} \u4E2A\u5B57\u7B26\uFF1B\u5B8C\u6574\u5185\u5BB9\u8BF7\u7528\u7F16\u8F91\u5668\u6253\u5F00\u3002",
30959
30961
  "files.nbFail": "ipynb \u89E3\u6790\u5931\u8D25\uFF0C\u6309\u7EAF\u6587\u672C\u663E\u793A",
30960
30962
  "files.nbEmpty": "\uFF08\u7A7A\u7B14\u8BB0\u672C\uFF09",
30961
30963
  "files.nbCells": "\u5171 {n} \u4E2A\u5355\u5143\u683C",
@@ -31022,6 +31024,7 @@
31022
31024
  "files.readFail": "Failed to read file",
31023
31025
  "files.reload": "Reload",
31024
31026
  "files.reloadTitle": "Re-read from disk (refresh preview)",
31027
+ "files.downloadTitle": "Download this file",
31025
31028
  "files.binary": "Binary file ({size}) \u2014 open with the system explorer",
31026
31029
  "files.imageTooLarge": "Image too large ({size}, limit {limit})",
31027
31030
  "files.pdfTooLarge": "PDF too large ({size}, limit {limit}) \u2014 open with the system viewer",
@@ -31043,6 +31046,7 @@
31043
31046
  "files.notEditable": "Editing is not supported for this file type",
31044
31047
  "files.truncatedEdit": "The file exceeds 8 MB and was truncated, so it cannot be safely edited.",
31045
31048
  "files.jsonFail": "JSON parse failed \u2014 shown as plain text",
31049
+ "files.jsonTruncated": "JSON file is too large \u2014 showing the first {n} characters; open the full content in an editor.",
31046
31050
  "files.nbFail": "ipynb parse failed \u2014 shown as plain text",
31047
31051
  "files.nbEmpty": "(empty notebook)",
31048
31052
  "files.nbCells": "{n} cells",
@@ -31496,6 +31500,7 @@
31496
31500
  var startEditing = ctx.startEditing;
31497
31501
  var stopEditing = ctx.stopEditing;
31498
31502
  var reloadFile = ctx.reloadFile;
31503
+ var downloadFile = ctx.downloadFile;
31499
31504
  function codeMirrorLanguage(path) {
31500
31505
  var ext = extOfName2(path);
31501
31506
  var factory = ext === "py" ? CMLangs.python && CMLangs.python.python : ext === "js" || ext === "mjs" || ext === "cjs" ? CMLangs.javascript && CMLangs.javascript.javascript : ext === "jsx" ? CMLangs.javascript && CMLangs.javascript.javascript : ext === "ts" || ext === "mts" || ext === "cts" ? CMLangs.javascript && CMLangs.javascript.javascript : ext === "tsx" ? CMLangs.javascript && CMLangs.javascript.javascript : ext === "json" || ext === "jsonc" ? CMLangs.json && CMLangs.json.json : ext === "md" || ext === "markdown" || ext === "mdx" ? CMLangs.markdown && CMLangs.markdown.markdown : ext === "html" || ext === "htm" ? CMLangs.html && CMLangs.html.html : ext === "css" || ext === "scss" || ext === "less" ? CMLangs.css && CMLangs.css.css : ext === "sql" ? CMLangs.sql && CMLangs.sql.sql : ext === "xml" ? CMLangs.xml && CMLangs.xml.xml : null;
@@ -31607,6 +31612,7 @@
31607
31612
  return create("div", { className: "dfv-cm-editor", ref: hostRef, "aria-label": entry.name });
31608
31613
  }
31609
31614
  var CODE_HIGHLIGHT_MAX_CHARS = 4e5;
31615
+ var JSON_PREVIEW_MAX_CHARS = 3e5;
31610
31616
  function jsonColorNodes(pretty) {
31611
31617
  var out = [];
31612
31618
  var last2 = 0;
@@ -32111,6 +32117,7 @@
32111
32117
  var text = entry.dirty ? entry.draft : entry.content;
32112
32118
  var pk = previewKind(entry.path);
32113
32119
  var view = null;
32120
+ var jsonPreviewTruncated = false;
32114
32121
  if (pk === "markdown") view = create(MarkdownPreview, { text, baseDir: parentOf(entry.path) });
32115
32122
  else if (pk === "html") view = create(HtmlPreview, {
32116
32123
  text,
@@ -32118,8 +32125,14 @@
32118
32125
  sessionId: getActiveSessionId(),
32119
32126
  title: entry.name
32120
32127
  });
32121
- else if (pk === "json") view = create(CodeWithLines, { text }, create(JsonPreview, { text }));
32122
- else if (pk === "notebook") view = create(NotebookPreview, { text });
32128
+ else if (pk === "json") {
32129
+ if (text.length > JSON_PREVIEW_MAX_CHARS) {
32130
+ jsonPreviewTruncated = true;
32131
+ view = create("pre", { className: "dfv-json dfv-code" }, text.slice(0, JSON_PREVIEW_MAX_CHARS));
32132
+ } else {
32133
+ view = create(CodeWithLines, { text }, create(JsonPreview, { text }));
32134
+ }
32135
+ } else if (pk === "notebook") view = create(NotebookPreview, { text });
32123
32136
  else if (pk === "csv" || pk === "tsv") view = create(DelimitedPreview, { text, delim: pk === "tsv" ? " " : "," });
32124
32137
  else {
32125
32138
  var lang = Object.prototype.hasOwnProperty.call(CODE_LANG_BY_EXT, extOfName2(entry.path)) ? CODE_LANG_BY_EXT[extOfName2(entry.path)] : void 0;
@@ -32134,6 +32147,11 @@
32134
32147
  { className: "dfv-cap" },
32135
32148
  T("files.truncated")
32136
32149
  ) : null,
32150
+ jsonPreviewTruncated ? create(
32151
+ "div",
32152
+ { className: "dfv-cap" },
32153
+ T("files.jsonTruncated", { n: JSON_PREVIEW_MAX_CHARS })
32154
+ ) : null,
32137
32155
  view
32138
32156
  );
32139
32157
  }
@@ -32172,6 +32190,20 @@
32172
32190
  ));
32173
32191
  }
32174
32192
  }
32193
+ if (active.loaded && !active.editing && !active.dirty && !active.saving) {
32194
+ buttons.push(create(
32195
+ "button",
32196
+ {
32197
+ type: "button",
32198
+ className: "dfv-btn",
32199
+ title: T("files.downloadTitle"),
32200
+ onClick: function() {
32201
+ downloadFile(active.path);
32202
+ }
32203
+ },
32204
+ T("menu.download")
32205
+ ));
32206
+ }
32175
32207
  buttons.push(active.loaded ? create(
32176
32208
  "button",
32177
32209
  {
@@ -34770,7 +34802,8 @@
34770
34802
  manuallySaveFile,
34771
34803
  startEditing,
34772
34804
  stopEditing,
34773
- reloadFile
34805
+ reloadFile,
34806
+ downloadFile
34774
34807
  });
34775
34808
  var TextEditor = renderers.TextEditor;
34776
34809
  var FileContent = renderers.FileContent;
@@ -288,6 +288,7 @@ window.__ModuleLoader__.load({
288
288
  startEditing: startEditing,
289
289
  stopEditing: stopEditing,
290
290
  reloadFile: reloadFile,
291
+ downloadFile: downloadFile,
291
292
  })
292
293
  var TextEditor = renderers.TextEditor
293
294
  var FileContent = renderers.FileContent
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lyhue1991/dsh-soup",
3
3
  "description": "DSH 项目资源管理器:右侧 details 列文件树(并列网格、宽度对齐宿主 details 合同 300-520px),有 Session log 时在其右侧、空白新会话在输入框上方右端提供 📁 切换按钮;支持多选、双击展开/打开、右键菜单(打开/系统打开/重命名/废纸篓/新建/复制路径)、拖拽移动、上传。文件「打开」在会话区新增「文件」标签页(原生 conversation.view,与对话/轨迹同级):文本可编辑 ⌘S 保存、图片预览、二进制提示。附带模型吞吐徽标:输入框正上方显示「正在等待模型...」与彩色 t/s 徽标(数据来自 llm/stream 真实流)。附带 GoalBar 多行展示:把原生单行截断 GoalBar 放开为多行完整显示,编辑用 textarea,工具与数据仍走原生 goal。",
4
- "version": "0.5.5",
4
+ "version": "0.5.6",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "scripts": {