@theia/vsx-registry 1.45.1 → 1.46.0-next.72

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 (100) hide show
  1. package/README.md +45 -45
  2. package/lib/browser/recommended-extensions/preference-provider-overrides.d.ts +17 -17
  3. package/lib/browser/recommended-extensions/preference-provider-overrides.js +95 -95
  4. package/lib/browser/recommended-extensions/recommended-extensions-json-schema.d.ts +14 -14
  5. package/lib/browser/recommended-extensions/recommended-extensions-json-schema.js +94 -94
  6. package/lib/browser/recommended-extensions/recommended-extensions-preference-contribution.d.ts +11 -11
  7. package/lib/browser/recommended-extensions/recommended-extensions-preference-contribution.js +59 -59
  8. package/lib/browser/vsx-extension-commands.d.ts +14 -13
  9. package/lib/browser/vsx-extension-commands.d.ts.map +1 -1
  10. package/lib/browser/vsx-extension-commands.js +68 -63
  11. package/lib/browser/vsx-extension-commands.js.map +1 -1
  12. package/lib/browser/vsx-extension-editor-manager.d.ts +9 -9
  13. package/lib/browser/vsx-extension-editor-manager.js +49 -49
  14. package/lib/browser/vsx-extension-editor.d.ts +21 -21
  15. package/lib/browser/vsx-extension-editor.js +109 -109
  16. package/lib/browser/vsx-extension.d.ts +146 -143
  17. package/lib/browser/vsx-extension.d.ts.map +1 -1
  18. package/lib/browser/vsx-extension.js +616 -596
  19. package/lib/browser/vsx-extension.js.map +1 -1
  20. package/lib/browser/vsx-extensions-contribution.d.ts +70 -60
  21. package/lib/browser/vsx-extensions-contribution.d.ts.map +1 -1
  22. package/lib/browser/vsx-extensions-contribution.js +375 -344
  23. package/lib/browser/vsx-extensions-contribution.js.map +1 -1
  24. package/lib/browser/vsx-extensions-model.d.ts +75 -72
  25. package/lib/browser/vsx-extensions-model.d.ts.map +1 -1
  26. package/lib/browser/vsx-extensions-model.js +437 -391
  27. package/lib/browser/vsx-extensions-model.js.map +1 -1
  28. package/lib/browser/vsx-extensions-preferences.d.ts +12 -0
  29. package/lib/browser/vsx-extensions-preferences.d.ts.map +1 -0
  30. package/lib/browser/vsx-extensions-preferences.js +47 -0
  31. package/lib/browser/vsx-extensions-preferences.js.map +1 -0
  32. package/lib/browser/vsx-extensions-search-bar.d.ts +22 -14
  33. package/lib/browser/vsx-extensions-search-bar.d.ts.map +1 -1
  34. package/lib/browser/vsx-extensions-search-bar.js +106 -75
  35. package/lib/browser/vsx-extensions-search-bar.js.map +1 -1
  36. package/lib/browser/vsx-extensions-search-model.d.ts +21 -21
  37. package/lib/browser/vsx-extensions-search-model.js +70 -70
  38. package/lib/browser/vsx-extensions-source.d.ts +19 -19
  39. package/lib/browser/vsx-extensions-source.js +102 -102
  40. package/lib/browser/vsx-extensions-view-container.d.ts +49 -49
  41. package/lib/browser/vsx-extensions-view-container.js +179 -179
  42. package/lib/browser/vsx-extensions-widget.d.ts +35 -34
  43. package/lib/browser/vsx-extensions-widget.d.ts.map +1 -1
  44. package/lib/browser/vsx-extensions-widget.js +164 -156
  45. package/lib/browser/vsx-extensions-widget.js.map +1 -1
  46. package/lib/browser/vsx-language-quick-pick-service.d.ts +15 -15
  47. package/lib/browser/vsx-language-quick-pick-service.js +121 -121
  48. package/lib/browser/vsx-registry-frontend-module.d.ts +4 -4
  49. package/lib/browser/vsx-registry-frontend-module.d.ts.map +1 -1
  50. package/lib/browser/vsx-registry-frontend-module.js +99 -97
  51. package/lib/browser/vsx-registry-frontend-module.js.map +1 -1
  52. package/lib/common/index.d.ts +3 -3
  53. package/lib/common/index.js +25 -25
  54. package/lib/common/ovsx-client-provider.d.ts +13 -13
  55. package/lib/common/ovsx-client-provider.js +29 -29
  56. package/lib/common/vsx-environment.d.ts +9 -9
  57. package/lib/common/vsx-environment.js +20 -20
  58. package/lib/common/vsx-extension-uri.d.ts +3 -3
  59. package/lib/common/vsx-extension-uri.js +20 -20
  60. package/lib/common/vsx-registry-common-module.d.ts +3 -3
  61. package/lib/common/vsx-registry-common-module.js +57 -57
  62. package/lib/node/vsx-cli.d.ts +9 -9
  63. package/lib/node/vsx-cli.js +41 -41
  64. package/lib/node/vsx-environment-impl.d.ts +14 -14
  65. package/lib/node/vsx-environment-impl.js +61 -61
  66. package/lib/node/vsx-extension-resolver.d.ts +20 -20
  67. package/lib/node/vsx-extension-resolver.js +154 -154
  68. package/lib/node/vsx-registry-backend-module.d.ts +3 -3
  69. package/lib/node/vsx-registry-backend-module.js +35 -35
  70. package/lib/package.spec.js +25 -25
  71. package/package.json +12 -12
  72. package/src/browser/recommended-extensions/preference-provider-overrides.ts +99 -99
  73. package/src/browser/recommended-extensions/recommended-extensions-json-schema.ts +74 -74
  74. package/src/browser/recommended-extensions/recommended-extensions-preference-contribution.ts +68 -68
  75. package/src/browser/style/extensions.svg +4 -4
  76. package/src/browser/style/index.css +436 -373
  77. package/src/browser/vsx-extension-commands.ts +68 -63
  78. package/src/browser/vsx-extension-editor-manager.ts +42 -42
  79. package/src/browser/vsx-extension-editor.tsx +96 -96
  80. package/src/browser/vsx-extension.tsx +704 -675
  81. package/src/browser/vsx-extensions-contribution.ts +361 -327
  82. package/src/browser/vsx-extensions-model.ts +436 -389
  83. package/src/browser/vsx-extensions-preferences.ts +58 -0
  84. package/src/browser/vsx-extensions-search-bar.tsx +107 -69
  85. package/src/browser/vsx-extensions-search-model.ts +61 -61
  86. package/src/browser/vsx-extensions-source.ts +83 -83
  87. package/src/browser/vsx-extensions-view-container.ts +179 -179
  88. package/src/browser/vsx-extensions-widget.tsx +165 -156
  89. package/src/browser/vsx-language-quick-pick-service.ts +110 -110
  90. package/src/browser/vsx-registry-frontend-module.ts +108 -106
  91. package/src/common/index.ts +19 -19
  92. package/src/common/ovsx-client-provider.ts +35 -35
  93. package/src/common/vsx-environment.ts +27 -27
  94. package/src/common/vsx-extension-uri.ts +20 -20
  95. package/src/common/vsx-registry-common-module.ts +63 -63
  96. package/src/node/vsx-cli.ts +38 -38
  97. package/src/node/vsx-environment-impl.ts +50 -50
  98. package/src/node/vsx-extension-resolver.ts +125 -125
  99. package/src/node/vsx-registry-backend-module.ts +35 -35
  100. package/src/package.spec.ts +29 -29
@@ -1,597 +1,617 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2020 TypeFox and others.
4
- //
5
- // This program and the accompanying materials are made available under the
6
- // terms of the Eclipse Public License v. 2.0 which is available at
7
- // http://www.eclipse.org/legal/epl-2.0.
8
- //
9
- // This Source Code may also be made available under the following Secondary
10
- // Licenses when the conditions for such availability set forth in the Eclipse
11
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
- // with the GNU Classpath Exception which is available at
13
- // https://www.gnu.org/software/classpath/license.html.
14
- //
15
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
- // *****************************************************************************
17
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
- return c > 3 && r && Object.defineProperty(target, key, r), r;
22
- };
23
- var __metadata = (this && this.__metadata) || function (k, v) {
24
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
- };
26
- var VSXExtension_1;
27
- Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.VSXExtensionEditorComponent = exports.VSXExtensionComponent = exports.AbstractVSXExtensionComponent = exports.VSXExtension = exports.VSXExtensionFactory = exports.VSXExtensionOptions = exports.VSXExtensionData = exports.VSXExtensionsContextMenu = exports.EXTENSIONS_CONTEXT_MENU = void 0;
29
- const React = require("@theia/core/shared/react");
30
- const DOMPurify = require("@theia/core/shared/dompurify");
31
- const inversify_1 = require("@theia/core/shared/inversify");
32
- const uri_1 = require("@theia/core/lib/common/uri");
33
- const opener_service_1 = require("@theia/core/lib/browser/opener-service");
34
- const hosted_plugin_1 = require("@theia/plugin-ext/lib/hosted/browser/hosted-plugin");
35
- const plugin_protocol_1 = require("@theia/plugin-ext/lib/common/plugin-protocol");
36
- const plugin_vscode_uri_1 = require("@theia/plugin-ext-vscode/lib/common/plugin-vscode-uri");
37
- const progress_service_1 = require("@theia/core/lib/common/progress-service");
38
- const endpoint_1 = require("@theia/core/lib/browser/endpoint");
39
- const vsx_environment_1 = require("../common/vsx-environment");
40
- const vsx_extensions_search_model_1 = require("./vsx-extensions-search-model");
41
- const common_1 = require("@theia/core/lib/common");
42
- const browser_1 = require("@theia/core/lib/browser");
43
- const window_service_1 = require("@theia/core/lib/browser/window/window-service");
44
- const markdown_rendering_1 = require("@theia/core/lib/common/markdown-rendering");
45
- exports.EXTENSIONS_CONTEXT_MENU = ['extensions_context_menu'];
46
- var VSXExtensionsContextMenu;
47
- (function (VSXExtensionsContextMenu) {
48
- VSXExtensionsContextMenu.INSTALL = [...exports.EXTENSIONS_CONTEXT_MENU, '1_install'];
49
- VSXExtensionsContextMenu.COPY = [...exports.EXTENSIONS_CONTEXT_MENU, '2_copy'];
50
- })(VSXExtensionsContextMenu = exports.VSXExtensionsContextMenu || (exports.VSXExtensionsContextMenu = {}));
51
- let VSXExtensionData = class VSXExtensionData {
52
- };
53
- VSXExtensionData.KEYS = new Set([
54
- 'version',
55
- 'iconUrl',
56
- 'publisher',
57
- 'name',
58
- 'displayName',
59
- 'description',
60
- 'averageRating',
61
- 'downloadCount',
62
- 'downloadUrl',
63
- 'readmeUrl',
64
- 'licenseUrl',
65
- 'repository',
66
- 'license',
67
- 'readme',
68
- 'preview',
69
- 'namespaceAccess',
70
- 'publishedBy'
71
- ]);
72
- VSXExtensionData = __decorate([
73
- (0, inversify_1.injectable)()
74
- ], VSXExtensionData);
75
- exports.VSXExtensionData = VSXExtensionData;
76
- let VSXExtensionOptions = class VSXExtensionOptions {
77
- };
78
- VSXExtensionOptions = __decorate([
79
- (0, inversify_1.injectable)()
80
- ], VSXExtensionOptions);
81
- exports.VSXExtensionOptions = VSXExtensionOptions;
82
- exports.VSXExtensionFactory = Symbol('VSXExtensionFactory');
83
- let VSXExtension = VSXExtension_1 = class VSXExtension {
84
- constructor() {
85
- this.data = {};
86
- this._busy = 0;
87
- }
88
- /**
89
- * Ensure the version string begins with `'v'`.
90
- */
91
- static formatVersion(version) {
92
- if (version && !version.startsWith('v')) {
93
- return `v${version}`;
94
- }
95
- return version;
96
- }
97
- postConstruct() {
98
- this.registryUri = this.environment.getRegistryUri();
99
- }
100
- get uri() {
101
- return plugin_vscode_uri_1.VSCodeExtensionUri.toUri(this.id);
102
- }
103
- get id() {
104
- return this.options.id;
105
- }
106
- get visible() {
107
- return !!this.name;
108
- }
109
- get plugin() {
110
- return this.pluginSupport.getPlugin(this.id);
111
- }
112
- get installed() {
113
- return !!this.plugin;
114
- }
115
- get builtin() {
116
- var _a;
117
- return ((_a = this.plugin) === null || _a === void 0 ? void 0 : _a.type) === plugin_protocol_1.PluginType.System;
118
- }
119
- update(data) {
120
- for (const key of VSXExtensionData.KEYS) {
121
- if (key in data) {
122
- Object.assign(this.data, { [key]: data[key] });
123
- }
124
- }
125
- }
126
- reloadWindow() {
127
- this.windowService.reload();
128
- }
129
- getData(key) {
130
- var _a;
131
- const model = (_a = this.plugin) === null || _a === void 0 ? void 0 : _a.metadata.model;
132
- if (model && key in model) {
133
- return model[key];
134
- }
135
- return this.data[key];
136
- }
137
- get iconUrl() {
138
- const plugin = this.plugin;
139
- const iconUrl = plugin && plugin.metadata.model.iconUrl;
140
- if (iconUrl) {
141
- return new endpoint_1.Endpoint({ path: iconUrl }).getRestUrl().toString();
142
- }
143
- return this.data['iconUrl'];
144
- }
145
- get publisher() {
146
- return this.getData('publisher');
147
- }
148
- get name() {
149
- return this.getData('name');
150
- }
151
- get displayName() {
152
- return this.getData('displayName') || this.name;
153
- }
154
- get description() {
155
- return this.getData('description');
156
- }
157
- get version() {
158
- return this.getData('version');
159
- }
160
- get averageRating() {
161
- return this.getData('averageRating');
162
- }
163
- get downloadCount() {
164
- return this.getData('downloadCount');
165
- }
166
- get downloadUrl() {
167
- return this.getData('downloadUrl');
168
- }
169
- get readmeUrl() {
170
- const plugin = this.plugin;
171
- const readmeUrl = plugin && plugin.metadata.model.readmeUrl;
172
- if (readmeUrl) {
173
- return new endpoint_1.Endpoint({ path: readmeUrl }).getRestUrl().toString();
174
- }
175
- return this.data['readmeUrl'];
176
- }
177
- get licenseUrl() {
178
- let licenseUrl = this.data['licenseUrl'];
179
- if (licenseUrl) {
180
- return licenseUrl;
181
- }
182
- else {
183
- const plugin = this.plugin;
184
- licenseUrl = plugin && plugin.metadata.model.licenseUrl;
185
- if (licenseUrl) {
186
- return new endpoint_1.Endpoint({ path: licenseUrl }).getRestUrl().toString();
187
- }
188
- }
189
- }
190
- get repository() {
191
- return this.getData('repository');
192
- }
193
- get license() {
194
- return this.getData('license');
195
- }
196
- get readme() {
197
- return this.getData('readme');
198
- }
199
- get preview() {
200
- return this.getData('preview');
201
- }
202
- get namespaceAccess() {
203
- return this.getData('namespaceAccess');
204
- }
205
- get publishedBy() {
206
- return this.getData('publishedBy');
207
- }
208
- get tooltip() {
209
- let md = `__${this.displayName}__ ${VSXExtension_1.formatVersion(this.version)}\n\n${this.description}\n_____\n\n${common_1.nls.localizeByDefault('Publisher: {0}', this.publisher)}`;
210
- if (this.license) {
211
- md += ` \r${common_1.nls.localize('theia/vsx-registry/license', 'License: {0}', this.license)}`;
212
- }
213
- if (this.downloadCount) {
214
- md += ` \r${common_1.nls.localize('theia/vsx-registry/downloadCount', 'Download count: {0}', downloadCompactFormatter.format(this.downloadCount))}`;
215
- }
216
- if (this.averageRating) {
217
- md += ` \r${getAverageRatingTitle(this.averageRating)}`;
218
- }
219
- return md;
220
- }
221
- get busy() {
222
- return !!this._busy;
223
- }
224
- async install(options) {
225
- var _a;
226
- this._busy++;
227
- try {
228
- await this.progressService.withProgress(common_1.nls.localizeByDefault("Installing extension '{0}' v{1}...", this.id, (_a = this.version) !== null && _a !== void 0 ? _a : 0), 'extensions', () => this.pluginServer.deploy(this.uri.toString(), undefined, options));
229
- }
230
- finally {
231
- this._busy--;
232
- }
233
- }
234
- async uninstall() {
235
- this._busy++;
236
- try {
237
- const { plugin } = this;
238
- if (plugin) {
239
- await this.progressService.withProgress(common_1.nls.localizeByDefault('Uninstalling {0}...', this.id), 'extensions', () => this.pluginServer.uninstall(plugin_protocol_1.PluginIdentifiers.componentsToVersionedId(plugin.metadata.model)));
240
- }
241
- }
242
- finally {
243
- this._busy--;
244
- }
245
- }
246
- handleContextMenu(e) {
247
- e.preventDefault();
248
- this.contextMenuRenderer.render({
249
- menuPath: exports.EXTENSIONS_CONTEXT_MENU,
250
- anchor: {
251
- x: e.clientX,
252
- y: e.clientY,
253
- },
254
- args: [this]
255
- });
256
- }
257
- /**
258
- * Get the registry link for the given extension.
259
- * @param path the url path.
260
- * @returns the registry link for the given extension at the path.
261
- */
262
- async getRegistryLink(path = '') {
263
- const registryUri = new uri_1.default(await this.registryUri);
264
- if (this.downloadUrl) {
265
- const downloadUri = new uri_1.default(this.downloadUrl);
266
- if (downloadUri.authority !== registryUri.authority) {
267
- throw new Error('cannot generate a valid URL');
268
- }
269
- }
270
- return registryUri.resolve('extension/' + this.id.replace('.', '/')).resolve(path);
271
- }
272
- async serialize() {
273
- const serializedExtension = [];
274
- serializedExtension.push(`Name: ${this.displayName}`);
275
- serializedExtension.push(`Id: ${this.id}`);
276
- serializedExtension.push(`Description: ${this.description}`);
277
- serializedExtension.push(`Version: ${this.version}`);
278
- serializedExtension.push(`Publisher: ${this.publisher}`);
279
- if (this.downloadUrl !== undefined) {
280
- const registryLink = await this.getRegistryLink();
281
- serializedExtension.push(`Open VSX Link: ${registryLink.toString()}`);
282
- }
283
- ;
284
- return serializedExtension.join('\n');
285
- }
286
- async open(options = { mode: 'reveal' }) {
287
- await this.doOpen(this.uri, options);
288
- }
289
- async doOpen(uri, options) {
290
- await (0, opener_service_1.open)(this.openerService, uri, options);
291
- }
292
- render(host) {
293
- return React.createElement(VSXExtensionComponent, { extension: this, host: host, hoverService: this.hoverService });
294
- }
295
- };
296
- __decorate([
297
- (0, inversify_1.inject)(VSXExtensionOptions),
298
- __metadata("design:type", VSXExtensionOptions)
299
- ], VSXExtension.prototype, "options", void 0);
300
- __decorate([
301
- (0, inversify_1.inject)(opener_service_1.OpenerService),
302
- __metadata("design:type", Object)
303
- ], VSXExtension.prototype, "openerService", void 0);
304
- __decorate([
305
- (0, inversify_1.inject)(hosted_plugin_1.HostedPluginSupport),
306
- __metadata("design:type", hosted_plugin_1.HostedPluginSupport)
307
- ], VSXExtension.prototype, "pluginSupport", void 0);
308
- __decorate([
309
- (0, inversify_1.inject)(plugin_protocol_1.PluginServer),
310
- __metadata("design:type", Object)
311
- ], VSXExtension.prototype, "pluginServer", void 0);
312
- __decorate([
313
- (0, inversify_1.inject)(progress_service_1.ProgressService),
314
- __metadata("design:type", progress_service_1.ProgressService)
315
- ], VSXExtension.prototype, "progressService", void 0);
316
- __decorate([
317
- (0, inversify_1.inject)(browser_1.ContextMenuRenderer),
318
- __metadata("design:type", browser_1.ContextMenuRenderer)
319
- ], VSXExtension.prototype, "contextMenuRenderer", void 0);
320
- __decorate([
321
- (0, inversify_1.inject)(vsx_environment_1.VSXEnvironment),
322
- __metadata("design:type", Object)
323
- ], VSXExtension.prototype, "environment", void 0);
324
- __decorate([
325
- (0, inversify_1.inject)(vsx_extensions_search_model_1.VSXExtensionsSearchModel),
326
- __metadata("design:type", vsx_extensions_search_model_1.VSXExtensionsSearchModel)
327
- ], VSXExtension.prototype, "search", void 0);
328
- __decorate([
329
- (0, inversify_1.inject)(browser_1.HoverService),
330
- __metadata("design:type", browser_1.HoverService)
331
- ], VSXExtension.prototype, "hoverService", void 0);
332
- __decorate([
333
- (0, inversify_1.inject)(window_service_1.WindowService),
334
- __metadata("design:type", Object)
335
- ], VSXExtension.prototype, "windowService", void 0);
336
- __decorate([
337
- (0, inversify_1.inject)(common_1.CommandRegistry),
338
- __metadata("design:type", common_1.CommandRegistry)
339
- ], VSXExtension.prototype, "commandRegistry", void 0);
340
- __decorate([
341
- (0, inversify_1.postConstruct)(),
342
- __metadata("design:type", Function),
343
- __metadata("design:paramtypes", []),
344
- __metadata("design:returntype", void 0)
345
- ], VSXExtension.prototype, "postConstruct", null);
346
- VSXExtension = VSXExtension_1 = __decorate([
347
- (0, inversify_1.injectable)()
348
- ], VSXExtension);
349
- exports.VSXExtension = VSXExtension;
350
- class AbstractVSXExtensionComponent extends React.Component {
351
- constructor() {
352
- super(...arguments);
353
- this.install = async (event) => {
354
- event === null || event === void 0 ? void 0 : event.stopPropagation();
355
- this.forceUpdate();
356
- try {
357
- const pending = this.props.extension.install();
358
- this.forceUpdate();
359
- await pending;
360
- }
361
- finally {
362
- this.forceUpdate();
363
- }
364
- };
365
- this.uninstall = async (event) => {
366
- event === null || event === void 0 ? void 0 : event.stopPropagation();
367
- try {
368
- const pending = this.props.extension.uninstall();
369
- this.forceUpdate();
370
- await pending;
371
- }
372
- finally {
373
- this.forceUpdate();
374
- }
375
- };
376
- this.reloadWindow = (event) => {
377
- event === null || event === void 0 ? void 0 : event.stopPropagation();
378
- this.props.extension.reloadWindow();
379
- };
380
- this.manage = (e) => {
381
- e.stopPropagation();
382
- this.props.extension.handleContextMenu(e);
383
- };
384
- }
385
- renderAction(host) {
386
- var _a;
387
- const { builtin, busy, plugin } = this.props.extension;
388
- const isFocused = ((_a = host === null || host === void 0 ? void 0 : host.model.getFocusedNode()) === null || _a === void 0 ? void 0 : _a.element) === this.props.extension;
389
- const tabIndex = (!host || isFocused) ? 0 : undefined;
390
- const installed = !!plugin;
391
- const outOfSynch = plugin === null || plugin === void 0 ? void 0 : plugin.metadata.outOfSync;
392
- if (builtin) {
393
- return React.createElement("div", { className: "codicon codicon-settings-gear action", tabIndex: tabIndex, onClick: this.manage });
394
- }
395
- if (busy) {
396
- if (installed) {
397
- return React.createElement("button", { className: "theia-button action theia-mod-disabled" }, common_1.nls.localizeByDefault('Uninstalling'));
398
- }
399
- return React.createElement("button", { className: "theia-button action prominent theia-mod-disabled" }, common_1.nls.localizeByDefault('Installing'));
400
- }
401
- if (installed) {
402
- return React.createElement("div", null,
403
- outOfSynch
404
- ? React.createElement("button", { className: "theia-button action", onClick: this.reloadWindow }, common_1.nls.localizeByDefault('Reload Required'))
405
- : React.createElement("button", { className: "theia-button action", onClick: this.uninstall }, common_1.nls.localizeByDefault('Uninstall')),
406
- React.createElement("div", { className: "codicon codicon-settings-gear action", onClick: this.manage }));
407
- }
408
- return React.createElement("button", { className: "theia-button prominent action", onClick: this.install }, common_1.nls.localizeByDefault('Install'));
409
- }
410
- }
411
- exports.AbstractVSXExtensionComponent = AbstractVSXExtensionComponent;
412
- const downloadFormatter = new Intl.NumberFormat();
413
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
414
- const downloadCompactFormatter = new Intl.NumberFormat('en-US', { notation: 'compact', compactDisplay: 'short' });
415
- const averageRatingFormatter = (averageRating) => Math.round(averageRating * 2) / 2;
416
- const getAverageRatingTitle = (averageRating) => common_1.nls.localizeByDefault('Average rating: {0} out of 5', averageRatingFormatter(averageRating));
417
- class VSXExtensionComponent extends AbstractVSXExtensionComponent {
418
- render() {
419
- const { iconUrl, publisher, displayName, description, version, downloadCount, averageRating, tooltip } = this.props.extension;
420
- return React.createElement("div", { className: 'theia-vsx-extension noselect', onMouseEnter: event => {
421
- this.props.hoverService.requestHover({
422
- content: new markdown_rendering_1.MarkdownStringImpl(tooltip),
423
- target: event.currentTarget,
424
- position: 'right'
425
- });
426
- } },
427
- iconUrl ?
428
- React.createElement("img", { className: 'theia-vsx-extension-icon', src: iconUrl }) :
429
- React.createElement("div", { className: 'theia-vsx-extension-icon placeholder' }),
430
- React.createElement("div", { className: 'theia-vsx-extension-content' },
431
- React.createElement("div", { className: 'title' },
432
- React.createElement("div", { className: 'noWrapInfo' },
433
- React.createElement("span", { className: 'name' }, displayName),
434
- " ",
435
- React.createElement("span", { className: 'version' }, VSXExtension.formatVersion(version))),
436
- React.createElement("div", { className: 'stat' },
437
- !!downloadCount && React.createElement("span", { className: 'download-count' },
438
- React.createElement("i", { className: (0, browser_1.codicon)('cloud-download') }),
439
- downloadCompactFormatter.format(downloadCount)),
440
- !!averageRating && React.createElement("span", { className: 'average-rating' },
441
- React.createElement("i", { className: (0, browser_1.codicon)('star-full') }),
442
- averageRatingFormatter(averageRating)))),
443
- React.createElement("div", { className: 'noWrapInfo theia-vsx-extension-description' }, description),
444
- React.createElement("div", { className: 'theia-vsx-extension-action-bar' },
445
- React.createElement("span", { className: 'noWrapInfo theia-vsx-extension-publisher' }, publisher),
446
- this.renderAction(this.props.host))));
447
- }
448
- }
449
- exports.VSXExtensionComponent = VSXExtensionComponent;
450
- class VSXExtensionEditorComponent extends AbstractVSXExtensionComponent {
451
- constructor() {
452
- super(...arguments);
453
- // TODO replace with webview
454
- this.openLink = (event) => {
455
- if (!this.body) {
456
- return;
457
- }
458
- const target = event.nativeEvent.target;
459
- if (!(target instanceof HTMLElement)) {
460
- return;
461
- }
462
- let node = target;
463
- while (node.tagName.toLowerCase() !== 'a') {
464
- if (node === this.body) {
465
- return;
466
- }
467
- if (!(node.parentElement instanceof HTMLElement)) {
468
- return;
469
- }
470
- node = node.parentElement;
471
- }
472
- const href = node.getAttribute('href');
473
- if (href && !href.startsWith('#')) {
474
- event.preventDefault();
475
- this.props.extension.doOpen(new uri_1.default(href));
476
- }
477
- };
478
- this.openExtension = async (e) => {
479
- e.stopPropagation();
480
- e.preventDefault();
481
- const extension = this.props.extension;
482
- const uri = await extension.getRegistryLink();
483
- extension.doOpen(uri);
484
- };
485
- this.searchPublisher = (e) => {
486
- e.stopPropagation();
487
- e.preventDefault();
488
- const extension = this.props.extension;
489
- if (extension.publisher) {
490
- extension.search.query = extension.publisher;
491
- }
492
- };
493
- this.openPublishedBy = async (e) => {
494
- e.stopPropagation();
495
- e.preventDefault();
496
- const extension = this.props.extension;
497
- const homepage = extension.publishedBy && extension.publishedBy.homepage;
498
- if (homepage) {
499
- extension.doOpen(new uri_1.default(homepage));
500
- }
501
- };
502
- this.openAverageRating = async (e) => {
503
- e.stopPropagation();
504
- e.preventDefault();
505
- const extension = this.props.extension;
506
- const uri = await extension.getRegistryLink('reviews');
507
- extension.doOpen(uri);
508
- };
509
- this.openRepository = (e) => {
510
- e.stopPropagation();
511
- e.preventDefault();
512
- const extension = this.props.extension;
513
- if (extension.repository) {
514
- extension.doOpen(new uri_1.default(extension.repository));
515
- }
516
- };
517
- this.openLicense = (e) => {
518
- e.stopPropagation();
519
- e.preventDefault();
520
- const extension = this.props.extension;
521
- const licenseUrl = extension.licenseUrl;
522
- if (licenseUrl) {
523
- extension.doOpen(new uri_1.default(licenseUrl));
524
- }
525
- };
526
- }
527
- get scrollContainer() {
528
- return this._scrollContainer;
529
- }
530
- render() {
531
- const { builtin, preview, id, iconUrl, publisher, displayName, description, version, averageRating, downloadCount, repository, license, readme } = this.props.extension;
532
- const sanitizedReadme = !!readme ? DOMPurify.sanitize(readme) : undefined;
533
- return React.createElement(React.Fragment, null,
534
- React.createElement("div", { className: 'header', ref: ref => this.header = (ref || undefined) },
535
- iconUrl ?
536
- React.createElement("img", { className: 'icon-container', src: iconUrl }) :
537
- React.createElement("div", { className: 'icon-container placeholder' }),
538
- React.createElement("div", { className: 'details' },
539
- React.createElement("div", { className: 'title' },
540
- React.createElement("span", { title: 'Extension name', className: 'name', onClick: this.openExtension }, displayName),
541
- React.createElement("span", { title: 'Extension identifier', className: 'identifier' }, id),
542
- preview && React.createElement("span", { className: 'preview' }, "Preview"),
543
- builtin && React.createElement("span", { className: 'builtin' }, "Built-in")),
544
- React.createElement("div", { className: 'subtitle' },
545
- React.createElement("span", { title: 'Publisher name', className: 'publisher', onClick: this.searchPublisher },
546
- this.renderNamespaceAccess(),
547
- publisher),
548
- !!downloadCount && React.createElement("span", { className: 'download-count', onClick: this.openExtension },
549
- React.createElement("i", { className: (0, browser_1.codicon)('cloud-download') }),
550
- downloadFormatter.format(downloadCount)),
551
- averageRating !== undefined &&
552
- React.createElement("span", { className: 'average-rating', title: getAverageRatingTitle(averageRating), onClick: this.openAverageRating }, this.renderStars()),
553
- repository && React.createElement("span", { className: 'repository', onClick: this.openRepository }, "Repository"),
554
- license && React.createElement("span", { className: 'license', onClick: this.openLicense }, license),
555
- version && React.createElement("span", { className: 'version' }, VSXExtension.formatVersion(version))),
556
- React.createElement("div", { className: 'description noWrapInfo' }, description),
557
- this.renderAction())),
558
- sanitizedReadme &&
559
- React.createElement("div", { className: 'scroll-container', ref: ref => this._scrollContainer = (ref || undefined) },
560
- React.createElement("div", { className: 'body', ref: ref => this.body = (ref || undefined), onClick: this.openLink,
561
- // eslint-disable-next-line react/no-danger
562
- dangerouslySetInnerHTML: { __html: sanitizedReadme } })));
563
- }
564
- renderNamespaceAccess() {
565
- const { publisher, namespaceAccess, publishedBy } = this.props.extension;
566
- if (namespaceAccess === undefined) {
567
- return undefined;
568
- }
569
- let tooltip = publishedBy ? ` Published by "${publishedBy.loginName}".` : '';
570
- let icon;
571
- if (namespaceAccess === 'public') {
572
- icon = 'globe';
573
- tooltip = `Everyone can publish to "${publisher}" namespace.` + tooltip;
574
- }
575
- else {
576
- icon = 'shield';
577
- tooltip = `Only verified owners can publish to "${publisher}" namespace.` + tooltip;
578
- }
579
- return React.createElement("i", { className: `${(0, browser_1.codicon)(icon)} namespace-access`, title: tooltip, onClick: this.openPublishedBy });
580
- }
581
- renderStars() {
582
- const rating = this.props.extension.averageRating || 0;
583
- const renderStarAt = (position) => position <= rating ?
584
- React.createElement("i", { className: (0, browser_1.codicon)('star-full') }) :
585
- position > rating && position - rating < 1 ?
586
- React.createElement("i", { className: (0, browser_1.codicon)('star-half') }) :
587
- React.createElement("i", { className: (0, browser_1.codicon)('star-empty') });
588
- return React.createElement(React.Fragment, null,
589
- renderStarAt(1),
590
- renderStarAt(2),
591
- renderStarAt(3),
592
- renderStarAt(4),
593
- renderStarAt(5));
594
- }
595
- }
596
- exports.VSXExtensionEditorComponent = VSXExtensionEditorComponent;
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2020 TypeFox and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
23
+ var __metadata = (this && this.__metadata) || function (k, v) {
24
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
+ };
26
+ var VSXExtension_1;
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.VSXExtensionEditorComponent = exports.VSXExtensionComponent = exports.AbstractVSXExtensionComponent = exports.VSXExtension = exports.VSXExtensionFactory = exports.VSXExtensionOptions = exports.VSXExtensionData = exports.VSXExtensionsContextMenu = exports.EXTENSIONS_CONTEXT_MENU = void 0;
29
+ const React = require("@theia/core/shared/react");
30
+ const DOMPurify = require("@theia/core/shared/dompurify");
31
+ const inversify_1 = require("@theia/core/shared/inversify");
32
+ const uri_1 = require("@theia/core/lib/common/uri");
33
+ const opener_service_1 = require("@theia/core/lib/browser/opener-service");
34
+ const hosted_plugin_1 = require("@theia/plugin-ext/lib/hosted/browser/hosted-plugin");
35
+ const plugin_protocol_1 = require("@theia/plugin-ext/lib/common/plugin-protocol");
36
+ const plugin_vscode_uri_1 = require("@theia/plugin-ext-vscode/lib/common/plugin-vscode-uri");
37
+ const progress_service_1 = require("@theia/core/lib/common/progress-service");
38
+ const endpoint_1 = require("@theia/core/lib/browser/endpoint");
39
+ const vsx_environment_1 = require("../common/vsx-environment");
40
+ const vsx_extensions_search_model_1 = require("./vsx-extensions-search-model");
41
+ const common_1 = require("@theia/core/lib/common");
42
+ const browser_1 = require("@theia/core/lib/browser");
43
+ const window_service_1 = require("@theia/core/lib/browser/window/window-service");
44
+ const markdown_rendering_1 = require("@theia/core/lib/common/markdown-rendering");
45
+ exports.EXTENSIONS_CONTEXT_MENU = ['extensions_context_menu'];
46
+ var VSXExtensionsContextMenu;
47
+ (function (VSXExtensionsContextMenu) {
48
+ VSXExtensionsContextMenu.INSTALL = [...exports.EXTENSIONS_CONTEXT_MENU, '1_install'];
49
+ VSXExtensionsContextMenu.COPY = [...exports.EXTENSIONS_CONTEXT_MENU, '2_copy'];
50
+ })(VSXExtensionsContextMenu = exports.VSXExtensionsContextMenu || (exports.VSXExtensionsContextMenu = {}));
51
+ let VSXExtensionData = class VSXExtensionData {
52
+ };
53
+ VSXExtensionData.KEYS = new Set([
54
+ 'version',
55
+ 'iconUrl',
56
+ 'publisher',
57
+ 'name',
58
+ 'displayName',
59
+ 'description',
60
+ 'averageRating',
61
+ 'downloadCount',
62
+ 'downloadUrl',
63
+ 'readmeUrl',
64
+ 'licenseUrl',
65
+ 'repository',
66
+ 'license',
67
+ 'readme',
68
+ 'preview',
69
+ 'verified',
70
+ 'namespaceAccess',
71
+ 'publishedBy'
72
+ ]);
73
+ VSXExtensionData = __decorate([
74
+ (0, inversify_1.injectable)()
75
+ ], VSXExtensionData);
76
+ exports.VSXExtensionData = VSXExtensionData;
77
+ let VSXExtensionOptions = class VSXExtensionOptions {
78
+ };
79
+ VSXExtensionOptions = __decorate([
80
+ (0, inversify_1.injectable)()
81
+ ], VSXExtensionOptions);
82
+ exports.VSXExtensionOptions = VSXExtensionOptions;
83
+ exports.VSXExtensionFactory = Symbol('VSXExtensionFactory');
84
+ let VSXExtension = VSXExtension_1 = class VSXExtension {
85
+ constructor() {
86
+ this.data = {};
87
+ this._busy = 0;
88
+ }
89
+ /**
90
+ * Ensure the version string begins with `'v'`.
91
+ */
92
+ static formatVersion(version) {
93
+ if (version && !version.startsWith('v')) {
94
+ return `v${version}`;
95
+ }
96
+ return version;
97
+ }
98
+ postConstruct() {
99
+ this.registryUri = this.environment.getRegistryUri();
100
+ }
101
+ get uri() {
102
+ return plugin_vscode_uri_1.VSCodeExtensionUri.toUri(this.id);
103
+ }
104
+ get id() {
105
+ return this.options.id;
106
+ }
107
+ get visible() {
108
+ return !!this.name;
109
+ }
110
+ get plugin() {
111
+ return this.pluginSupport.getPlugin(this.id);
112
+ }
113
+ get installed() {
114
+ return !!this.plugin;
115
+ }
116
+ get builtin() {
117
+ var _a;
118
+ return ((_a = this.plugin) === null || _a === void 0 ? void 0 : _a.type) === plugin_protocol_1.PluginType.System;
119
+ }
120
+ update(data) {
121
+ for (const key of VSXExtensionData.KEYS) {
122
+ if (key in data) {
123
+ Object.assign(this.data, { [key]: data[key] });
124
+ }
125
+ }
126
+ }
127
+ reloadWindow() {
128
+ this.windowService.reload();
129
+ }
130
+ getData(key) {
131
+ var _a;
132
+ const model = (_a = this.plugin) === null || _a === void 0 ? void 0 : _a.metadata.model;
133
+ if (model && key in model) {
134
+ return model[key];
135
+ }
136
+ return this.data[key];
137
+ }
138
+ get iconUrl() {
139
+ const plugin = this.plugin;
140
+ const iconUrl = plugin && plugin.metadata.model.iconUrl;
141
+ if (iconUrl) {
142
+ return new endpoint_1.Endpoint({ path: iconUrl }).getRestUrl().toString();
143
+ }
144
+ return this.data['iconUrl'];
145
+ }
146
+ get publisher() {
147
+ return this.getData('publisher');
148
+ }
149
+ get name() {
150
+ return this.getData('name');
151
+ }
152
+ get displayName() {
153
+ return this.getData('displayName') || this.name;
154
+ }
155
+ get description() {
156
+ return this.getData('description');
157
+ }
158
+ get version() {
159
+ return this.getData('version');
160
+ }
161
+ get averageRating() {
162
+ return this.getData('averageRating');
163
+ }
164
+ get downloadCount() {
165
+ return this.getData('downloadCount');
166
+ }
167
+ get downloadUrl() {
168
+ return this.getData('downloadUrl');
169
+ }
170
+ get readmeUrl() {
171
+ const plugin = this.plugin;
172
+ const readmeUrl = plugin && plugin.metadata.model.readmeUrl;
173
+ if (readmeUrl) {
174
+ return new endpoint_1.Endpoint({ path: readmeUrl }).getRestUrl().toString();
175
+ }
176
+ return this.data['readmeUrl'];
177
+ }
178
+ get licenseUrl() {
179
+ let licenseUrl = this.data['licenseUrl'];
180
+ if (licenseUrl) {
181
+ return licenseUrl;
182
+ }
183
+ else {
184
+ const plugin = this.plugin;
185
+ licenseUrl = plugin && plugin.metadata.model.licenseUrl;
186
+ if (licenseUrl) {
187
+ return new endpoint_1.Endpoint({ path: licenseUrl }).getRestUrl().toString();
188
+ }
189
+ }
190
+ }
191
+ get repository() {
192
+ return this.getData('repository');
193
+ }
194
+ get license() {
195
+ return this.getData('license');
196
+ }
197
+ get readme() {
198
+ return this.getData('readme');
199
+ }
200
+ get preview() {
201
+ return this.getData('preview');
202
+ }
203
+ get verified() {
204
+ return this.getData('verified');
205
+ }
206
+ get namespaceAccess() {
207
+ return this.getData('namespaceAccess');
208
+ }
209
+ get publishedBy() {
210
+ return this.getData('publishedBy');
211
+ }
212
+ get tooltip() {
213
+ let md = `__${this.displayName}__ ${VSXExtension_1.formatVersion(this.version)}\n\n${this.description}\n_____\n\n${common_1.nls.localizeByDefault('Publisher: {0}', this.publisher)}`;
214
+ if (this.license) {
215
+ md += ` \r${common_1.nls.localize('theia/vsx-registry/license', 'License: {0}', this.license)}`;
216
+ }
217
+ if (this.downloadCount) {
218
+ md += ` \r${common_1.nls.localize('theia/vsx-registry/downloadCount', 'Download count: {0}', downloadCompactFormatter.format(this.downloadCount))}`;
219
+ }
220
+ if (this.averageRating) {
221
+ md += ` \r${getAverageRatingTitle(this.averageRating)}`;
222
+ }
223
+ return md;
224
+ }
225
+ get busy() {
226
+ return !!this._busy;
227
+ }
228
+ async install(options) {
229
+ if (!this.verified) {
230
+ const choice = await new browser_1.ConfirmDialog({
231
+ title: common_1.nls.localize('theia/vsx-registry/confirmDialogTitle', 'Are you sure you want to proceed with the installation ?'),
232
+ msg: common_1.nls.localize('theia/vsx-registry/confirmDialogMessage', 'The extension "{0}" is unverified and might pose a security risk.', this.displayName)
233
+ }).open();
234
+ if (choice) {
235
+ this.doInstall(options);
236
+ }
237
+ }
238
+ else {
239
+ this.doInstall(options);
240
+ }
241
+ }
242
+ async uninstall() {
243
+ this._busy++;
244
+ try {
245
+ const { plugin } = this;
246
+ if (plugin) {
247
+ await this.progressService.withProgress(common_1.nls.localizeByDefault('Uninstalling {0}...', this.id), 'extensions', () => this.pluginServer.uninstall(plugin_protocol_1.PluginIdentifiers.componentsToVersionedId(plugin.metadata.model)));
248
+ }
249
+ }
250
+ finally {
251
+ this._busy--;
252
+ }
253
+ }
254
+ async doInstall(options) {
255
+ var _a;
256
+ this._busy++;
257
+ try {
258
+ await this.progressService.withProgress(common_1.nls.localizeByDefault("Installing extension '{0}' v{1}...", this.id, (_a = this.version) !== null && _a !== void 0 ? _a : 0), 'extensions', () => this.pluginServer.deploy(this.uri.toString(), undefined, options));
259
+ }
260
+ finally {
261
+ this._busy--;
262
+ }
263
+ }
264
+ handleContextMenu(e) {
265
+ e.preventDefault();
266
+ this.contextMenuRenderer.render({
267
+ menuPath: exports.EXTENSIONS_CONTEXT_MENU,
268
+ anchor: {
269
+ x: e.clientX,
270
+ y: e.clientY,
271
+ },
272
+ args: [this]
273
+ });
274
+ }
275
+ /**
276
+ * Get the registry link for the given extension.
277
+ * @param path the url path.
278
+ * @returns the registry link for the given extension at the path.
279
+ */
280
+ async getRegistryLink(path = '') {
281
+ const registryUri = new uri_1.default(await this.registryUri);
282
+ if (this.downloadUrl) {
283
+ const downloadUri = new uri_1.default(this.downloadUrl);
284
+ if (downloadUri.authority !== registryUri.authority) {
285
+ throw new Error('cannot generate a valid URL');
286
+ }
287
+ }
288
+ return registryUri.resolve('extension/' + this.id.replace('.', '/')).resolve(path);
289
+ }
290
+ async serialize() {
291
+ const serializedExtension = [];
292
+ serializedExtension.push(`Name: ${this.displayName}`);
293
+ serializedExtension.push(`Id: ${this.id}`);
294
+ serializedExtension.push(`Description: ${this.description}`);
295
+ serializedExtension.push(`Version: ${this.version}`);
296
+ serializedExtension.push(`Publisher: ${this.publisher}`);
297
+ if (this.downloadUrl !== undefined) {
298
+ const registryLink = await this.getRegistryLink();
299
+ serializedExtension.push(`Open VSX Link: ${registryLink.toString()}`);
300
+ }
301
+ ;
302
+ return serializedExtension.join('\n');
303
+ }
304
+ async open(options = { mode: 'reveal' }) {
305
+ await this.doOpen(this.uri, options);
306
+ }
307
+ async doOpen(uri, options) {
308
+ await (0, opener_service_1.open)(this.openerService, uri, options);
309
+ }
310
+ render(host) {
311
+ return React.createElement(VSXExtensionComponent, { extension: this, host: host, hoverService: this.hoverService });
312
+ }
313
+ };
314
+ __decorate([
315
+ (0, inversify_1.inject)(VSXExtensionOptions),
316
+ __metadata("design:type", VSXExtensionOptions)
317
+ ], VSXExtension.prototype, "options", void 0);
318
+ __decorate([
319
+ (0, inversify_1.inject)(opener_service_1.OpenerService),
320
+ __metadata("design:type", Object)
321
+ ], VSXExtension.prototype, "openerService", void 0);
322
+ __decorate([
323
+ (0, inversify_1.inject)(hosted_plugin_1.HostedPluginSupport),
324
+ __metadata("design:type", hosted_plugin_1.HostedPluginSupport)
325
+ ], VSXExtension.prototype, "pluginSupport", void 0);
326
+ __decorate([
327
+ (0, inversify_1.inject)(plugin_protocol_1.PluginServer),
328
+ __metadata("design:type", Object)
329
+ ], VSXExtension.prototype, "pluginServer", void 0);
330
+ __decorate([
331
+ (0, inversify_1.inject)(progress_service_1.ProgressService),
332
+ __metadata("design:type", progress_service_1.ProgressService)
333
+ ], VSXExtension.prototype, "progressService", void 0);
334
+ __decorate([
335
+ (0, inversify_1.inject)(browser_1.ContextMenuRenderer),
336
+ __metadata("design:type", browser_1.ContextMenuRenderer)
337
+ ], VSXExtension.prototype, "contextMenuRenderer", void 0);
338
+ __decorate([
339
+ (0, inversify_1.inject)(vsx_environment_1.VSXEnvironment),
340
+ __metadata("design:type", Object)
341
+ ], VSXExtension.prototype, "environment", void 0);
342
+ __decorate([
343
+ (0, inversify_1.inject)(vsx_extensions_search_model_1.VSXExtensionsSearchModel),
344
+ __metadata("design:type", vsx_extensions_search_model_1.VSXExtensionsSearchModel)
345
+ ], VSXExtension.prototype, "search", void 0);
346
+ __decorate([
347
+ (0, inversify_1.inject)(browser_1.HoverService),
348
+ __metadata("design:type", browser_1.HoverService)
349
+ ], VSXExtension.prototype, "hoverService", void 0);
350
+ __decorate([
351
+ (0, inversify_1.inject)(window_service_1.WindowService),
352
+ __metadata("design:type", Object)
353
+ ], VSXExtension.prototype, "windowService", void 0);
354
+ __decorate([
355
+ (0, inversify_1.inject)(common_1.CommandRegistry),
356
+ __metadata("design:type", common_1.CommandRegistry)
357
+ ], VSXExtension.prototype, "commandRegistry", void 0);
358
+ __decorate([
359
+ (0, inversify_1.postConstruct)(),
360
+ __metadata("design:type", Function),
361
+ __metadata("design:paramtypes", []),
362
+ __metadata("design:returntype", void 0)
363
+ ], VSXExtension.prototype, "postConstruct", null);
364
+ VSXExtension = VSXExtension_1 = __decorate([
365
+ (0, inversify_1.injectable)()
366
+ ], VSXExtension);
367
+ exports.VSXExtension = VSXExtension;
368
+ class AbstractVSXExtensionComponent extends React.Component {
369
+ constructor() {
370
+ super(...arguments);
371
+ this.install = async (event) => {
372
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
373
+ this.forceUpdate();
374
+ try {
375
+ const pending = this.props.extension.install();
376
+ this.forceUpdate();
377
+ await pending;
378
+ }
379
+ finally {
380
+ this.forceUpdate();
381
+ }
382
+ };
383
+ this.uninstall = async (event) => {
384
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
385
+ try {
386
+ const pending = this.props.extension.uninstall();
387
+ this.forceUpdate();
388
+ await pending;
389
+ }
390
+ finally {
391
+ this.forceUpdate();
392
+ }
393
+ };
394
+ this.reloadWindow = (event) => {
395
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
396
+ this.props.extension.reloadWindow();
397
+ };
398
+ this.manage = (e) => {
399
+ e.stopPropagation();
400
+ this.props.extension.handleContextMenu(e);
401
+ };
402
+ }
403
+ renderAction(host) {
404
+ var _a;
405
+ const { builtin, busy, plugin } = this.props.extension;
406
+ const isFocused = ((_a = host === null || host === void 0 ? void 0 : host.model.getFocusedNode()) === null || _a === void 0 ? void 0 : _a.element) === this.props.extension;
407
+ const tabIndex = (!host || isFocused) ? 0 : undefined;
408
+ const installed = !!plugin;
409
+ const outOfSynch = plugin === null || plugin === void 0 ? void 0 : plugin.metadata.outOfSync;
410
+ if (builtin) {
411
+ return React.createElement("div", { className: "codicon codicon-settings-gear action", tabIndex: tabIndex, onClick: this.manage });
412
+ }
413
+ if (busy) {
414
+ if (installed) {
415
+ return React.createElement("button", { className: "theia-button action theia-mod-disabled" }, common_1.nls.localizeByDefault('Uninstalling'));
416
+ }
417
+ return React.createElement("button", { className: "theia-button action prominent theia-mod-disabled" }, common_1.nls.localizeByDefault('Installing'));
418
+ }
419
+ if (installed) {
420
+ return React.createElement("div", null,
421
+ outOfSynch
422
+ ? React.createElement("button", { className: "theia-button action", onClick: this.reloadWindow }, common_1.nls.localizeByDefault('Reload Required'))
423
+ : React.createElement("button", { className: "theia-button action", onClick: this.uninstall }, common_1.nls.localizeByDefault('Uninstall')),
424
+ React.createElement("div", { className: "codicon codicon-settings-gear action", onClick: this.manage }));
425
+ }
426
+ return React.createElement("button", { className: "theia-button prominent action", onClick: this.install }, common_1.nls.localizeByDefault('Install'));
427
+ }
428
+ }
429
+ exports.AbstractVSXExtensionComponent = AbstractVSXExtensionComponent;
430
+ const downloadFormatter = new Intl.NumberFormat();
431
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
432
+ const downloadCompactFormatter = new Intl.NumberFormat('en-US', { notation: 'compact', compactDisplay: 'short' });
433
+ const averageRatingFormatter = (averageRating) => Math.round(averageRating * 2) / 2;
434
+ const getAverageRatingTitle = (averageRating) => common_1.nls.localizeByDefault('Average rating: {0} out of 5', averageRatingFormatter(averageRating));
435
+ class VSXExtensionComponent extends AbstractVSXExtensionComponent {
436
+ render() {
437
+ const { iconUrl, publisher, displayName, description, version, downloadCount, averageRating, tooltip, verified } = this.props.extension;
438
+ return React.createElement("div", { className: 'theia-vsx-extension noselect', onMouseEnter: event => {
439
+ this.props.hoverService.requestHover({
440
+ content: new markdown_rendering_1.MarkdownStringImpl(tooltip),
441
+ target: event.currentTarget,
442
+ position: 'right'
443
+ });
444
+ } },
445
+ iconUrl ?
446
+ React.createElement("img", { className: 'theia-vsx-extension-icon', src: iconUrl }) :
447
+ React.createElement("div", { className: 'theia-vsx-extension-icon placeholder' }),
448
+ React.createElement("div", { className: 'theia-vsx-extension-content' },
449
+ React.createElement("div", { className: 'title' },
450
+ React.createElement("div", { className: 'noWrapInfo' },
451
+ React.createElement("span", { className: 'name' }, displayName),
452
+ " ",
453
+ React.createElement("span", { className: 'version' }, VSXExtension.formatVersion(version))),
454
+ React.createElement("div", { className: 'stat' },
455
+ !!downloadCount && React.createElement("span", { className: 'download-count' },
456
+ React.createElement("i", { className: (0, browser_1.codicon)('cloud-download') }),
457
+ downloadCompactFormatter.format(downloadCount)),
458
+ !!averageRating && React.createElement("span", { className: 'average-rating' },
459
+ React.createElement("i", { className: (0, browser_1.codicon)('star-full') }),
460
+ averageRatingFormatter(averageRating)))),
461
+ React.createElement("div", { className: 'noWrapInfo theia-vsx-extension-description' }, description),
462
+ React.createElement("div", { className: 'theia-vsx-extension-action-bar' },
463
+ React.createElement("div", { className: 'theia-vsx-extension-publisher-container' },
464
+ verified === true ? (React.createElement("i", { className: (0, browser_1.codicon)('verified-filled') })) : verified === false ? (React.createElement("i", { className: (0, browser_1.codicon)('verified') })) : (React.createElement("i", { className: (0, browser_1.codicon)('question') })),
465
+ React.createElement("span", { className: 'noWrapInfo theia-vsx-extension-publisher' }, publisher)),
466
+ this.renderAction(this.props.host))));
467
+ }
468
+ }
469
+ exports.VSXExtensionComponent = VSXExtensionComponent;
470
+ class VSXExtensionEditorComponent extends AbstractVSXExtensionComponent {
471
+ constructor() {
472
+ super(...arguments);
473
+ // TODO replace with webview
474
+ this.openLink = (event) => {
475
+ if (!this.body) {
476
+ return;
477
+ }
478
+ const target = event.nativeEvent.target;
479
+ if (!(target instanceof HTMLElement)) {
480
+ return;
481
+ }
482
+ let node = target;
483
+ while (node.tagName.toLowerCase() !== 'a') {
484
+ if (node === this.body) {
485
+ return;
486
+ }
487
+ if (!(node.parentElement instanceof HTMLElement)) {
488
+ return;
489
+ }
490
+ node = node.parentElement;
491
+ }
492
+ const href = node.getAttribute('href');
493
+ if (href && !href.startsWith('#')) {
494
+ event.preventDefault();
495
+ this.props.extension.doOpen(new uri_1.default(href));
496
+ }
497
+ };
498
+ this.openExtension = async (e) => {
499
+ e.stopPropagation();
500
+ e.preventDefault();
501
+ const extension = this.props.extension;
502
+ const uri = await extension.getRegistryLink();
503
+ extension.doOpen(uri);
504
+ };
505
+ this.searchPublisher = (e) => {
506
+ e.stopPropagation();
507
+ e.preventDefault();
508
+ const extension = this.props.extension;
509
+ if (extension.publisher) {
510
+ extension.search.query = extension.publisher;
511
+ }
512
+ };
513
+ this.openPublishedBy = async (e) => {
514
+ e.stopPropagation();
515
+ e.preventDefault();
516
+ const extension = this.props.extension;
517
+ const homepage = extension.publishedBy && extension.publishedBy.homepage;
518
+ if (homepage) {
519
+ extension.doOpen(new uri_1.default(homepage));
520
+ }
521
+ };
522
+ this.openAverageRating = async (e) => {
523
+ e.stopPropagation();
524
+ e.preventDefault();
525
+ const extension = this.props.extension;
526
+ const uri = await extension.getRegistryLink('reviews');
527
+ extension.doOpen(uri);
528
+ };
529
+ this.openRepository = (e) => {
530
+ e.stopPropagation();
531
+ e.preventDefault();
532
+ const extension = this.props.extension;
533
+ if (extension.repository) {
534
+ extension.doOpen(new uri_1.default(extension.repository));
535
+ }
536
+ };
537
+ this.openLicense = (e) => {
538
+ e.stopPropagation();
539
+ e.preventDefault();
540
+ const extension = this.props.extension;
541
+ const licenseUrl = extension.licenseUrl;
542
+ if (licenseUrl) {
543
+ extension.doOpen(new uri_1.default(licenseUrl));
544
+ }
545
+ };
546
+ }
547
+ get scrollContainer() {
548
+ return this._scrollContainer;
549
+ }
550
+ render() {
551
+ const { builtin, preview, id, iconUrl, publisher, displayName, description, version, averageRating, downloadCount, repository, license, readme } = this.props.extension;
552
+ const sanitizedReadme = !!readme ? DOMPurify.sanitize(readme) : undefined;
553
+ return React.createElement(React.Fragment, null,
554
+ React.createElement("div", { className: 'header', ref: ref => this.header = (ref || undefined) },
555
+ iconUrl ?
556
+ React.createElement("img", { className: 'icon-container', src: iconUrl }) :
557
+ React.createElement("div", { className: 'icon-container placeholder' }),
558
+ React.createElement("div", { className: 'details' },
559
+ React.createElement("div", { className: 'title' },
560
+ React.createElement("span", { title: 'Extension name', className: 'name', onClick: this.openExtension }, displayName),
561
+ React.createElement("span", { title: 'Extension identifier', className: 'identifier' }, id),
562
+ preview && React.createElement("span", { className: 'preview' }, "Preview"),
563
+ builtin && React.createElement("span", { className: 'builtin' }, "Built-in")),
564
+ React.createElement("div", { className: 'subtitle' },
565
+ React.createElement("span", { title: 'Publisher name', className: 'publisher', onClick: this.searchPublisher },
566
+ this.renderNamespaceAccess(),
567
+ publisher),
568
+ !!downloadCount && React.createElement("span", { className: 'download-count', onClick: this.openExtension },
569
+ React.createElement("i", { className: (0, browser_1.codicon)('cloud-download') }),
570
+ downloadFormatter.format(downloadCount)),
571
+ averageRating !== undefined &&
572
+ React.createElement("span", { className: 'average-rating', title: getAverageRatingTitle(averageRating), onClick: this.openAverageRating }, this.renderStars()),
573
+ repository && React.createElement("span", { className: 'repository', onClick: this.openRepository }, "Repository"),
574
+ license && React.createElement("span", { className: 'license', onClick: this.openLicense }, license),
575
+ version && React.createElement("span", { className: 'version' }, VSXExtension.formatVersion(version))),
576
+ React.createElement("div", { className: 'description noWrapInfo' }, description),
577
+ this.renderAction())),
578
+ sanitizedReadme &&
579
+ React.createElement("div", { className: 'scroll-container', ref: ref => this._scrollContainer = (ref || undefined) },
580
+ React.createElement("div", { className: 'body', ref: ref => this.body = (ref || undefined), onClick: this.openLink,
581
+ // eslint-disable-next-line react/no-danger
582
+ dangerouslySetInnerHTML: { __html: sanitizedReadme } })));
583
+ }
584
+ renderNamespaceAccess() {
585
+ const { publisher, namespaceAccess, publishedBy } = this.props.extension;
586
+ if (namespaceAccess === undefined) {
587
+ return undefined;
588
+ }
589
+ let tooltip = publishedBy ? ` Published by "${publishedBy.loginName}".` : '';
590
+ let icon;
591
+ if (namespaceAccess === 'public') {
592
+ icon = 'globe';
593
+ tooltip = `Everyone can publish to "${publisher}" namespace.` + tooltip;
594
+ }
595
+ else {
596
+ icon = 'shield';
597
+ tooltip = `Only verified owners can publish to "${publisher}" namespace.` + tooltip;
598
+ }
599
+ return React.createElement("i", { className: `${(0, browser_1.codicon)(icon)} namespace-access`, title: tooltip, onClick: this.openPublishedBy });
600
+ }
601
+ renderStars() {
602
+ const rating = this.props.extension.averageRating || 0;
603
+ const renderStarAt = (position) => position <= rating ?
604
+ React.createElement("i", { className: (0, browser_1.codicon)('star-full') }) :
605
+ position > rating && position - rating < 1 ?
606
+ React.createElement("i", { className: (0, browser_1.codicon)('star-half') }) :
607
+ React.createElement("i", { className: (0, browser_1.codicon)('star-empty') });
608
+ return React.createElement(React.Fragment, null,
609
+ renderStarAt(1),
610
+ renderStarAt(2),
611
+ renderStarAt(3),
612
+ renderStarAt(4),
613
+ renderStarAt(5));
614
+ }
615
+ }
616
+ exports.VSXExtensionEditorComponent = VSXExtensionEditorComponent;
597
617
  //# sourceMappingURL=vsx-extension.js.map