@theia/core 1.66.0-next.44 → 1.66.0-next.73

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 (71) hide show
  1. package/lib/browser/authentication-service.d.ts +14 -10
  2. package/lib/browser/authentication-service.d.ts.map +1 -1
  3. package/lib/browser/authentication-service.js +23 -11
  4. package/lib/browser/authentication-service.js.map +1 -1
  5. package/lib/browser/catalog.json +17 -9
  6. package/lib/browser/credentials-service.d.ts +2 -0
  7. package/lib/browser/credentials-service.d.ts.map +1 -1
  8. package/lib/browser/credentials-service.js +6 -0
  9. package/lib/browser/credentials-service.js.map +1 -1
  10. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  11. package/lib/browser/frontend-application-module.js +3 -0
  12. package/lib/browser/frontend-application-module.js.map +1 -1
  13. package/lib/browser/symbol-icon-color-contribution.d.ts +6 -0
  14. package/lib/browser/symbol-icon-color-contribution.d.ts.map +1 -0
  15. package/lib/browser/symbol-icon-color-contribution.js +212 -0
  16. package/lib/browser/symbol-icon-color-contribution.js.map +1 -0
  17. package/lib/browser/tree/tree-widget.d.ts +6 -0
  18. package/lib/browser/tree/tree-widget.d.ts.map +1 -1
  19. package/lib/browser/tree/tree-widget.js +23 -6
  20. package/lib/browser/tree/tree-widget.js.map +1 -1
  21. package/lib/browser-only/frontend-only-application-module.d.ts.map +1 -1
  22. package/lib/browser-only/frontend-only-application-module.js +2 -1
  23. package/lib/browser-only/frontend-only-application-module.js.map +1 -1
  24. package/lib/common/color.d.ts +17 -1
  25. package/lib/common/color.d.ts.map +1 -1
  26. package/lib/common/color.js +62 -1
  27. package/lib/common/color.js.map +1 -1
  28. package/lib/common/content-replacer-v2-impl.d.ts +70 -0
  29. package/lib/common/content-replacer-v2-impl.d.ts.map +1 -0
  30. package/lib/common/content-replacer-v2-impl.js +407 -0
  31. package/lib/common/content-replacer-v2-impl.js.map +1 -0
  32. package/lib/common/content-replacer-v2-impl.spec.d.ts +2 -0
  33. package/lib/common/content-replacer-v2-impl.spec.d.ts.map +1 -0
  34. package/lib/common/content-replacer-v2-impl.spec.js +319 -0
  35. package/lib/common/content-replacer-v2-impl.spec.js.map +1 -0
  36. package/lib/common/content-replacer.d.ts +13 -1
  37. package/lib/common/content-replacer.d.ts.map +1 -1
  38. package/lib/common/content-replacer.js +3 -3
  39. package/lib/common/content-replacer.js.map +1 -1
  40. package/lib/common/content-replacer.spec.js +2 -2
  41. package/lib/common/content-replacer.spec.js.map +1 -1
  42. package/lib/common/key-store.d.ts +1 -0
  43. package/lib/common/key-store.d.ts.map +1 -1
  44. package/lib/electron-browser/menu/electron-menu-contribution.js +1 -1
  45. package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
  46. package/lib/node/key-store-server.d.ts +1 -0
  47. package/lib/node/key-store-server.d.ts.map +1 -1
  48. package/lib/node/key-store-server.js +4 -0
  49. package/lib/node/key-store-server.js.map +1 -1
  50. package/lib/node/key-store-server.spec.d.ts +2 -0
  51. package/lib/node/key-store-server.spec.d.ts.map +1 -0
  52. package/lib/node/key-store-server.spec.js +226 -0
  53. package/lib/node/key-store-server.spec.js.map +1 -0
  54. package/package.json +4 -4
  55. package/src/browser/authentication-service.ts +57 -18
  56. package/src/browser/credentials-service.ts +9 -0
  57. package/src/browser/frontend-application-module.ts +3 -0
  58. package/src/browser/style/index.css +1 -0
  59. package/src/browser/style/symbol-icon.css +258 -0
  60. package/src/browser/symbol-icon-color-contribution.ts +242 -0
  61. package/src/browser/tree/tree-widget.tsx +25 -6
  62. package/src/browser-only/frontend-only-application-module.ts +2 -1
  63. package/src/common/color.ts +51 -1
  64. package/src/common/content-replacer-v2-impl.spec.ts +344 -0
  65. package/src/common/content-replacer-v2-impl.ts +471 -0
  66. package/src/common/content-replacer.spec.ts +4 -4
  67. package/src/common/content-replacer.ts +11 -1
  68. package/src/common/key-store.ts +1 -0
  69. package/src/electron-browser/menu/electron-menu-contribution.ts +1 -1
  70. package/src/node/key-store-server.spec.ts +262 -0
  71. package/src/node/key-store-server.ts +5 -0
@@ -0,0 +1,344 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { expect } from 'chai';
18
+ import { ContentReplacerV2Impl } from './content-replacer-v2-impl';
19
+ import { Replacement } from './content-replacer';
20
+
21
+ describe('ContentReplacerV2Impl', () => {
22
+ let contentReplacer: ContentReplacerV2Impl;
23
+
24
+ before(() => {
25
+ contentReplacer = new ContentReplacerV2Impl();
26
+ });
27
+
28
+ // All original V1 test cases for backward compatibility
29
+ describe('V1 compatibility tests', () => {
30
+ it('should replace content when oldContent matches exactly', () => {
31
+ const originalContent = 'Hello World!';
32
+ const replacements: Replacement[] = [
33
+ { oldContent: 'World', newContent: 'Universe' }
34
+ ];
35
+ const expectedContent = 'Hello Universe!';
36
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
37
+ expect(result.updatedContent).to.equal(expectedContent);
38
+ expect(result.errors).to.be.empty;
39
+ });
40
+
41
+ it('should replace content when oldContent matches after trimming lines', () => {
42
+ const originalContent = 'Line one\n Line two \nLine three';
43
+ const replacements: Replacement[] = [
44
+ { oldContent: 'Line two', newContent: 'Second Line' }
45
+ ];
46
+ const expectedContent = 'Line one\n Second Line \nLine three';
47
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
48
+ expect(result.updatedContent).to.equal(expectedContent);
49
+ expect(result.errors).to.be.empty;
50
+ });
51
+
52
+ it('should return an error when oldContent is not found', () => {
53
+ const originalContent = 'Sample content';
54
+ const replacements: Replacement[] = [
55
+ { oldContent: 'Nonexistent', newContent: 'Replacement' }
56
+ ];
57
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
58
+ expect(result.updatedContent).to.equal(originalContent);
59
+ expect(result.errors).to.include('Content to replace not found: "Nonexistent"');
60
+ });
61
+
62
+ it('should return an error when oldContent has multiple occurrences', () => {
63
+ const originalContent = 'Repeat Repeat Repeat';
64
+ const replacements: Replacement[] = [
65
+ { oldContent: 'Repeat', newContent: 'Once' }
66
+ ];
67
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
68
+ expect(result.updatedContent).to.equal(originalContent);
69
+ expect(result.errors.some(candidate => candidate.startsWith('Multiple occurrences found for: "Repeat"'))).to.be.true;
70
+ });
71
+
72
+ it('should prepend newContent when oldContent is an empty string', () => {
73
+ const originalContent = 'Existing content';
74
+ const replacements: Replacement[] = [
75
+ { oldContent: '', newContent: 'Prepended content\n' }
76
+ ];
77
+ const expectedContent = 'Prepended content\nExisting content';
78
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
79
+ expect(result.updatedContent).to.equal(expectedContent);
80
+ expect(result.errors).to.be.empty;
81
+ });
82
+
83
+ it('should handle multiple replacements correctly', () => {
84
+ const originalContent = 'Foo Bar Baz';
85
+ const replacements: Replacement[] = [
86
+ { oldContent: 'Foo', newContent: 'FooModified' },
87
+ { oldContent: 'Bar', newContent: 'BarModified' },
88
+ { oldContent: 'Baz', newContent: 'BazModified' }
89
+ ];
90
+ const expectedContent = 'FooModified BarModified BazModified';
91
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
92
+ expect(result.updatedContent).to.equal(expectedContent);
93
+ expect(result.errors).to.be.empty;
94
+ });
95
+
96
+ it('should replace all occurrences when multiple is true', () => {
97
+ const originalContent = 'Repeat Repeat Repeat';
98
+ const replacements: Replacement[] = [
99
+ { oldContent: 'Repeat', newContent: 'Once', multiple: true }
100
+ ];
101
+ const expectedContent = 'Once Once Once';
102
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
103
+ expect(result.updatedContent).to.equal(expectedContent);
104
+ expect(result.errors).to.be.empty;
105
+ });
106
+
107
+ it('should return an error when multiple is false and multiple occurrences are found', () => {
108
+ const originalContent = 'Repeat Repeat Repeat';
109
+ const replacements: Replacement[] = [
110
+ { oldContent: 'Repeat', newContent: 'Once', multiple: false }
111
+ ];
112
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
113
+ expect(result.updatedContent).to.equal(originalContent);
114
+ expect(result.errors.some(candidate => candidate.startsWith('Multiple occurrences found for: "Repeat"'))).to.be.true;
115
+ });
116
+
117
+ it('should return an error when conflicting replacements for the same oldContent are provided', () => {
118
+ const originalContent = 'Conflict test content';
119
+ const replacements: Replacement[] = [
120
+ { oldContent: 'test', newContent: 'test1' },
121
+ { oldContent: 'test', newContent: 'test2' }
122
+ ];
123
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
124
+ expect(result.updatedContent).to.equal(originalContent);
125
+ expect(result.errors).to.include('Conflicting replacement values for: "test"');
126
+ });
127
+ });
128
+
129
+ // New V2 feature tests
130
+ describe('V2 enhanced features', () => {
131
+ describe('Line ending normalization', () => {
132
+ it('should match content with different line endings (CRLF vs LF)', () => {
133
+ const originalContent = 'Line one\r\nLine two\r\nLine three';
134
+ const replacements: Replacement[] = [
135
+ { oldContent: 'Line one\nLine two', newContent: 'Modified lines' }
136
+ ];
137
+ const expectedContent = 'Modified lines\r\nLine three';
138
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
139
+ expect(result.updatedContent).to.equal(expectedContent);
140
+ expect(result.errors).to.be.empty;
141
+ });
142
+
143
+ it('should preserve original line endings when replacing', () => {
144
+ const originalContent = 'Line one\r\nLine two\r\nLine three';
145
+ const replacements: Replacement[] = [
146
+ { oldContent: 'Line two', newContent: 'New line\nWith LF' }
147
+ ];
148
+ const expectedContent = 'Line one\r\nNew line\r\nWith LF\r\nLine three';
149
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
150
+ expect(result.updatedContent).to.equal(expectedContent);
151
+ expect(result.errors).to.be.empty;
152
+ });
153
+
154
+ it('should handle mixed line endings', () => {
155
+ const originalContent = 'Line one\nLine two\r\nLine three\rLine four';
156
+ const replacements: Replacement[] = [
157
+ { oldContent: 'Line two\nLine three', newContent: 'Replaced content' }
158
+ ];
159
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
160
+ expect(result.errors).to.be.empty;
161
+ expect(result.updatedContent).to.include('Replaced content');
162
+ });
163
+ });
164
+
165
+ describe('Multi-line fuzzy matching', () => {
166
+ it('should match multi-line content with different indentation', () => {
167
+ const originalContent = ' function test() {\n console.log("hello");\n return true;\n }';
168
+ const replacements: Replacement[] = [
169
+ {
170
+ oldContent: 'function test() {\nconsole.log("hello");\nreturn true;\n}',
171
+ newContent: 'function test() {\n console.log("modified");\n return false;\n}'
172
+ }
173
+ ];
174
+ const expectedContent = ' function test() {\n console.log("modified");\n return false;\n }';
175
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
176
+ expect(result.updatedContent).to.equal(expectedContent);
177
+ expect(result.errors).to.be.empty;
178
+ });
179
+
180
+ it('should match content with extra whitespace between lines', () => {
181
+ const originalContent = 'function test() {\n \n console.log("hello");\n \n}';
182
+ const replacements: Replacement[] = [
183
+ {
184
+ oldContent: 'function test() {\nconsole.log("hello");\n}',
185
+ newContent: 'function modified() {\n console.log("world");\n}'
186
+ }
187
+ ];
188
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
189
+ expect(result.errors).to.be.empty;
190
+ expect(result.updatedContent).to.include('function modified()');
191
+ expect(result.updatedContent).to.include('console.log("world")');
192
+ });
193
+
194
+ it('should match content with trailing whitespace on lines', () => {
195
+ const originalContent = 'const x = 1; \nconst y = 2; \n';
196
+ const replacements: Replacement[] = [
197
+ {
198
+ oldContent: 'const x = 1;\nconst y = 2;',
199
+ newContent: 'const a = 3;\nconst b = 4;'
200
+ }
201
+ ];
202
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
203
+ expect(result.errors).to.be.empty;
204
+ expect(result.updatedContent).to.include('const a = 3;');
205
+ expect(result.updatedContent).to.include('const b = 4;');
206
+ });
207
+ });
208
+
209
+ describe('Indentation preservation', () => {
210
+ it('should preserve indentation when replacing single line', () => {
211
+ const originalContent = ' const x = 1;\n const y = 2;';
212
+ const replacements: Replacement[] = [
213
+ { oldContent: 'const x = 1;', newContent: 'const a = 3;' }
214
+ ];
215
+ const expectedContent = ' const a = 3;\n const y = 2;';
216
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
217
+ expect(result.updatedContent).to.equal(expectedContent);
218
+ expect(result.errors).to.be.empty;
219
+ });
220
+
221
+ it('should preserve relative indentation in multi-line replacements', () => {
222
+ const originalContent = ' if (condition) {\n doSomething();\n }';
223
+ const replacements: Replacement[] = [
224
+ {
225
+ oldContent: 'if (condition) {\n doSomething();\n}',
226
+ newContent: 'if (newCondition) {\n doFirst();\n doSecond();\n}'
227
+ }
228
+ ];
229
+ const expectedContent = ' if (newCondition) {\n doFirst();\n doSecond();\n }';
230
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
231
+ expect(result.updatedContent).to.equal(expectedContent);
232
+ expect(result.errors).to.be.empty;
233
+ });
234
+
235
+ it('should handle tabs and spaces correctly', () => {
236
+ const originalContent = '\tfunction test() {\n\t\tconsole.log("hello");\n\t}';
237
+ const replacements: Replacement[] = [
238
+ {
239
+ oldContent: 'function test() {\n console.log("hello");\n}',
240
+ newContent: 'function modified() {\n console.log("world");\n}'
241
+ }
242
+ ];
243
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
244
+ expect(result.errors).to.be.empty;
245
+ expect(result.updatedContent).to.match(/^\tfunction modified/);
246
+ expect(result.updatedContent).to.include('\t\tconsole.log("world")');
247
+ });
248
+ });
249
+
250
+ describe('Error handling improvements', () => {
251
+ it('should truncate long content in error messages', () => {
252
+ const longContent = 'a'.repeat(200);
253
+ const originalContent = 'Some content';
254
+ const replacements: Replacement[] = [
255
+ { oldContent: longContent, newContent: 'replacement' }
256
+ ];
257
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
258
+ expect(result.errors.length).to.equal(1);
259
+ expect(result.errors[0].length).to.be.lessThan(250); // Error message should be truncated
260
+ expect(result.errors[0]).to.include('...');
261
+ });
262
+ });
263
+
264
+ describe('Complex scenarios', () => {
265
+ it('should handle multiple replacements with different matching strategies', () => {
266
+ const originalContent = 'Line 1\r\n Line 2 \nLine 3\nExact match here';
267
+ const replacements: Replacement[] = [
268
+ { oldContent: 'Line 1\nLine 2', newContent: 'Modified 1-2' }, // Line ending normalization
269
+ { oldContent: 'Line 3', newContent: 'Modified 3' }, // Trimmed match
270
+ { oldContent: 'Exact match here', newContent: 'Exact replaced' } // Exact match
271
+ ];
272
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
273
+ expect(result.errors).to.be.empty;
274
+ expect(result.updatedContent).to.include('Modified 1-2');
275
+ expect(result.updatedContent).to.include('Modified 3');
276
+ expect(result.updatedContent).to.include('Exact replaced');
277
+ });
278
+
279
+ it('should handle code blocks with varying indentation', () => {
280
+ const originalContent = `
281
+ class MyClass {
282
+ constructor() {
283
+ this.value = 42;
284
+ }
285
+
286
+ getValue() {
287
+ return this.value;
288
+ }
289
+ }`;
290
+ const replacements: Replacement[] = [
291
+ {
292
+ oldContent: `getValue() {
293
+ return this.value;
294
+ }`,
295
+ newContent: `getValue() {
296
+ console.log('Getting value');
297
+ return this.value;
298
+ }`
299
+ }
300
+ ];
301
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
302
+ expect(result.errors).to.be.empty;
303
+ expect(result.updatedContent).to.include("console.log('Getting value')");
304
+ // Check that indentation is preserved
305
+ expect(result.updatedContent).to.match(/ getValue\(\) \{[\r\n\s]*console\.log/);
306
+ });
307
+
308
+ it('should handle empty lines in multi-line matches', () => {
309
+ const originalContent = 'function test() {\n\n return true;\n\n}';
310
+ const replacements: Replacement[] = [
311
+ {
312
+ oldContent: 'function test() {\n\nreturn true;\n\n}',
313
+ newContent: 'function test() {\n return false;\n}'
314
+ }
315
+ ];
316
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
317
+ expect(result.errors).to.be.empty;
318
+ expect(result.updatedContent).to.include('return false');
319
+ });
320
+ });
321
+
322
+ describe('Multiple occurrences with fuzzy matching', () => {
323
+ it('should handle multiple occurrences with fuzzy matching when multiple is true', () => {
324
+ const originalContent = ' item1\n\n item2\n\n item1';
325
+ const replacements: Replacement[] = [
326
+ { oldContent: 'item1', newContent: 'replaced', multiple: true }
327
+ ];
328
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
329
+ expect(result.errors).to.be.empty;
330
+ expect(result.updatedContent.match(/replaced/g)).to.have.length(2);
331
+ });
332
+
333
+ it('should detect multiple fuzzy matches and error when multiple is false', () => {
334
+ const originalContent = ' function a() {}\n\n function a() {}';
335
+ const replacements: Replacement[] = [
336
+ { oldContent: 'function a() {}', newContent: 'function b() {}', multiple: false }
337
+ ];
338
+ const result = contentReplacer.applyReplacements(originalContent, replacements);
339
+ expect(result.updatedContent).to.equal(originalContent);
340
+ expect(result.errors.some(err => err.includes('Multiple occurrences found'))).to.be.true;
341
+ });
342
+ });
343
+ });
344
+ });