@theia/plugin-ext 1.75.0-next.25 → 1.75.0-next.28

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 (73) hide show
  1. package/lib/common/errors.d.ts +1 -14
  2. package/lib/common/errors.d.ts.map +1 -1
  3. package/lib/common/errors.js +3 -16
  4. package/lib/common/errors.js.map +1 -1
  5. package/lib/common/plugin-protocol.d.ts +44 -719
  6. package/lib/common/plugin-protocol.d.ts.map +1 -1
  7. package/lib/common/plugin-protocol.js +11 -34
  8. package/lib/common/plugin-protocol.js.map +1 -1
  9. package/lib/hosted/browser/worker/plugin-manifest-loader.d.ts.map +1 -1
  10. package/lib/hosted/browser/worker/plugin-manifest-loader.js +5 -36
  11. package/lib/hosted/browser/worker/plugin-manifest-loader.js.map +1 -1
  12. package/lib/hosted/browser/worker/worker-main.js +2 -1
  13. package/lib/hosted/browser/worker/worker-main.js.map +1 -1
  14. package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
  15. package/lib/hosted/node/hosted-plugin-localization-service.js +4 -68
  16. package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
  17. package/lib/hosted/node/plugin-host-rpc.d.ts.map +1 -1
  18. package/lib/hosted/node/plugin-host-rpc.js +2 -2
  19. package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
  20. package/lib/hosted/node/plugin-reader.d.ts.map +1 -1
  21. package/lib/hosted/node/plugin-reader.js +4 -3
  22. package/lib/hosted/node/plugin-reader.js.map +1 -1
  23. package/lib/hosted/node/scanners/grammars-reader.d.ts +3 -2
  24. package/lib/hosted/node/scanners/grammars-reader.d.ts.map +1 -1
  25. package/lib/hosted/node/scanners/grammars-reader.js +5 -23
  26. package/lib/hosted/node/scanners/grammars-reader.js.map +1 -1
  27. package/lib/hosted/node/scanners/scanner-theia.d.ts +37 -72
  28. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  29. package/lib/hosted/node/scanners/scanner-theia.js +114 -854
  30. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  31. package/lib/hosted/node/scanners/scanner-theia.spec.js +4 -4
  32. package/lib/hosted/node/scanners/scanner-theia.spec.js.map +1 -1
  33. package/lib/main/browser/plugin-contribution-handler.js +1 -1
  34. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  35. package/lib/main/browser/plugin-icon-service.d.ts.map +1 -1
  36. package/lib/main/browser/plugin-icon-service.js +2 -1
  37. package/lib/main/browser/plugin-icon-service.js.map +1 -1
  38. package/lib/main/browser/plugin-icon-theme-service.d.ts.map +1 -1
  39. package/lib/main/browser/plugin-icon-theme-service.js +2 -1
  40. package/lib/main/browser/plugin-icon-theme-service.js.map +1 -1
  41. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  42. package/lib/main/browser/plugin-shared-style.js +2 -1
  43. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  44. package/package.json +31 -30
  45. package/src/common/errors.ts +1 -25
  46. package/src/common/plugin-protocol.ts +194 -719
  47. package/src/hosted/browser/worker/plugin-manifest-loader.ts +8 -41
  48. package/src/hosted/browser/worker/worker-main.ts +2 -1
  49. package/src/hosted/node/hosted-plugin-localization-service.ts +3 -82
  50. package/src/hosted/node/plugin-host-rpc.ts +3 -3
  51. package/src/hosted/node/plugin-reader.ts +4 -3
  52. package/src/hosted/node/scanners/grammars-reader.ts +14 -23
  53. package/src/hosted/node/scanners/scanner-theia.spec.ts +4 -4
  54. package/src/hosted/node/scanners/scanner-theia.ts +200 -972
  55. package/src/main/browser/plugin-contribution-handler.ts +1 -1
  56. package/src/main/browser/plugin-icon-service.ts +2 -1
  57. package/src/main/browser/plugin-icon-theme-service.ts +2 -1
  58. package/src/main/browser/plugin-shared-style.ts +2 -1
  59. package/lib/hosted/node/plugin-activation-events.d.ts +0 -7
  60. package/lib/hosted/node/plugin-activation-events.d.ts.map +0 -1
  61. package/lib/hosted/node/plugin-activation-events.js +0 -95
  62. package/lib/hosted/node/plugin-activation-events.js.map +0 -1
  63. package/lib/hosted/node/plugin-manifest-loader.d.ts +0 -3
  64. package/lib/hosted/node/plugin-manifest-loader.d.ts.map +0 -1
  65. package/lib/hosted/node/plugin-manifest-loader.js +0 -34
  66. package/lib/hosted/node/plugin-manifest-loader.js.map +0 -1
  67. package/lib/main/node/errors.spec.d.ts +0 -2
  68. package/lib/main/node/errors.spec.d.ts.map +0 -1
  69. package/lib/main/node/errors.spec.js +0 -36
  70. package/lib/main/node/errors.spec.js.map +0 -1
  71. package/src/hosted/node/plugin-activation-events.ts +0 -112
  72. package/src/hosted/node/plugin-manifest-loader.ts +0 -32
  73. package/src/main/node/errors.spec.ts +0 -37
@@ -16,11 +16,11 @@
16
16
 
17
17
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
18
 
19
- import { PluginIdentifiers, PluginModel, PluginPackage } from '../../../common/plugin-protocol';
19
+ import { PluginModel, PluginPackage } from '../../../common/plugin-protocol';
20
20
  import { Endpoint } from '@theia/core/lib/browser/endpoint';
21
21
  import URI from '@theia/core/lib/common/uri';
22
-
23
- const NLS_REGEX = /^%([\w\d.-]+)%$/i;
22
+ import { localizeWithResolver } from '@theia/plugin-utils/lib/common/package-nls';
23
+ import { prepareLoadedManifest } from '@theia/plugin-utils/lib/common/plugin-manifest';
24
24
 
25
25
  function getUri(pluginModel: PluginModel, relativePath: string): URI {
26
26
  const ownURI = new Endpoint().getRestUrl();
@@ -54,23 +54,18 @@ function readContents(uri: string): Promise<string> {
54
54
 
55
55
  async function readPluginJson(pluginModel: PluginModel, relativePath: string): Promise<any> {
56
56
  const content = await readPluginFile(pluginModel, relativePath);
57
- const json = JSON.parse(content) as PluginPackage;
58
- json.publisher ??= PluginIdentifiers.UNPUBLISHED;
59
- return json;
57
+ return JSON.parse(content);
60
58
  }
61
59
 
62
60
  export async function loadManifest(pluginModel: PluginModel): Promise<any> {
63
61
  const [manifest, translations] = await Promise.all([
64
- readPluginJson(pluginModel, 'package.json'),
62
+ readPluginJson(pluginModel, 'package.json').then(raw =>
63
+ prepareLoadedManifest(raw as PluginPackage, { updateActivationEvents: false })
64
+ ),
65
65
  loadTranslations(pluginModel)
66
66
  ]);
67
- // translate vscode builtins, as they are published with a prefix.
68
- const built_prefix = '@theia/vscode-builtin-';
69
- if (manifest && manifest.name && manifest.name.startsWith(built_prefix)) {
70
- manifest.name = manifest.name.substring(built_prefix.length);
71
- }
72
67
  return manifest && translations && Object.keys(translations).length ?
73
- localize(manifest, translations) :
68
+ localizeWithResolver(manifest, key => translations[key]) :
74
69
  manifest;
75
70
  }
76
71
 
@@ -84,31 +79,3 @@ async function loadTranslations(pluginModel: PluginModel): Promise<any> {
84
79
  return {};
85
80
  }
86
81
  }
87
-
88
- function localize(value: any, translations: {
89
- [key: string]: string
90
- }): any {
91
- if (typeof value === 'string') {
92
- const match = NLS_REGEX.exec(value);
93
- return match && translations[match[1]] || value;
94
- }
95
- if (Array.isArray(value)) {
96
- const result = [];
97
- for (const item of value) {
98
- result.push(localize(item, translations));
99
- }
100
- return result;
101
- }
102
- if (value === null) {
103
- return value;
104
- }
105
- if (typeof value === 'object') {
106
- const result: { [key: string]: any } = {};
107
- // eslint-disable-next-line guard-for-in
108
- for (const propertyName in value) {
109
- result[propertyName] = localize(value[propertyName], translations);
110
- }
111
- return result;
112
- }
113
- return value;
114
- }
@@ -35,6 +35,7 @@ import { EnvExtImpl } from '../../../plugin/env';
35
35
  import { DebugExtImpl } from '../../../plugin/debug/debug-ext';
36
36
  import { LocalizationExtImpl } from '../../../plugin/localization-ext';
37
37
  import pluginHostModule from './worker-plugin-module';
38
+ import { PLUGINS_BASE_PATH } from '@theia/plugin-utils/lib/common/constants';
38
39
 
39
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
41
  const ctx = self as any;
@@ -70,7 +71,7 @@ pluginManager.setPluginHost({
70
71
  ctx.frontendModuleName = plugin.lifecycle.frontendModuleName;
71
72
  }
72
73
 
73
- ctx.importScripts('./hostedPlugin/' + getPluginId(plugin.model) + '/' + plugin.pluginPath);
74
+ ctx.importScripts(`./${PLUGINS_BASE_PATH}/` + getPluginId(plugin.model) + '/' + plugin.pluginPath);
74
75
  }
75
76
  }
76
77
 
@@ -22,9 +22,11 @@ import { inject, injectable, named } from '@theia/core/shared/inversify';
22
22
  import { DeployedPlugin, Localization as PluginLocalization, PluginIdentifiers, Translation } from '../../common';
23
23
  import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
24
24
  import { BackendApplicationContribution } from '@theia/core/lib/node';
25
- import { Disposable, DisposableCollection, isObject, MaybePromise, nls, Path, URI, ILogger } from '@theia/core';
25
+ import { Disposable, DisposableCollection, MaybePromise, nls, Path, URI, ILogger } from '@theia/core';
26
26
  import { Deferred } from '@theia/core/lib/common/promise-util';
27
27
  import { LanguagePackBundle, LanguagePackService } from '../../common/language-pack-service';
28
+ import { localizePackage } from '@theia/plugin-utils/lib/common/package-nls';
29
+ import { loadPackageTranslations } from '@theia/plugin-utils/lib/node/package-nls';
28
30
 
29
31
  export interface VSCodeNlsConfig {
30
32
  locale: string
@@ -327,84 +329,3 @@ async function loadTranslations(packagePath: Path, translations: Translation[]):
327
329
  function buildTranslationKey(pluginId: string, scope: string, key: string): string {
328
330
  return `${pluginId}/${Localization.transformKey(scope)}/${key}`;
329
331
  }
330
-
331
- // Localization logic for `package.json` entries
332
- // Extensions can use `package.nls.json` files to store translations for values in their package.json
333
- // This logic has not changed with the introduction of the vscode.l10n API
334
-
335
- interface PackageTranslation {
336
- translation?: Record<string, string>
337
- default?: Record<string, string>
338
- }
339
-
340
- async function loadPackageTranslations(pluginPath: string, locale: string): Promise<PackageTranslation> {
341
- const localizedPluginPath = path.join(pluginPath, `package.nls.${locale}.json`);
342
- try {
343
- const defaultValue = coerceLocalizations(await fs.readJson(path.join(pluginPath, 'package.nls.json')));
344
- if (await fs.pathExists(localizedPluginPath)) {
345
- return {
346
- translation: coerceLocalizations(await fs.readJson(localizedPluginPath)),
347
- default: defaultValue
348
- };
349
- }
350
- return {
351
- default: defaultValue
352
- };
353
- } catch (e) {
354
- if (e.code !== 'ENOENT') {
355
- throw e;
356
- }
357
- return {};
358
- }
359
- }
360
-
361
- interface LocalizeInfo {
362
- message: string
363
- comment?: string
364
- }
365
-
366
- function isLocalizeInfo(obj: unknown): obj is LocalizeInfo {
367
- return isObject(obj) && 'message' in obj || false;
368
- }
369
-
370
- function coerceLocalizations(translations: Record<string, string | LocalizeInfo>): Record<string, string> {
371
- for (const [key, value] of Object.entries(translations)) {
372
- if (isLocalizeInfo(value)) {
373
- translations[key] = value.message;
374
- } else if (typeof value !== 'string') {
375
- // Only strings or LocalizeInfo values are valid
376
- translations[key] = 'INVALID TRANSLATION VALUE';
377
- }
378
- }
379
- return translations as Record<string, string>;
380
- }
381
-
382
- function localizePackage(value: unknown, translations: PackageTranslation, callback: (key: string, defaultValue: string) => string): unknown {
383
- if (typeof value === 'string') {
384
- let result = value;
385
- if (value.length > 2 && value.startsWith('%') && value.endsWith('%')) {
386
- const key = value.slice(1, -1);
387
- if (translations.translation && key in translations.translation) {
388
- result = translations.translation[key];
389
- } else if (translations.default && key in translations.default) {
390
- result = callback(key, translations.default[key]);
391
- }
392
- }
393
- return result;
394
- }
395
- if (Array.isArray(value)) {
396
- const result = [];
397
- for (const item of value) {
398
- result.push(localizePackage(item, translations, callback));
399
- }
400
- return result;
401
- }
402
- if (isObject(value)) {
403
- const result: Record<string, unknown> = {};
404
- for (const [name, item] of Object.entries(value)) {
405
- result[name] = localizePackage(item, translations, callback);
406
- }
407
- return result;
408
- }
409
- return value;
410
- }
@@ -25,7 +25,7 @@ import {
25
25
  MAIN_RPC_CONTEXT, Plugin, PluginAPIFactory, PluginManager,
26
26
  LocalizationExt
27
27
  } from '../../common/plugin-api-rpc';
28
- import { PluginMetadata, PluginModel } from '../../common/plugin-protocol';
28
+ import { PluginMetadata, PluginModel, PluginPackage } from '../../common/plugin-protocol';
29
29
  import { createAPIFactory } from '../../plugin/plugin-context';
30
30
  import { EnvExtImpl } from '../../plugin/env';
31
31
  import { PreferenceRegistryExtImpl } from '../../plugin/preference-registry';
@@ -35,7 +35,7 @@ import { EditorsAndDocumentsExtImpl } from '../../plugin/editors-and-documents';
35
35
  import { WorkspaceExtImpl } from '../../plugin/workspace';
36
36
  import { MessageRegistryExt } from '../../plugin/message-registry';
37
37
  import { ClipboardExt } from '../../plugin/clipboard-ext';
38
- import { loadManifest } from './plugin-manifest-loader';
38
+ import { loadManifest } from '@theia/plugin-utils/lib/node/plugin-manifest';
39
39
  import { KeyValueStorageProxy } from '../../plugin/plugin-storage';
40
40
  import { WebviewsExtImpl } from '../../plugin/webviews';
41
41
  import { TerminalServiceExtImpl } from '../../plugin/terminal-ext';
@@ -214,7 +214,7 @@ export abstract class AbstractPluginHostRPC<PM extends AbstractPluginManagerExtI
214
214
  const pluginModel = plg.model;
215
215
  const pluginLifecycle = plg.lifecycle;
216
216
 
217
- const rawModel = await loadManifest(pluginModel.packagePath);
217
+ const rawModel = await loadManifest<PluginPackage>(pluginModel.packagePath);
218
218
  rawModel.packagePath = pluginModel.packagePath;
219
219
  if (pluginModel.entryPoint!.frontend) {
220
220
  foreign.push({
@@ -23,7 +23,8 @@ import { inject, injectable, optional, multiInject } from '@theia/core/shared/in
23
23
  import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
24
24
  import { PluginMetadata, getPluginId, MetadataProcessor, PluginPackage, PluginContribution } from '../../common/plugin-protocol';
25
25
  import { MetadataScanner } from './metadata-scanner';
26
- import { loadManifest } from './plugin-manifest-loader';
26
+ import { loadManifest } from '@theia/plugin-utils/lib/node/plugin-manifest';
27
+ import { PLUGINS_BASE_PATH } from '@theia/plugin-utils/lib/common/constants';
27
28
 
28
29
  @injectable()
29
30
  export class HostedPluginReader implements BackendApplicationContribution {
@@ -43,7 +44,7 @@ export class HostedPluginReader implements BackendApplicationContribution {
43
44
  protected pluginsIdsFiles: Map<string, string> = new Map();
44
45
 
45
46
  configure(app: express.Application): void {
46
- app.get('/hostedPlugin/:pluginId/:path(*)', async (req, res) => {
47
+ app.get(`/${PLUGINS_BASE_PATH}/:pluginId/:path(*)`, async (req, res) => {
47
48
  const pluginId = req.params.pluginId;
48
49
  const filePath = req.params.path;
49
50
 
@@ -141,7 +142,7 @@ export class HostedPluginReader implements BackendApplicationContribution {
141
142
  return undefined;
142
143
  }
143
144
  const resolvedPluginPath = await realpath(pluginPath);
144
- const manifest = await loadManifest(resolvedPluginPath);
145
+ const manifest = await loadManifest<PluginPackage>(resolvedPluginPath);
145
146
  if (!manifest) {
146
147
  return undefined;
147
148
  }
@@ -16,16 +16,20 @@
16
16
 
17
17
  import { injectable } from '@theia/core/shared/inversify';
18
18
  import { PluginPackageGrammarsContribution, GrammarsContribution } from '../../../common';
19
- import * as path from 'path';
20
- import * as fs from '@theia/core/shared/fs-extra';
19
+ import { readGrammarFromDisk } from '@theia/plugin-utils/lib/node/read-grammars';
20
+ import type { NormalizeContributionsContext } from '@theia/plugin-utils/lib/common/contribution-types';
21
21
 
22
22
  @injectable()
23
23
  export class GrammarsReader {
24
24
 
25
- async readGrammars(rawGrammars: PluginPackageGrammarsContribution[], pluginPath: string): Promise<GrammarsContribution[]> {
25
+ async readGrammars(
26
+ rawGrammars: readonly PluginPackageGrammarsContribution[],
27
+ pluginPath: string,
28
+ log?: Pick<NormalizeContributionsContext, 'onError'>
29
+ ): Promise<GrammarsContribution[]> {
26
30
  const result = new Array<GrammarsContribution>();
27
31
  for (const rawGrammar of rawGrammars) {
28
- const grammar = await this.readGrammar(rawGrammar, pluginPath);
32
+ const grammar = await this.readGrammar(rawGrammar, pluginPath, log);
29
33
  if (grammar) {
30
34
  result.push(grammar);
31
35
  }
@@ -34,24 +38,11 @@ export class GrammarsReader {
34
38
  return result;
35
39
  }
36
40
 
37
- private async readGrammar(rawGrammar: PluginPackageGrammarsContribution, pluginPath: string): Promise<GrammarsContribution | undefined> {
38
- // TODO: validate inputs
39
- let grammar: string | object;
40
-
41
- if (rawGrammar.path.endsWith('json')) {
42
- grammar = await fs.readJSON(path.resolve(pluginPath, rawGrammar.path));
43
- } else {
44
- grammar = await fs.readFile(path.resolve(pluginPath, rawGrammar.path), 'utf8');
45
- }
46
- return {
47
- language: rawGrammar.language,
48
- scope: rawGrammar.scopeName,
49
- format: rawGrammar.path.endsWith('json') ? 'json' : 'plist',
50
- grammar: grammar,
51
- grammarLocation: rawGrammar.path,
52
- injectTo: rawGrammar.injectTo,
53
- embeddedLanguages: rawGrammar.embeddedLanguages,
54
- tokenTypes: rawGrammar.tokenTypes
55
- };
41
+ protected async readGrammar(
42
+ rawGrammar: PluginPackageGrammarsContribution,
43
+ pluginPath: string,
44
+ log?: Pick<NormalizeContributionsContext, 'onError'>
45
+ ): Promise<GrammarsContribution | undefined> {
46
+ return readGrammarFromDisk(rawGrammar, pluginPath, log);
56
47
  }
57
48
  }
@@ -239,7 +239,7 @@ describe('TheiaPluginScanner - readWalkthroughs', () => {
239
239
  steps: [{ id: 's1', title: 'S1', description: 'd1' }]
240
240
  }], 'test-publisher', 'test-plugin', 'images/icon.png');
241
241
 
242
- expect(result![0].pluginIcon).to.equal('hostedPlugin/test_publisher_test_plugin/images%2Ficon.png');
242
+ expect(result![0].pluginIcon).to.equal('hostedPlugin/test_publisher_test_plugin/images/icon.png');
243
243
  });
244
244
 
245
245
  it('should leave the extension icon undefined when the package declares none', () => {
@@ -391,7 +391,7 @@ describe('TheiaPluginScanner - readWalkthroughs', () => {
391
391
  }]);
392
392
 
393
393
  expect(result).to.have.lengthOf(1);
394
- expect(result![0].steps[0].media).to.deep.equal({ image: 'hostedPlugin/test_publisher_test_plugin/media%2Fimage.png' });
394
+ expect(result![0].steps[0].media).to.deep.equal({ image: 'hostedPlugin/test_publisher_test_plugin/media/image.png' });
395
395
  });
396
396
 
397
397
  it('should keep the alt text of svg media', () => {
@@ -408,7 +408,7 @@ describe('TheiaPluginScanner - readWalkthroughs', () => {
408
408
  }]);
409
409
 
410
410
  expect(result![0].steps[0].media).to.deep.equal({
411
- svg: 'hostedPlugin/test_publisher_test_plugin/media%2Ficon.svg',
411
+ svg: 'hostedPlugin/test_publisher_test_plugin/media/icon.svg',
412
412
  altText: 'An icon'
413
413
  });
414
414
  });
@@ -427,6 +427,6 @@ describe('TheiaPluginScanner - readWalkthroughs', () => {
427
427
  }]);
428
428
 
429
429
  expect(result).to.have.lengthOf(1);
430
- expect(result![0].steps[0].media).to.deep.equal({ svg: 'hostedPlugin/test_publisher_test_plugin/media%2Ficon.svg' });
430
+ expect(result![0].steps[0].media).to.deep.equal({ svg: 'hostedPlugin/test_publisher_test_plugin/media/icon.svg' });
431
431
  });
432
432
  });