@lvce-editor/explorer-view 7.6.0 → 7.9.0

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.
@@ -3,10 +3,67 @@ const toCommandId = key => {
3
3
  return key.slice(dotIndex + 1);
4
4
  };
5
5
  const create$a = () => {
6
+ const commandQueues = new Map();
7
+ const generations = Object.create(null);
6
8
  const states = Object.create(null);
7
9
  const commandMapRef = {};
10
+ const getGeneration = uid => generations[uid] || 0;
11
+ const isCurrentGeneration = (uid, generation) => {
12
+ return states[uid] !== undefined && getGeneration(uid) === generation;
13
+ };
14
+ const updateState = (uid, generation, fallbackState, updater) => {
15
+ if (!isCurrentGeneration(uid, generation)) {
16
+ return Promise.resolve(fallbackState);
17
+ }
18
+ const current = states[uid];
19
+ const updatedState = updater(current.newState);
20
+ if (updatedState !== current.newState) {
21
+ states[uid] = {
22
+ newState: updatedState,
23
+ oldState: current.oldState,
24
+ scheduledState: updatedState
25
+ };
26
+ }
27
+ return Promise.resolve(updatedState);
28
+ };
29
+ const createAsyncCommandContext = (uid, generation) => {
30
+ let latestState = states[uid].newState;
31
+ return {
32
+ getState: () => {
33
+ if (isCurrentGeneration(uid, generation)) {
34
+ latestState = states[uid].newState;
35
+ }
36
+ return latestState;
37
+ },
38
+ updateState: async updater => {
39
+ latestState = await updateState(uid, generation, latestState, updater);
40
+ return latestState;
41
+ }
42
+ };
43
+ };
44
+ const enqueueCommand = async (uid, command) => {
45
+ const previous = commandQueues.get(uid) || Promise.resolve();
46
+ const run = async () => {
47
+ try {
48
+ await previous;
49
+ } catch {
50
+ // The previous caller receives its error; later commands must still run.
51
+ }
52
+ await command();
53
+ };
54
+ const current = run();
55
+ commandQueues.set(uid, current);
56
+ try {
57
+ await current;
58
+ } finally {
59
+ if (commandQueues.get(uid) === current) {
60
+ commandQueues.delete(uid);
61
+ }
62
+ }
63
+ };
8
64
  return {
9
65
  clear() {
66
+ commandQueues.clear();
10
67
  for (const key of Object.keys(states)) {
11
68
  delete states[key];
12
69
  }
@@ -26,6 +83,7 @@ const create$a = () => {
26
83
  return diffResult;
27
84
  },
28
85
  dispose(uid) {
86
+ commandQueues.delete(uid);
29
87
  delete states[uid];
30
88
  },
31
89
  get(uid) {
@@ -43,14 +101,27 @@ const create$a = () => {
43
101
  Object.assign(commandMapRef, commandMap);
44
102
  },
45
103
  set(uid, oldState, newState, scheduledState) {
104
+ const current = states[uid];
105
+ if (!current || oldState === newState && newState !== current.newState) {
106
+ generations[uid] = getGeneration(uid) + 1;
107
+ }
46
108
  states[uid] = {
47
109
  newState,
48
110
  oldState,
49
111
  scheduledState: scheduledState ?? newState
50
112
  };
51
113
  },
114
+ wrapAsyncCommand(fn) {
115
+ const wrapped = async (uid, ...args) => {
116
+ const generation = getGeneration(uid);
117
+ const context = createAsyncCommandContext(uid, generation);
118
+ await fn(context, ...args);
119
+ };
120
+ return wrapped;
121
+ },
52
122
  wrapCommand(fn) {
53
123
  const wrapped = async (uid, ...args) => {
124
+ const generation = getGeneration(uid);
54
125
  const {
55
126
  newState,
56
127
  oldState
@@ -59,6 +130,9 @@ const create$a = () => {
59
130
  if (oldState === newerState || newState === newerState) {
60
131
  return;
61
132
  }
133
+ if (!isCurrentGeneration(uid, generation)) {
134
+ return;
135
+ }
62
136
  const latestOld = states[uid];
63
137
  const latestNew = {
64
138
  ...latestOld.newState,
@@ -83,6 +157,7 @@ const create$a = () => {
83
157
  },
84
158
  wrapLoadContent(fn) {
85
159
  const wrapped = async (uid, ...args) => {
160
+ const generation = getGeneration(uid);
86
161
  const {
87
162
  newState,
88
163
  oldState
@@ -97,6 +172,11 @@ const create$a = () => {
97
172
  error
98
173
  };
99
174
  }
175
+ if (!isCurrentGeneration(uid, generation)) {
176
+ return {
177
+ error
178
+ };
179
+ }
100
180
  const latestOld = states[uid];
101
181
  const latestNew = {
102
182
  ...latestOld.newState,
@@ -112,6 +192,51 @@ const create$a = () => {
112
192
  };
113
193
  };
114
194
  return wrapped;
195
+ },
196
+ wrapSerialAsyncCommand(fn) {
197
+ const wrapped = async (uid, ...args) => {
198
+ await enqueueCommand(uid, async () => {
199
+ if (!states[uid]) {
200
+ return;
201
+ }
202
+ const generation = getGeneration(uid);
203
+ const context = createAsyncCommandContext(uid, generation);
204
+ await fn(context, ...args);
205
+ });
206
+ };
207
+ return wrapped;
208
+ },
209
+ wrapSerialCommand(fn) {
210
+ const wrapped = async (uid, ...args) => {
211
+ await enqueueCommand(uid, async () => {
212
+ if (!states[uid]) {
213
+ return;
214
+ }
215
+ const generation = getGeneration(uid);
216
+ const {
217
+ newState,
218
+ oldState
219
+ } = states[uid];
220
+ const newerState = await fn(newState, ...args);
221
+ if (oldState === newerState || newState === newerState) {
222
+ return;
223
+ }
224
+ if (!isCurrentGeneration(uid, generation)) {
225
+ return;
226
+ }
227
+ const latestOld = states[uid];
228
+ const latestNew = {
229
+ ...latestOld.newState,
230
+ ...newerState
231
+ };
232
+ states[uid] = {
233
+ newState: latestNew,
234
+ oldState: latestOld.oldState,
235
+ scheduledState: latestNew
236
+ };
237
+ });
238
+ };
239
+ return wrapped;
115
240
  }
116
241
  };
117
242
  };
@@ -284,7 +409,6 @@ const walkValue = (value, transferrables, isTransferrable) => {
284
409
  for (const property of Object.values(value)) {
285
410
  walkValue(property, transferrables, isTransferrable);
286
411
  }
287
- return;
288
412
  }
289
413
  };
290
414
  const getTransferrables = value => {
@@ -438,7 +562,14 @@ class IpcError extends VError {
438
562
  const cause = new Error(message);
439
563
  // @ts-ignore
440
564
  cause.code = code;
441
- cause.stack = stack;
565
+ if (stack) {
566
+ Object.defineProperty(cause, 'stack', {
567
+ configurable: true,
568
+ enumerable: false,
569
+ value: stack,
570
+ writable: true
571
+ });
572
+ }
442
573
  super(cause, betterMessage);
443
574
  } else {
444
575
  super(betterMessage);
@@ -742,8 +873,10 @@ const getCurrentStack = () => {
742
873
  const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip));
743
874
  return currentStack;
744
875
  };
745
- const getNewLineIndex = (string, startIndex = undefined) => {
746
- return string.indexOf(NewLine, startIndex);
876
+ const getNewLineIndex = (string, startIndex) => {
877
+ {
878
+ return string.indexOf(NewLine);
879
+ }
747
880
  };
748
881
  const getParentStack = error => {
749
882
  let parentStack = error.stack || error.data || error.message || '';
@@ -754,55 +887,77 @@ const getParentStack = error => {
754
887
  };
755
888
  const MethodNotFound = -32601;
756
889
  const Custom = -32001;
890
+ const restoreExistingError = (error, currentStack) => {
891
+ if (typeof error.stack === 'string') {
892
+ error.stack = error.stack + NewLine + currentStack;
893
+ }
894
+ return error;
895
+ };
896
+ const restoreMethodNotFoundError = (error, currentStack) => {
897
+ const restoredError = new JsonRpcError(error.message);
898
+ const parentStack = getParentStack(error);
899
+ restoredError.stack = parentStack + NewLine + currentStack;
900
+ return restoredError;
901
+ };
902
+ const restoreStackFromData = (restoredError, error, currentStack) => {
903
+ if (error.data.stack && error.data.type && error.message) {
904
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
905
+ return;
906
+ }
907
+ if (error.data.stack) {
908
+ restoredError.stack = error.data.stack;
909
+ }
910
+ };
911
+ const applyDataProperties = (restoredError, error) => {
912
+ if (!error.data) {
913
+ return;
914
+ }
915
+ restoreStackFromData(restoredError, error, getCurrentStack());
916
+ if (error.data.codeFrame) {
917
+ // @ts-ignore
918
+ restoredError.codeFrame = error.data.codeFrame;
919
+ }
920
+ if (error.data.code) {
921
+ // @ts-ignore
922
+ restoredError.code = error.data.code;
923
+ }
924
+ if (error.data.type) {
925
+ // @ts-ignore
926
+ restoredError.name = error.data.type;
927
+ }
928
+ };
929
+ const applyDirectProperties = (restoredError, error) => {
930
+ if (error.stack) {
931
+ const lowerStack = restoredError.stack || '';
932
+ const indexNewLine = getNewLineIndex(lowerStack);
933
+ const parentStack = getParentStack(error);
934
+ // @ts-ignore
935
+ restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
936
+ }
937
+ if (error.codeFrame) {
938
+ // @ts-ignore
939
+ restoredError.codeFrame = error.codeFrame;
940
+ }
941
+ };
942
+ const restoreMessageError = (error, _currentStack) => {
943
+ const restoredError = constructError(error.message, error.type, error.name);
944
+ if (error.data) {
945
+ applyDataProperties(restoredError, error);
946
+ } else {
947
+ applyDirectProperties(restoredError, error);
948
+ }
949
+ return restoredError;
950
+ };
757
951
  const restoreJsonRpcError = error => {
758
952
  const currentStack = getCurrentStack();
759
953
  if (error && error instanceof Error) {
760
- if (typeof error.stack === 'string') {
761
- error.stack = error.stack + NewLine + currentStack;
762
- }
763
- return error;
954
+ return restoreExistingError(error, currentStack);
764
955
  }
765
956
  if (error && error.code && error.code === MethodNotFound) {
766
- const restoredError = new JsonRpcError(error.message);
767
- const parentStack = getParentStack(error);
768
- restoredError.stack = parentStack + NewLine + currentStack;
769
- return restoredError;
957
+ return restoreMethodNotFoundError(error, currentStack);
770
958
  }
771
959
  if (error && error.message) {
772
- const restoredError = constructError(error.message, error.type, error.name);
773
- if (error.data) {
774
- if (error.data.stack && error.data.type && error.message) {
775
- restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
776
- } else if (error.data.stack) {
777
- restoredError.stack = error.data.stack;
778
- }
779
- if (error.data.codeFrame) {
780
- // @ts-ignore
781
- restoredError.codeFrame = error.data.codeFrame;
782
- }
783
- if (error.data.code) {
784
- // @ts-ignore
785
- restoredError.code = error.data.code;
786
- }
787
- if (error.data.type) {
788
- // @ts-ignore
789
- restoredError.name = error.data.type;
790
- }
791
- } else {
792
- if (error.stack) {
793
- const lowerStack = restoredError.stack || '';
794
- // @ts-ignore
795
- const indexNewLine = getNewLineIndex(lowerStack);
796
- const parentStack = getParentStack(error);
797
- // @ts-ignore
798
- restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
799
- }
800
- if (error.codeFrame) {
801
- // @ts-ignore
802
- restoredError.codeFrame = error.codeFrame;
803
- }
804
- }
805
- return restoredError;
960
+ return restoreMessageError(error);
806
961
  }
807
962
  if (typeof error === 'string') {
808
963
  return new Error(`JsonRpc Error: ${error}`);
@@ -1262,9 +1417,175 @@ const create$1 = rpcId => {
1262
1417
  };
1263
1418
  };
1264
1419
 
1420
+ const Audio = 0;
1421
+ const Button$4 = 1;
1422
+ const Col = 2;
1423
+ const ColGroup = 3;
1424
+ const Div$1 = 4;
1425
+ const H1 = 5;
1426
+ const Input$2 = 6;
1427
+ const Kbd = 7;
1428
+ const Span = 8;
1429
+ const Table = 9;
1430
+ const TBody = 10;
1431
+ const Td = 11;
1265
1432
  const Text = 12;
1433
+ const Th = 13;
1434
+ const THead = 14;
1435
+ const Tr = 15;
1436
+ const I = 16;
1437
+ const Img$1 = 17;
1438
+ const Root = 0;
1439
+ const Ins = 20;
1440
+ const Del = 21;
1441
+ const H2 = 22;
1442
+ const H3 = 23;
1443
+ const H4 = 24;
1444
+ const H5 = 25;
1445
+ const H6 = 26;
1446
+ const Article = 27;
1447
+ const Aside = 28;
1448
+ const Footer = 29;
1449
+ const Header = 30;
1450
+ const Nav = 40;
1451
+ const Section = 41;
1452
+ const Search = 42;
1453
+ const Dd = 43;
1454
+ const Dl = 44;
1455
+ const Figcaption = 45;
1456
+ const Figure = 46;
1457
+ const Hr = 47;
1458
+ const Li = 48;
1459
+ const Ol = 49;
1460
+ const P$1 = 50;
1461
+ const Pre = 51;
1462
+ const A = 53;
1463
+ const Abbr = 54;
1464
+ const Br = 55;
1465
+ const Cite = 56;
1466
+ const Data = 57;
1467
+ const Time = 58;
1468
+ const Tfoot = 59;
1469
+ const Ul = 60;
1470
+ const Video = 61;
1471
+ const TextArea = 62;
1472
+ const Select = 63;
1473
+ const Option = 64;
1474
+ const Code = 65;
1475
+ const Label$1 = 66;
1476
+ const Dt = 67;
1477
+ const Iframe = 68;
1478
+ const Main = 69;
1479
+ const Strong = 70;
1480
+ const Em = 71;
1481
+ const Style = 72;
1482
+ const Html = 73;
1483
+ const Head = 74;
1484
+ const Title = 75;
1485
+ const Meta = 76;
1486
+ const Canvas = 77;
1487
+ const Form = 78;
1488
+ const BlockQuote = 79;
1489
+ const Quote = 80;
1490
+ const Circle = 81;
1491
+ const Defs = 82;
1492
+ const Ellipse = 83;
1493
+ const G = 84;
1494
+ const Line = 85;
1495
+ const Path = 86;
1496
+ const Polygon = 87;
1497
+ const Polyline = 88;
1498
+ const Rect = 89;
1499
+ const Svg = 90;
1500
+ const Use = 91;
1266
1501
  const Reference = 100;
1267
1502
 
1503
+ const VirtualDomElements = {
1504
+ __proto__: null,
1505
+ A,
1506
+ Abbr,
1507
+ Article,
1508
+ Aside,
1509
+ Audio,
1510
+ BlockQuote,
1511
+ Br,
1512
+ Button: Button$4,
1513
+ Canvas,
1514
+ Circle,
1515
+ Cite,
1516
+ Code,
1517
+ Col,
1518
+ ColGroup,
1519
+ Data,
1520
+ Dd,
1521
+ Defs,
1522
+ Del,
1523
+ Div: Div$1,
1524
+ Dl,
1525
+ Dt,
1526
+ Ellipse,
1527
+ Em,
1528
+ Figcaption,
1529
+ Figure,
1530
+ Footer,
1531
+ Form,
1532
+ G,
1533
+ H1,
1534
+ H2,
1535
+ H3,
1536
+ H4,
1537
+ H5,
1538
+ H6,
1539
+ Head,
1540
+ Header,
1541
+ Hr,
1542
+ Html,
1543
+ I,
1544
+ Iframe,
1545
+ Img: Img$1,
1546
+ Input: Input$2,
1547
+ Ins,
1548
+ Kbd,
1549
+ Label: Label$1,
1550
+ Li,
1551
+ Line,
1552
+ Main,
1553
+ Meta,
1554
+ Nav,
1555
+ Ol,
1556
+ Option,
1557
+ P: P$1,
1558
+ Path,
1559
+ Polygon,
1560
+ Polyline,
1561
+ Pre,
1562
+ Quote,
1563
+ Rect,
1564
+ Reference,
1565
+ Root,
1566
+ Search,
1567
+ Section,
1568
+ Select,
1569
+ Span,
1570
+ Strong,
1571
+ Style,
1572
+ Svg,
1573
+ TBody,
1574
+ THead,
1575
+ Table,
1576
+ Td,
1577
+ Text,
1578
+ TextArea,
1579
+ Tfoot,
1580
+ Th,
1581
+ Time,
1582
+ Title,
1583
+ Tr,
1584
+ Ul,
1585
+ Use,
1586
+ Video
1587
+ };
1588
+
1268
1589
  const Button$3 = 'event.button';
1269
1590
  const ClientX = 'event.clientX';
1270
1591
  const ClientY = 'event.clientY';
@@ -1393,6 +1714,9 @@ const remove = async dirent => {
1393
1714
  const readDirWithFileTypes = async uri => {
1394
1715
  return invoke('FileSystem.readDirWithFileTypes', uri);
1395
1716
  };
1717
+ const readFile = async uri => {
1718
+ return invoke('FileSystem.readFile', uri);
1719
+ };
1396
1720
  const getPathSeparator$1 = async root => {
1397
1721
  return invoke('FileSystem.getPathSeparator', root);
1398
1722
  };
@@ -1951,15 +2275,15 @@ const Slash$1 = '/';
1951
2275
  const BackSlash = '\\';
1952
2276
 
1953
2277
  const emptyObject = {};
1954
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1955
2278
  const i18nString = (key, placeholders = emptyObject) => {
1956
2279
  if (placeholders === emptyObject) {
1957
2280
  return key;
1958
2281
  }
1959
- const replacer = (match, rest) => {
1960
- return placeholders[rest];
1961
- };
1962
- return key.replaceAll(RE_PLACEHOLDER, replacer);
2282
+ let result = key;
2283
+ for (const [placeholder, replacement] of Object.entries(placeholders)) {
2284
+ result = result.split(`{${placeholder}}`).join(String(replacement));
2285
+ }
2286
+ return result;
1963
2287
  };
1964
2288
 
1965
2289
  const CollapseAllFoldersInExplorer = 'Collapse All Folders in Explorer';
@@ -2575,6 +2899,215 @@ const getFileIcons = async (dirents, fileIconCache) => {
2575
2899
  };
2576
2900
  };
2577
2901
 
2902
+ const directoryTypes = new Set([DirectoryExpanded, DirectoryExpanding, EditingDirectoryExpanded]);
2903
+ const getParentPath = (path, pathSeparator) => {
2904
+ const index = path.lastIndexOf(pathSeparator);
2905
+ if (index === -1) {
2906
+ return '';
2907
+ }
2908
+ return path.slice(0, index);
2909
+ };
2910
+ const getGitIgnoreCandidateDirs = (root, items, pathSeparator) => {
2911
+ const dirs = new Set([root]);
2912
+ for (const item of items) {
2913
+ if (directoryTypes.has(item.type)) {
2914
+ dirs.add(item.path);
2915
+ }
2916
+ const parent = getParentPath(item.path, pathSeparator);
2917
+ if (parent && parent.startsWith(root)) {
2918
+ dirs.add(parent);
2919
+ }
2920
+ }
2921
+ return [...dirs];
2922
+ };
2923
+
2924
+ const trimLeadingSeparator = path => {
2925
+ return path.startsWith('/') ? path.slice(1) : path;
2926
+ };
2927
+ const toSlashPath = (path, pathSeparator) => {
2928
+ if (pathSeparator === '/') {
2929
+ return path;
2930
+ }
2931
+ return path.replaceAll(pathSeparator, '/');
2932
+ };
2933
+ const getGitIgnoreRelativePath = (root, path, pathSeparator) => {
2934
+ const slashRoot = toSlashPath(root, pathSeparator);
2935
+ const slashPath = toSlashPath(path, pathSeparator);
2936
+ if (slashPath === slashRoot) {
2937
+ return '';
2938
+ }
2939
+ if (slashRoot.endsWith('/')) {
2940
+ return slashPath.slice(slashRoot.length);
2941
+ }
2942
+ return trimLeadingSeparator(slashPath.slice(slashRoot.length));
2943
+ };
2944
+
2945
+ const joinPath = (parent, child, pathSeparator) => {
2946
+ if (parent.endsWith(pathSeparator)) {
2947
+ return `${parent}${child}`;
2948
+ }
2949
+ return `${parent}${pathSeparator}${child}`;
2950
+ };
2951
+
2952
+ const lineSeparatorRegex = /\r?\n/;
2953
+ const stripTrailingSpaces = line => {
2954
+ let end = line.length;
2955
+ while (end > 0 && line[end - 1] === ' ' && line[end - 2] !== '\\') {
2956
+ end--;
2957
+ }
2958
+ return line.slice(0, end).replaceAll('\\ ', ' ');
2959
+ };
2960
+ const parseLine = (basePath, line) => {
2961
+ line = stripTrailingSpaces(line);
2962
+ if (!line || line.startsWith('#')) {
2963
+ return undefined;
2964
+ }
2965
+ let negative = false;
2966
+ if (line.startsWith('\\!')) {
2967
+ line = line.slice(1);
2968
+ } else if (line.startsWith('!')) {
2969
+ negative = true;
2970
+ line = line.slice(1);
2971
+ }
2972
+ const anchored = line.startsWith('/');
2973
+ line = line.replaceAll('\\#', '#').replaceAll('\\!', '!');
2974
+ const directoryOnly = line.endsWith('/');
2975
+ if (directoryOnly) {
2976
+ line = line.slice(0, -1);
2977
+ }
2978
+ while (line.startsWith('/')) {
2979
+ line = line.slice(1);
2980
+ }
2981
+ if (!line) {
2982
+ return undefined;
2983
+ }
2984
+ return {
2985
+ anchored,
2986
+ basePath,
2987
+ directoryOnly,
2988
+ hasSlash: line.includes('/'),
2989
+ negative,
2990
+ pattern: line
2991
+ };
2992
+ };
2993
+ const parseGitIgnore = (basePath, content) => {
2994
+ const patterns = [];
2995
+ for (const line of content.split(lineSeparatorRegex)) {
2996
+ const pattern = parseLine(basePath, line);
2997
+ if (pattern) {
2998
+ patterns.push(pattern);
2999
+ }
3000
+ }
3001
+ return patterns;
3002
+ };
3003
+
3004
+ const readGitIgnoreFile = async (root, dir, pathSeparator) => {
3005
+ try {
3006
+ const content = await readFile(joinPath(dir, '.gitignore', pathSeparator));
3007
+ const basePath = getGitIgnoreRelativePath(root, dir, pathSeparator);
3008
+ return parseGitIgnore(basePath, content);
3009
+ } catch {
3010
+ return [];
3011
+ }
3012
+ };
3013
+ const getGitIgnoreFiles = async (root, items, pathSeparator) => {
3014
+ const dirs = getGitIgnoreCandidateDirs(root, items, pathSeparator);
3015
+ const nestedPatterns = await Promise.all(dirs.map(dir => {
3016
+ return readGitIgnoreFile(root, dir, pathSeparator);
3017
+ }));
3018
+ return nestedPatterns.flat();
3019
+ };
3020
+
3021
+ const regexSpecialCharacters = /[|\\{}()[\]^$+?.]/g;
3022
+ const escapeRegex = text => {
3023
+ return text.replaceAll(regexSpecialCharacters, '\\$&');
3024
+ };
3025
+ const globToRegex = glob => {
3026
+ let regex = '^';
3027
+ for (let i = 0; i < glob.length; i++) {
3028
+ const char = glob[i];
3029
+ const next = glob[i + 1];
3030
+ if (char === '*' && next === '*') {
3031
+ if (glob[i + 2] === '/') {
3032
+ regex += '(?:.*/)?';
3033
+ i += 2;
3034
+ } else {
3035
+ regex += '.*';
3036
+ i++;
3037
+ }
3038
+ } else if (char === '*') {
3039
+ regex += '[^/]*';
3040
+ } else if (char === '?') {
3041
+ regex += '[^/]';
3042
+ } else {
3043
+ regex += escapeRegex(char);
3044
+ }
3045
+ }
3046
+ regex += '$';
3047
+ return new RegExp(regex);
3048
+ };
3049
+ const isWithinBase = (relativePath, basePath) => {
3050
+ return !basePath || relativePath === basePath || relativePath.startsWith(`${basePath}/`);
3051
+ };
3052
+ const getBaseRelativePath = (relativePath, basePath) => {
3053
+ if (!basePath) {
3054
+ return relativePath;
3055
+ }
3056
+ if (relativePath === basePath) {
3057
+ return '';
3058
+ }
3059
+ return relativePath.slice(basePath.length + 1);
3060
+ };
3061
+ const matchesDirectoryPattern = (baseRelativePath, pattern) => {
3062
+ if (pattern.hasSlash || pattern.anchored) {
3063
+ return baseRelativePath === pattern.pattern || baseRelativePath.startsWith(`${pattern.pattern}/`);
3064
+ }
3065
+ return baseRelativePath.split('/').includes(pattern.pattern);
3066
+ };
3067
+ const matchesPathPattern = (baseRelativePath, pattern) => {
3068
+ const regex = globToRegex(pattern.pattern);
3069
+ if (pattern.hasSlash || pattern.anchored) {
3070
+ return regex.test(baseRelativePath);
3071
+ }
3072
+ return baseRelativePath.split('/').some(part => regex.test(part));
3073
+ };
3074
+ const matchesPattern = (baseRelativePath, pattern) => {
3075
+ if (!baseRelativePath) {
3076
+ return false;
3077
+ }
3078
+ if (pattern.directoryOnly) {
3079
+ return matchesDirectoryPattern(baseRelativePath, pattern);
3080
+ }
3081
+ return matchesPathPattern(baseRelativePath, pattern);
3082
+ };
3083
+ const isGitIgnored = (relativePath, patterns) => {
3084
+ let ignored = false;
3085
+ for (const pattern of patterns) {
3086
+ if (!isWithinBase(relativePath, pattern.basePath)) {
3087
+ continue;
3088
+ }
3089
+ const baseRelativePath = getBaseRelativePath(relativePath, pattern.basePath);
3090
+ if (matchesPattern(baseRelativePath, pattern)) {
3091
+ ignored = !pattern.negative;
3092
+ }
3093
+ }
3094
+ return ignored;
3095
+ };
3096
+
3097
+ const getGitIgnoredUris = async (root, items, pathSeparator, enabled) => {
3098
+ if (!enabled || !root || items.length === 0) {
3099
+ return [];
3100
+ }
3101
+ const patterns = await getGitIgnoreFiles(root, items, pathSeparator);
3102
+ if (patterns.length === 0) {
3103
+ return [];
3104
+ }
3105
+ return items.filter(item => {
3106
+ const relativePath = getGitIgnoreRelativePath(root, item.path, pathSeparator);
3107
+ return isGitIgnored(relativePath, patterns);
3108
+ }).map(item => item.path);
3109
+ };
3110
+
2578
3111
  // TODO optimize this function to return the minimum number
2579
3112
  // of visible items needed, e.g. when not scrolled 5 items with
2580
3113
  // 20px fill 100px but when scrolled 6 items are needed
@@ -2696,6 +3229,8 @@ const text = data => {
2696
3229
  };
2697
3230
  };
2698
3231
 
3232
+ new Set(Object.values(VirtualDomElements));
3233
+
2699
3234
  const SetText = 1;
2700
3235
  const Replace = 2;
2701
3236
  const SetAttribute = 3;
@@ -3053,18 +3588,55 @@ const {
3053
3588
  set,
3054
3589
  wrapGetter
3055
3590
  } = create$a();
3591
+ const commandQueues = new Map();
3592
+ const runQueuedCommand = async (previousCommand, command) => {
3593
+ try {
3594
+ await previousCommand;
3595
+ } catch {
3596
+ // Keep the queue usable after returning the error to the command caller
3597
+ }
3598
+ await command();
3599
+ };
3600
+ const enqueueCommand = async (id, command) => {
3601
+ const currentCommand = runQueuedCommand(commandQueues.get(id), command);
3602
+ commandQueues.set(id, currentCommand);
3603
+ try {
3604
+ await currentCommand;
3605
+ } finally {
3606
+ if (commandQueues.get(id) === currentCommand) {
3607
+ commandQueues.delete(id);
3608
+ }
3609
+ }
3610
+ };
3056
3611
  const hasSameVisibleExplorerItemInputs = (oldState, newState) => {
3057
3612
  return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.height === newState.height && oldState.itemHeight === newState.itemHeight && oldState.focusedIndex === newState.focusedIndex && oldState.editingIndex === newState.editingIndex && oldState.editingIcon === newState.editingIcon && oldState.cutItems === newState.cutItems && oldState.editingErrorMessage === newState.editingErrorMessage && oldState.dropTargets === newState.dropTargets && oldState.fileIconCache === newState.fileIconCache && oldState.decorations === newState.decorations && oldState.useChevrons === newState.useChevrons && oldState.sourceControlIgnoredUris === newState.sourceControlIgnoredUris;
3058
3613
  };
3059
- const wrapListItemCommand = fn => {
3060
- const wrappedCommand = async (id, ...args) => {
3614
+ const maybeUpdateGitIgnoredUris = async (oldState, newState) => {
3615
+ if (oldState.items === newState.items || oldState.sourceControlIgnoredUris !== newState.sourceControlIgnoredUris) {
3616
+ return newState;
3617
+ }
3618
+ const {
3619
+ gitIgnoreDecorations,
3620
+ items,
3621
+ pathSeparator,
3622
+ root
3623
+ } = newState;
3624
+ const sourceControlIgnoredUris = await getGitIgnoredUris(root, items, pathSeparator, gitIgnoreDecorations);
3625
+ return {
3626
+ ...newState,
3627
+ sourceControlIgnoredUris
3628
+ };
3629
+ };
3630
+ const wrapListItemCommandInternal = (fn, queued) => {
3631
+ const runCommand = async (id, ...args) => {
3061
3632
  const {
3062
3633
  newState
3063
3634
  } = get(id);
3064
- const updatedState = await fn(newState, ...args);
3065
- if (newState === updatedState) {
3635
+ const rawUpdatedState = await fn(newState, ...args);
3636
+ if (newState === rawUpdatedState) {
3066
3637
  return;
3067
3638
  }
3639
+ const updatedState = await maybeUpdateGitIgnoredUris(newState, rawUpdatedState);
3068
3640
  const {
3069
3641
  cutItems,
3070
3642
  decorations,
@@ -3103,8 +3675,22 @@ const wrapListItemCommand = fn => {
3103
3675
  const intermediate2 = get(id);
3104
3676
  set(id, intermediate2.oldState, finalState);
3105
3677
  };
3678
+ if (!queued) {
3679
+ return runCommand;
3680
+ }
3681
+ const wrappedCommand = async (id, ...args) => {
3682
+ await enqueueCommand(id, async () => {
3683
+ await runCommand(id, ...args);
3684
+ });
3685
+ };
3106
3686
  return wrappedCommand;
3107
3687
  };
3688
+ const wrapListItemCommand = fn => {
3689
+ return wrapListItemCommandInternal(fn, true);
3690
+ };
3691
+ const wrapListItemCommandImmediate = fn => {
3692
+ return wrapListItemCommandInternal(fn, false);
3693
+ };
3108
3694
 
3109
3695
  const ListItem = 22;
3110
3696
 
@@ -3144,6 +3730,7 @@ const create = (id, uri, x, y, width, height, args, parentUid, platform = 0, ass
3144
3730
  focusedIndex: -1,
3145
3731
  focusWord: '',
3146
3732
  focusWordTimeout: 800,
3733
+ gitIgnoreDecorations: false,
3147
3734
  handleOffset: 0,
3148
3735
  hasError: false,
3149
3736
  height,
@@ -4240,7 +4827,9 @@ const refresh = async state => {
4240
4827
  const {
4241
4828
  excluded,
4242
4829
  focusedIndex,
4830
+ gitIgnoreDecorations,
4243
4831
  items,
4832
+ pathSeparator,
4244
4833
  root
4245
4834
  } = state;
4246
4835
  const expandedDirents = getExpandedDirents(items);
@@ -4253,10 +4842,12 @@ const refresh = async state => {
4253
4842
  if (focusedIndex >= newItems.length) {
4254
4843
  newFocusedIndex = newItems.length - 1;
4255
4844
  }
4845
+ const sourceControlIgnoredUris = await getGitIgnoredUris(root, newItems, pathSeparator, gitIgnoreDecorations);
4256
4846
  return {
4257
4847
  ...state,
4258
4848
  focusedIndex: newFocusedIndex,
4259
- items: newItems
4849
+ items: newItems,
4850
+ sourceControlIgnoredUris
4260
4851
  };
4261
4852
  };
4262
4853
 
@@ -4438,15 +5029,21 @@ const handleRangeSelection = (state, startIndex, endIndex) => {
4438
5029
 
4439
5030
  const handleClickAtRangeSelection = async (state, index) => {
4440
5031
  const {
5032
+ focusedIndex,
4441
5033
  items
4442
5034
  } = state;
4443
5035
  const firstSelectedIndex = items.findIndex(item => item.selected);
4444
- if (firstSelectedIndex === -1) {
4445
- return handleRangeSelection(state, index, index);
5036
+ let anchorIndex = firstSelectedIndex;
5037
+ if (anchorIndex === -1) {
5038
+ anchorIndex = focusedIndex === -1 ? index : focusedIndex;
4446
5039
  }
4447
- const min = Math.min(firstSelectedIndex, index);
4448
- const max = Math.min(firstSelectedIndex, index);
4449
- return handleRangeSelection(state, min, max);
5040
+ const min = Math.min(anchorIndex, index);
5041
+ const max = Math.max(anchorIndex, index);
5042
+ const newState = handleRangeSelection(state, min, max);
5043
+ return {
5044
+ ...newState,
5045
+ focusedIndex: index
5046
+ };
4450
5047
  };
4451
5048
 
4452
5049
  const toggleIndividualSelection = async (state, index) => {
@@ -4835,12 +5432,15 @@ const getSettings = async () => {
4835
5432
  const confirmPaste = confirmPasteRaw === false ? false : false;
4836
5433
  const excludedRaw = await invoke$2('Preferences.get', 'files.exclude');
4837
5434
  const excluded = getExcluded(excludedRaw);
5435
+ const gitIgnoreDecorationsRaw = await invoke$2('Preferences.get', 'explorer.gitIgnoreDecorations');
5436
+ const gitIgnoreDecorations = gitIgnoreDecorationsRaw === false ? false : true;
4838
5437
  const sourceControlDecorationsRaw = await invoke$2('Preferences.get', 'explorer.sourceControlDecorations');
4839
5438
  const sourceControlDecorations = sourceControlDecorationsRaw === false ? false : true;
4840
5439
  return {
4841
5440
  confirmDelete,
4842
5441
  confirmPaste,
4843
5442
  excluded,
5443
+ gitIgnoreDecorations,
4844
5444
  sourceControlDecorations,
4845
5445
  useChevrons
4846
5446
  };
@@ -4954,6 +5554,7 @@ const loadContent = async (state, savedState) => {
4954
5554
  const {
4955
5555
  confirmDelete,
4956
5556
  excluded,
5557
+ gitIgnoreDecorations,
4957
5558
  sourceControlDecorations,
4958
5559
  useChevrons
4959
5560
  } = await getSettings();
@@ -4971,6 +5572,7 @@ const loadContent = async (state, savedState) => {
4971
5572
  const minLineY = Math.round(deltaY / itemHeight);
4972
5573
  const scheme = getScheme(root);
4973
5574
  const decorations = await getFileDecorations(scheme, root, restoredDirents.filter(item => item.depth === 1).map(item => item.path), sourceControlDecorations, assetDir, platform);
5575
+ const sourceControlIgnoredUris = await getGitIgnoredUris(root, restoredDirents, pathSeparator, gitIgnoreDecorations);
4974
5576
  return {
4975
5577
  ...state,
4976
5578
  confirmDelete,
@@ -4979,6 +5581,7 @@ const loadContent = async (state, savedState) => {
4979
5581
  errorCode: '',
4980
5582
  errorMessage: '',
4981
5583
  excluded,
5584
+ gitIgnoreDecorations,
4982
5585
  hasError: false,
4983
5586
  initial: false,
4984
5587
  isReadonly: isReadonly$1,
@@ -4987,6 +5590,7 @@ const loadContent = async (state, savedState) => {
4987
5590
  minLineY,
4988
5591
  pathSeparator,
4989
5592
  root,
5593
+ sourceControlIgnoredUris,
4990
5594
  useChevrons
4991
5595
  };
4992
5596
  } catch (error) {
@@ -4997,6 +5601,7 @@ const loadContent = async (state, savedState) => {
4997
5601
  confirmDelete,
4998
5602
  errorCode,
4999
5603
  errorMessage,
5604
+ gitIgnoreDecorations,
5000
5605
  hasError: true,
5001
5606
  initial: false,
5002
5607
  isReadonly: false,
@@ -5856,13 +6461,13 @@ const handleWheel = (state, deltaMode, deltaY) => {
5856
6461
  return setDeltaY(state, state.deltaY + deltaY);
5857
6462
  };
5858
6463
 
5859
- const handleWorkspaceChange = async state => {
6464
+ const handleWorkspaceChange = async (state, _workspacePath, savedState) => {
5860
6465
  const newRoot = await getWorkspacePath();
5861
6466
  const state1 = {
5862
6467
  ...state,
5863
6468
  root: newRoot
5864
6469
  };
5865
- const newState = await loadContent(state1, undefined);
6470
+ const newState = await loadContent(state1, savedState);
5866
6471
  return newState;
5867
6472
  };
5868
6473
 
@@ -6852,8 +7457,9 @@ const revealItemHidden = async (state, uri) => {
6852
7457
  const pathPartsChildrenFlat = pathPartsChildren.flat();
6853
7458
  const orderedPathParts = orderDirents(pathPartsChildrenFlat);
6854
7459
  const mergedDirents = mergeVisibleWithHiddenItems(items, orderedPathParts);
7460
+ const orderedDirents = orderDirents(mergedDirents);
6855
7461
  const expandedPaths = new Set(pathPartsToReveal.map(pathPart => pathPart.path));
6856
- const newDirents = mergedDirents.map(item => {
7462
+ const newDirents = orderedDirents.map(item => {
6857
7463
  if (expandedPaths.has(item.path) && item.type === Directory) {
6858
7464
  return {
6859
7465
  ...item,
@@ -7116,8 +7722,8 @@ const commandMap = {
7116
7722
  'Explorer.handleResize': wrapListItemCommand(handleResize),
7117
7723
  'Explorer.handleUpload': wrapListItemCommand(handleUpload),
7118
7724
  'Explorer.handleWheel': wrapListItemCommand(handleWheel),
7119
- 'Explorer.handleWorkspaceChange': wrapListItemCommand(handleWorkspaceChange),
7120
- 'Explorer.handleWorkspaceRefresh': wrapListItemCommand(handleWorkspaceRefresh),
7725
+ 'Explorer.handleWorkspaceChange': wrapListItemCommandImmediate(handleWorkspaceChange),
7726
+ 'Explorer.handleWorkspaceRefresh': wrapListItemCommandImmediate(handleWorkspaceRefresh),
7121
7727
  'Explorer.initialize': initialize,
7122
7728
  'Explorer.loadContent': wrapListItemCommand(loadContent),
7123
7729
  'Explorer.newFile': wrapListItemCommand(newFile),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/explorer-view",
3
- "version": "7.6.0",
3
+ "version": "7.9.0",
4
4
  "description": "Explorer Worker",
5
5
  "repository": {
6
6
  "type": "git",