dsh-workspace-explorer 1.1.0 → 1.1.2

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.
@@ -1,184 +1,184 @@
1
- using System;
2
- using System.Runtime.InteropServices;
3
-
4
- public static class ExplorerShell {
5
- [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
6
- private static extern IShellItem SHCreateItemFromParsingName(string path, IntPtr binding, [MarshalAs(UnmanagedType.LPStruct)] Guid iid);
7
-
8
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
9
- private static extern bool MoveFileEx(string source, string destination, uint flags);
10
-
11
- [DllImport("user32.dll")]
12
- public static extern uint GetClipboardSequenceNumber();
13
-
14
- [DllImport("user32.dll")]
15
- private static extern bool OpenClipboard(IntPtr window);
16
-
17
- [DllImport("user32.dll")]
18
- private static extern bool CloseClipboard();
19
-
20
- [DllImport("user32.dll")]
21
- private static extern bool EmptyClipboard();
22
-
23
- [DllImport("user32.dll", CharSet = CharSet.Unicode)]
24
- private static extern uint RegisterClipboardFormat(string format);
25
-
26
- [DllImport("user32.dll")]
27
- private static extern IntPtr GetClipboardData(uint format);
28
-
29
- [DllImport("kernel32.dll")]
30
- private static extern IntPtr GlobalLock(IntPtr memory);
31
-
32
- [DllImport("kernel32.dll")]
33
- private static extern bool GlobalUnlock(IntPtr memory);
34
-
35
- [DllImport("kernel32.dll")]
36
- private static extern UIntPtr GlobalSize(IntPtr memory);
37
-
38
- public static bool ClipboardIsCut() {
39
- if (!OpenClipboard(IntPtr.Zero)) throw new InvalidOperationException("Clipboard unavailable");
40
- try {
41
- IntPtr memory = GetClipboardData(RegisterClipboardFormat("Preferred DropEffect"));
42
- if (memory == IntPtr.Zero || GlobalSize(memory).ToUInt64() < 4) return false;
43
- IntPtr data = GlobalLock(memory);
44
- if (data == IntPtr.Zero) return false;
45
- try { return (Marshal.ReadInt32(data) & 2) != 0; }
46
- finally { GlobalUnlock(memory); }
47
- } finally { CloseClipboard(); }
48
- }
49
-
50
- public static int Rename(string source, string destination) {
51
- return MoveFileEx(source, destination, 0) ? 0 : Marshal.GetLastWin32Error();
52
- }
53
-
54
- public static void ClearClipboardIfUnchanged(uint sequence) {
55
- if (!OpenClipboard(IntPtr.Zero)) return;
56
- try {
57
- if (sequence == GetClipboardSequenceNumber()) EmptyClipboard();
58
- } finally { CloseClipboard(); }
59
- }
60
-
61
- public static bool Transfer(string source, string destination, bool cut) {
62
- IFileOperation operation = (IFileOperation)new FileOperation();
63
- try {
64
- const uint silent = 0x4, keepBoth = 0x8, noConfirmation = 0x10;
65
- const uint noErrorUI = 0x400, onlySelected = 0x2000, earlyFailure = 0x100000;
66
- const uint keepExtension = 0x200000, noCopyHooks = 0x800000, undoRecord = 0x20000000;
67
- operation.SetOperationFlags(silent | keepBoth | noConfirmation | noErrorUI | onlySelected
68
- | earlyFailure | keepExtension | noCopyHooks | undoRecord);
69
- Guid iid = typeof(IShellItem).GUID;
70
- IShellItem item = SHCreateItemFromParsingName(source, IntPtr.Zero, iid);
71
- try {
72
- IShellItem folder = SHCreateItemFromParsingName(destination, IntPtr.Zero, iid);
73
- try {
74
- if (cut) operation.MoveItem(item, folder, null, IntPtr.Zero);
75
- else operation.CopyItem(item, folder, null, IntPtr.Zero);
76
- operation.PerformOperations();
77
- return !operation.GetAnyOperationsAborted();
78
- } finally { Marshal.ReleaseComObject(folder); }
79
- } finally { Marshal.ReleaseComObject(item); }
80
- } finally { Marshal.ReleaseComObject(operation); }
81
- }
82
-
83
- public static bool Recycle(string source) {
84
- IFileOperation operation = (IFileOperation)new FileOperation();
85
- try {
86
- const uint silent = 0x4, noConfirmation = 0x10, allowUndo = 0x40, noErrorUI = 0x400;
87
- const uint onlySelected = 0x2000, warnPermanent = 0x4000, recycle = 0x80000;
88
- const uint earlyFailure = 0x100000, noCopyHooks = 0x800000, undoRecord = 0x20000000;
89
- operation.SetOperationFlags(silent | noConfirmation | allowUndo | noErrorUI | onlySelected | warnPermanent
90
- | recycle | earlyFailure | noCopyHooks | undoRecord);
91
- IShellItem item = SHCreateItemFromParsingName(source, IntPtr.Zero, typeof(IShellItem).GUID);
92
- try {
93
- RecycleOnly sink = new RecycleOnly();
94
- operation.DeleteItem(item, sink);
95
- operation.PerformOperations();
96
- return sink.Recycled && !operation.GetAnyOperationsAborted();
97
- } finally { Marshal.ReleaseComObject(item); }
98
- } finally { Marshal.ReleaseComObject(operation); }
99
- }
100
-
101
- [ComImport, Guid("3AD05575-8857-4850-9277-11B85BDB8E09")]
102
- private class FileOperation { }
103
-
104
- [ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
105
- public interface IShellItem { }
106
-
107
- // Keep the declaration in the native IFileOperation vtable order.
108
- [ComImport, Guid("947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
109
- private interface IFileOperation {
110
- void Advise(IntPtr sink, out uint cookie);
111
- void Unadvise(uint cookie);
112
- void SetOperationFlags(uint flags);
113
- void SetProgressMessage([MarshalAs(UnmanagedType.LPWStr)] string message);
114
- void SetProgressDialog(IntPtr dialog);
115
- void SetProperties(IntPtr properties);
116
- void SetOwnerWindow(IntPtr window);
117
- void ApplyPropertiesToItem(IShellItem item);
118
- void ApplyPropertiesToItems(IntPtr items);
119
- void RenameItem(IShellItem item, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr sink);
120
- void RenameItems(IntPtr items, [MarshalAs(UnmanagedType.LPWStr)] string name);
121
- void MoveItem(IShellItem item, IShellItem destination, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr sink);
122
- void MoveItems(IntPtr items, IShellItem destination);
123
- void CopyItem(IShellItem item, IShellItem destination, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr sink);
124
- void CopyItems(IntPtr items, IShellItem destination);
125
- void DeleteItem(IShellItem item, IFileOperationProgressSink sink);
126
- void DeleteItems(IntPtr items);
127
- void NewItem(IShellItem destination, uint attributes, [MarshalAs(UnmanagedType.LPWStr)] string name,
128
- [MarshalAs(UnmanagedType.LPWStr)] string template, IntPtr sink);
129
- void PerformOperations();
130
- [return: MarshalAs(UnmanagedType.Bool)]
131
- bool GetAnyOperationsAborted();
132
- }
133
-
134
- [ComImport, Guid("04B0F1A7-9490-44BC-96E1-4296A31252E2"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
135
- public interface IFileOperationProgressSink {
136
- [PreserveSig] int StartOperations();
137
- [PreserveSig] int FinishOperations(int result);
138
- [PreserveSig] int PreRenameItem(uint flags, IShellItem item, IntPtr name);
139
- [PreserveSig] int PostRenameItem(uint flags, IShellItem item, IntPtr name, int result, IShellItem created);
140
- [PreserveSig] int PreMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name);
141
- [PreserveSig] int PostMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created);
142
- [PreserveSig] int PreCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name);
143
- [PreserveSig] int PostCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created);
144
- [PreserveSig] int PreDeleteItem(uint flags, IShellItem item);
145
- [PreserveSig] int PostDeleteItem(uint flags, IShellItem item, int result, IShellItem created);
146
- [PreserveSig] int PreNewItem(uint flags, IShellItem folder, IntPtr name);
147
- [PreserveSig] int PostNewItem(uint flags, IShellItem folder, IntPtr name, IntPtr template, uint attrs, int result, IShellItem created);
148
- [PreserveSig] int UpdateProgress(uint total, uint completed);
149
- [PreserveSig] int ResetTimer();
150
- [PreserveSig] int PauseTimer();
151
- [PreserveSig] int ResumeTimer();
152
- }
153
-
154
- [ComVisible(true), ClassInterface(ClassInterfaceType.None)]
155
- public sealed class RecycleOnly : IFileOperationProgressSink {
156
- public bool Recycled { get; private set; }
157
-
158
- public int PreDeleteItem(uint flags, IShellItem item) {
159
- const uint recycleIfPossible = 0x80;
160
- const int cancelled = unchecked((int)0x800704C7);
161
- return (flags & recycleIfPossible) != 0 ? 0 : cancelled;
162
- }
163
-
164
- public int PostDeleteItem(uint flags, IShellItem item, int result, IShellItem created) {
165
- Recycled = result >= 0 && created != null;
166
- return 0;
167
- }
168
-
169
- public int StartOperations() { return 0; }
170
- public int FinishOperations(int result) { return 0; }
171
- public int PreRenameItem(uint flags, IShellItem item, IntPtr name) { return 0; }
172
- public int PostRenameItem(uint flags, IShellItem item, IntPtr name, int result, IShellItem created) { return 0; }
173
- public int PreMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name) { return 0; }
174
- public int PostMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created) { return 0; }
175
- public int PreCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name) { return 0; }
176
- public int PostCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created) { return 0; }
177
- public int PreNewItem(uint flags, IShellItem folder, IntPtr name) { return 0; }
178
- public int PostNewItem(uint flags, IShellItem folder, IntPtr name, IntPtr template, uint attrs, int result, IShellItem created) { return 0; }
179
- public int UpdateProgress(uint total, uint completed) { return 0; }
180
- public int ResetTimer() { return 0; }
181
- public int PauseTimer() { return 0; }
182
- public int ResumeTimer() { return 0; }
183
- }
1
+ using System;
2
+ using System.Runtime.InteropServices;
3
+
4
+ public static class ExplorerShell {
5
+ [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
6
+ private static extern IShellItem SHCreateItemFromParsingName(string path, IntPtr binding, [MarshalAs(UnmanagedType.LPStruct)] Guid iid);
7
+
8
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
9
+ private static extern bool MoveFileEx(string source, string destination, uint flags);
10
+
11
+ [DllImport("user32.dll")]
12
+ public static extern uint GetClipboardSequenceNumber();
13
+
14
+ [DllImport("user32.dll")]
15
+ private static extern bool OpenClipboard(IntPtr window);
16
+
17
+ [DllImport("user32.dll")]
18
+ private static extern bool CloseClipboard();
19
+
20
+ [DllImport("user32.dll")]
21
+ private static extern bool EmptyClipboard();
22
+
23
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
24
+ private static extern uint RegisterClipboardFormat(string format);
25
+
26
+ [DllImport("user32.dll")]
27
+ private static extern IntPtr GetClipboardData(uint format);
28
+
29
+ [DllImport("kernel32.dll")]
30
+ private static extern IntPtr GlobalLock(IntPtr memory);
31
+
32
+ [DllImport("kernel32.dll")]
33
+ private static extern bool GlobalUnlock(IntPtr memory);
34
+
35
+ [DllImport("kernel32.dll")]
36
+ private static extern UIntPtr GlobalSize(IntPtr memory);
37
+
38
+ public static bool ClipboardIsCut() {
39
+ if (!OpenClipboard(IntPtr.Zero)) throw new InvalidOperationException("Clipboard unavailable");
40
+ try {
41
+ IntPtr memory = GetClipboardData(RegisterClipboardFormat("Preferred DropEffect"));
42
+ if (memory == IntPtr.Zero || GlobalSize(memory).ToUInt64() < 4) return false;
43
+ IntPtr data = GlobalLock(memory);
44
+ if (data == IntPtr.Zero) return false;
45
+ try { return (Marshal.ReadInt32(data) & 2) != 0; }
46
+ finally { GlobalUnlock(memory); }
47
+ } finally { CloseClipboard(); }
48
+ }
49
+
50
+ public static int Rename(string source, string destination) {
51
+ return MoveFileEx(source, destination, 0) ? 0 : Marshal.GetLastWin32Error();
52
+ }
53
+
54
+ public static void ClearClipboardIfUnchanged(uint sequence) {
55
+ if (!OpenClipboard(IntPtr.Zero)) return;
56
+ try {
57
+ if (sequence == GetClipboardSequenceNumber()) EmptyClipboard();
58
+ } finally { CloseClipboard(); }
59
+ }
60
+
61
+ public static bool Transfer(string source, string destination, bool cut) {
62
+ IFileOperation operation = (IFileOperation)new FileOperation();
63
+ try {
64
+ const uint silent = 0x4, keepBoth = 0x8, noConfirmation = 0x10;
65
+ const uint noErrorUI = 0x400, onlySelected = 0x2000, earlyFailure = 0x100000;
66
+ const uint keepExtension = 0x200000, noCopyHooks = 0x800000, undoRecord = 0x20000000;
67
+ operation.SetOperationFlags(silent | keepBoth | noConfirmation | noErrorUI | onlySelected
68
+ | earlyFailure | keepExtension | noCopyHooks | undoRecord);
69
+ Guid iid = typeof(IShellItem).GUID;
70
+ IShellItem item = SHCreateItemFromParsingName(source, IntPtr.Zero, iid);
71
+ try {
72
+ IShellItem folder = SHCreateItemFromParsingName(destination, IntPtr.Zero, iid);
73
+ try {
74
+ if (cut) operation.MoveItem(item, folder, null, IntPtr.Zero);
75
+ else operation.CopyItem(item, folder, null, IntPtr.Zero);
76
+ operation.PerformOperations();
77
+ return !operation.GetAnyOperationsAborted();
78
+ } finally { Marshal.ReleaseComObject(folder); }
79
+ } finally { Marshal.ReleaseComObject(item); }
80
+ } finally { Marshal.ReleaseComObject(operation); }
81
+ }
82
+
83
+ public static bool Recycle(string source) {
84
+ IFileOperation operation = (IFileOperation)new FileOperation();
85
+ try {
86
+ const uint silent = 0x4, noConfirmation = 0x10, allowUndo = 0x40, noErrorUI = 0x400;
87
+ const uint onlySelected = 0x2000, warnPermanent = 0x4000, recycle = 0x80000;
88
+ const uint earlyFailure = 0x100000, noCopyHooks = 0x800000, undoRecord = 0x20000000;
89
+ operation.SetOperationFlags(silent | noConfirmation | allowUndo | noErrorUI | onlySelected | warnPermanent
90
+ | recycle | earlyFailure | noCopyHooks | undoRecord);
91
+ IShellItem item = SHCreateItemFromParsingName(source, IntPtr.Zero, typeof(IShellItem).GUID);
92
+ try {
93
+ RecycleOnly sink = new RecycleOnly();
94
+ operation.DeleteItem(item, sink);
95
+ operation.PerformOperations();
96
+ return sink.Recycled && !operation.GetAnyOperationsAborted();
97
+ } finally { Marshal.ReleaseComObject(item); }
98
+ } finally { Marshal.ReleaseComObject(operation); }
99
+ }
100
+
101
+ [ComImport, Guid("3AD05575-8857-4850-9277-11B85BDB8E09")]
102
+ private class FileOperation { }
103
+
104
+ [ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
105
+ public interface IShellItem { }
106
+
107
+ // Keep the declaration in the native IFileOperation vtable order.
108
+ [ComImport, Guid("947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
109
+ private interface IFileOperation {
110
+ void Advise(IntPtr sink, out uint cookie);
111
+ void Unadvise(uint cookie);
112
+ void SetOperationFlags(uint flags);
113
+ void SetProgressMessage([MarshalAs(UnmanagedType.LPWStr)] string message);
114
+ void SetProgressDialog(IntPtr dialog);
115
+ void SetProperties(IntPtr properties);
116
+ void SetOwnerWindow(IntPtr window);
117
+ void ApplyPropertiesToItem(IShellItem item);
118
+ void ApplyPropertiesToItems(IntPtr items);
119
+ void RenameItem(IShellItem item, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr sink);
120
+ void RenameItems(IntPtr items, [MarshalAs(UnmanagedType.LPWStr)] string name);
121
+ void MoveItem(IShellItem item, IShellItem destination, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr sink);
122
+ void MoveItems(IntPtr items, IShellItem destination);
123
+ void CopyItem(IShellItem item, IShellItem destination, [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr sink);
124
+ void CopyItems(IntPtr items, IShellItem destination);
125
+ void DeleteItem(IShellItem item, IFileOperationProgressSink sink);
126
+ void DeleteItems(IntPtr items);
127
+ void NewItem(IShellItem destination, uint attributes, [MarshalAs(UnmanagedType.LPWStr)] string name,
128
+ [MarshalAs(UnmanagedType.LPWStr)] string template, IntPtr sink);
129
+ void PerformOperations();
130
+ [return: MarshalAs(UnmanagedType.Bool)]
131
+ bool GetAnyOperationsAborted();
132
+ }
133
+
134
+ [ComImport, Guid("04B0F1A7-9490-44BC-96E1-4296A31252E2"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
135
+ public interface IFileOperationProgressSink {
136
+ [PreserveSig] int StartOperations();
137
+ [PreserveSig] int FinishOperations(int result);
138
+ [PreserveSig] int PreRenameItem(uint flags, IShellItem item, IntPtr name);
139
+ [PreserveSig] int PostRenameItem(uint flags, IShellItem item, IntPtr name, int result, IShellItem created);
140
+ [PreserveSig] int PreMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name);
141
+ [PreserveSig] int PostMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created);
142
+ [PreserveSig] int PreCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name);
143
+ [PreserveSig] int PostCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created);
144
+ [PreserveSig] int PreDeleteItem(uint flags, IShellItem item);
145
+ [PreserveSig] int PostDeleteItem(uint flags, IShellItem item, int result, IShellItem created);
146
+ [PreserveSig] int PreNewItem(uint flags, IShellItem folder, IntPtr name);
147
+ [PreserveSig] int PostNewItem(uint flags, IShellItem folder, IntPtr name, IntPtr template, uint attrs, int result, IShellItem created);
148
+ [PreserveSig] int UpdateProgress(uint total, uint completed);
149
+ [PreserveSig] int ResetTimer();
150
+ [PreserveSig] int PauseTimer();
151
+ [PreserveSig] int ResumeTimer();
152
+ }
153
+
154
+ [ComVisible(true), ClassInterface(ClassInterfaceType.None)]
155
+ public sealed class RecycleOnly : IFileOperationProgressSink {
156
+ public bool Recycled { get; private set; }
157
+
158
+ public int PreDeleteItem(uint flags, IShellItem item) {
159
+ const uint recycleIfPossible = 0x80;
160
+ const int cancelled = unchecked((int)0x800704C7);
161
+ return (flags & recycleIfPossible) != 0 ? 0 : cancelled;
162
+ }
163
+
164
+ public int PostDeleteItem(uint flags, IShellItem item, int result, IShellItem created) {
165
+ Recycled = result >= 0 && created != null;
166
+ return 0;
167
+ }
168
+
169
+ public int StartOperations() { return 0; }
170
+ public int FinishOperations(int result) { return 0; }
171
+ public int PreRenameItem(uint flags, IShellItem item, IntPtr name) { return 0; }
172
+ public int PostRenameItem(uint flags, IShellItem item, IntPtr name, int result, IShellItem created) { return 0; }
173
+ public int PreMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name) { return 0; }
174
+ public int PostMoveItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created) { return 0; }
175
+ public int PreCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name) { return 0; }
176
+ public int PostCopyItem(uint flags, IShellItem item, IShellItem folder, IntPtr name, int result, IShellItem created) { return 0; }
177
+ public int PreNewItem(uint flags, IShellItem folder, IntPtr name) { return 0; }
178
+ public int PostNewItem(uint flags, IShellItem folder, IntPtr name, IntPtr template, uint attrs, int result, IShellItem created) { return 0; }
179
+ public int UpdateProgress(uint total, uint completed) { return 0; }
180
+ public int ResetTimer() { return 0; }
181
+ public int PauseTimer() { return 0; }
182
+ public int ResumeTimer() { return 0; }
183
+ }
184
184
  }
package/src/host/files.js CHANGED
@@ -56,12 +56,30 @@ function fileVersion(info) {
56
56
  return JSON.stringify([info.dev, info.ino, info.size, info.mtimeMs, info.ctimeMs]);
57
57
  }
58
58
 
59
- function decodePreviewText(data, eof) {
59
+ const pythonEncodingAliases = new Map([
60
+ ['utf-8-sig', 'utf-8'], ['cp936', 'gbk'], ['cp932', 'shift_jis'],
61
+ ['cp1252', 'windows-1252'], ['latin-1', 'latin1'], ['iso-8859-1', 'latin1'],
62
+ ]);
63
+
64
+ function pythonSourceEncoding(data) {
65
+ if (data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) return 'utf-8';
66
+ const [first, second = ''] = data.toString('latin1').split(/\r\n?|\n/, 2);
67
+ const cookie = /^[ \t\f]*#.*?coding[=:][ \t]*([-_.a-zA-Z0-9]+)/;
68
+ const declared = cookie.exec(first)?.[1]
69
+ ?? (/^[ \t\f]*(?:#|$)/.test(first) ? cookie.exec(second)?.[1] : undefined);
70
+ const label = declared?.toLowerCase().replaceAll('_', '-') ?? 'utf-8';
71
+ return pythonEncodingAliases.get(label) ?? label;
72
+ }
73
+
74
+ function decodePreviewText(data, eof, encoding = 'utf-8') {
75
+ let decoder;
76
+ try { decoder = new TextDecoder(encoding, { fatal: true }); }
77
+ catch { decoder = new TextDecoder('utf-8', { fatal: true }); }
60
78
  let text;
61
79
  try {
62
- text = new TextDecoder('utf-8', { fatal: true }).decode(data, { stream: !eof });
80
+ text = encoding === 'latin1' ? data.toString('latin1') : decoder.decode(data, { stream: !eof });
63
81
  } catch {
64
- throw new BrowseError('此文件不是 UTF-8 文本');
82
+ throw new BrowseError(decoder.encoding === 'utf-8' ? '此文件不是 UTF-8 文本' : '无法按文件声明的编码预览');
65
83
  }
66
84
  if (text.includes('\0')) throw new BrowseError('此格式没有可用的文本预览');
67
85
  return text;
@@ -281,7 +299,7 @@ function createDiskAccess() {
281
299
  const target = await resolve(absolute, signal, workspace);
282
300
  const info = await stat(target);
283
301
  if (info.isDirectory()) return { path: absolute, nativePath: target, type: 'directory' };
284
- if (info.isFile()) return { path: absolute, nativePath: target, type: 'file', name: path.basename(absolute) };
302
+ if (info.isFile()) return { path: absolute, nativePath: target, type: 'file', name: path.basename(absolute), size: info.size };
285
303
  throw new BrowseError('该路径不指向普通文件或文件夹');
286
304
  }
287
305
 
@@ -560,8 +578,9 @@ export function registerDesktopFiles(ctx) {
560
578
  return json({ url: thumbnailEndpoint + '?ticket=' + token });
561
579
  }
562
580
  if (operation === 'text') {
563
- const { data, eof } = await disks.read(input, maxText, signal, workspace, { sniffText: true });
564
- return json({ text: decodePreviewText(data, eof), eof });
581
+ const python = typeof input === 'string' && /\.py$/i.test(input);
582
+ const { data, eof } = await disks.read(input, maxText, signal, workspace, { sniffText: !python });
583
+ return json({ text: decodePreviewText(data, eof, python ? pythonSourceEncoding(data) : undefined), eof });
565
584
  }
566
585
  if (operation === 'bytes' || operation === 'office') {
567
586
  const converter = operation === 'office' ? ctx.officeToPdf : undefined;
@@ -1,30 +1,30 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { createRequire } from 'node:module';
3
- import { dirname, join } from 'node:path';
4
- import { pdfAssetsPath } from '../document-types.js';
5
-
6
- const require = createRequire(import.meta.url);
7
- const assetName = /^(?:build\/pdf(?:\.worker)?\.min\.mjs|cmaps\/[\w.-]+\.bcmap|standard_fonts\/[\w.-]+\.(?:pfb|ttf)|wasm\/[\w.-]+\.(?:wasm|js))$/;
8
-
9
- export function registerPdfAssets(ctx) {
10
- ctx.connection.fetch.register({
11
- path: pdfAssetsPath,
12
- methods: ['GET'],
13
- requestBody: 'buffered',
14
- async fetch(request) {
15
- const file = new URL(request.url).searchParams.get('file');
16
- if (!file || !assetName.test(file)) return new Response(null, { status: 404 });
17
- try {
18
- const root = dirname(require.resolve('pdfjs-dist/package.json'));
19
- const data = await readFile(join(root, file));
20
- const contentType = file.endsWith('.wasm') ? 'application/wasm'
21
- : /\.m?js$/.test(file) ? 'text/javascript' : 'application/octet-stream';
22
- return new Response(data, { headers: {
23
- 'content-type': contentType, 'x-content-type-options': 'nosniff', 'cache-control': 'no-store',
24
- } });
25
- } catch {
26
- return new Response(null, { status: 404 });
27
- }
28
- },
29
- });
30
- }
1
+ import { readFile } from 'node:fs/promises';
2
+ import { createRequire } from 'node:module';
3
+ import { dirname, join } from 'node:path';
4
+ import { pdfAssetsPath } from '../document-types.js';
5
+
6
+ const require = createRequire(import.meta.url);
7
+ const assetName = /^(?:build\/pdf(?:\.worker)?\.min\.mjs|cmaps\/[\w.-]+\.bcmap|standard_fonts\/[\w.-]+\.(?:pfb|ttf)|wasm\/[\w.-]+\.(?:wasm|js))$/;
8
+
9
+ export function registerPdfAssets(ctx) {
10
+ ctx.connection.fetch.register({
11
+ path: pdfAssetsPath,
12
+ methods: ['GET'],
13
+ requestBody: 'buffered',
14
+ async fetch(request) {
15
+ const file = new URL(request.url).searchParams.get('file');
16
+ if (!file || !assetName.test(file)) return new Response(null, { status: 404 });
17
+ try {
18
+ const root = dirname(require.resolve('pdfjs-dist/package.json'));
19
+ const data = await readFile(join(root, file));
20
+ const contentType = file.endsWith('.wasm') ? 'application/wasm'
21
+ : /\.m?js$/.test(file) ? 'text/javascript' : 'application/octet-stream';
22
+ return new Response(data, { headers: {
23
+ 'content-type': contentType, 'x-content-type-options': 'nosniff', 'cache-control': 'no-store',
24
+ } });
25
+ } catch {
26
+ return new Response(null, { status: 404 });
27
+ }
28
+ },
29
+ });
30
+ }