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

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.
@@ -64,7 +64,11 @@ import {
64
64
  TerminalProfile,
65
65
  PluginIconContribution,
66
66
  PluginEntryPoint,
67
- PluginPackageContribution
67
+ PluginPackageContribution,
68
+ WalkthroughContribution,
69
+ WalkthroughStepContribution,
70
+ PluginPackageWalkthroughStepMedia,
71
+ WalkthroughStepMedia
68
72
  } from '../../../common/plugin-protocol';
69
73
  import { promises as fs, readdirSync } from 'fs';
70
74
  import * as path from 'path';
@@ -557,6 +561,12 @@ export class TheiaPluginScanner extends AbstractPluginScanner {
557
561
  }
558
562
  }
559
563
 
564
+ try {
565
+ contributions.walkthroughs = this.readWalkthroughs(rawPlugin);
566
+ } catch (err) {
567
+ this.logger.error(`Could not read '${rawPlugin.name}' contribution 'walkthroughs'.`, rawPlugin.contributes.walkthroughs, err);
568
+ }
569
+
560
570
  return contributions;
561
571
  }
562
572
 
@@ -593,6 +603,91 @@ export class TheiaPluginScanner extends AbstractPluginScanner {
593
603
  return translation;
594
604
  }
595
605
 
606
+ protected readWalkthroughs(pck: PluginPackage): WalkthroughContribution[] | undefined {
607
+ if (!pck.contributes || !pck.contributes.walkthroughs) {
608
+ return undefined;
609
+ }
610
+ const pluginId = PluginIdentifiers.componentsToUnversionedId({ publisher: pck.publisher, name: pck.name, version: pck.version });
611
+ // `PluginModel` does not carry the extension icon, so it travels with the walkthroughs that show it.
612
+ const pluginIcon = pck.icon ? this.toPluginUrl(pck, pck.icon) : undefined;
613
+ const result: WalkthroughContribution[] = [];
614
+ for (const walkthrough of pck.contributes.walkthroughs) {
615
+ if (typeof walkthrough.id !== 'string' || !walkthrough.id) {
616
+ this.logger.error(`'contributes.walkthroughs.id' of '${pluginId}' must be defined and non-empty`);
617
+ continue;
618
+ }
619
+ if (typeof walkthrough.title !== 'string' || !walkthrough.title) {
620
+ this.logger.error(`'contributes.walkthroughs.title' of '${pluginId}.${walkthrough.id}' must be defined and non-empty`);
621
+ continue;
622
+ }
623
+ if (!Array.isArray(walkthrough.steps)) {
624
+ this.logger.error(`'contributes.walkthroughs.steps' of '${pluginId}.${walkthrough.id}' must be an array`);
625
+ continue;
626
+ }
627
+ const steps: WalkthroughStepContribution[] = [];
628
+ for (const step of walkthrough.steps) {
629
+ if (typeof step.id !== 'string' || !step.id) {
630
+ this.logger.error(`'contributes.walkthroughs.steps.id' of '${pluginId}.${walkthrough.id}' must be defined and non-empty`);
631
+ continue;
632
+ }
633
+ if (typeof step.title !== 'string' || !step.title) {
634
+ this.logger.error(`'contributes.walkthroughs.steps.title' of '${pluginId}.${walkthrough.id}.${step.id}' must be defined and non-empty`);
635
+ continue;
636
+ }
637
+ steps.push({
638
+ id: step.id,
639
+ title: step.title,
640
+ description: step.description || '',
641
+ media: this.resolveWalkthroughMedia(pck, step.media),
642
+ completionEvents: step.completionEvents,
643
+ when: step.when
644
+ });
645
+ }
646
+ result.push({
647
+ id: walkthrough.id,
648
+ title: walkthrough.title,
649
+ description: walkthrough.description || '',
650
+ steps,
651
+ when: walkthrough.when,
652
+ icon: walkthrough.icon,
653
+ pluginId,
654
+ pluginIcon
655
+ });
656
+ }
657
+ return result.length > 0 ? result : undefined;
658
+ }
659
+
660
+ protected resolveWalkthroughMedia(pck: PluginPackage, media?: PluginPackageWalkthroughStepMedia): WalkthroughStepMedia | undefined {
661
+ if (!media) {
662
+ return undefined;
663
+ }
664
+ if ('markdown' in media) {
665
+ return { markdown: this.toPluginUrl(pck, media.markdown) };
666
+ }
667
+ const altText = 'altText' in media ? media.altText as string : undefined;
668
+ if ('svg' in media) {
669
+ return { svg: this.toPluginUrl(pck, media.svg), ...(altText !== undefined && { altText }) };
670
+ }
671
+ if ('image' in media) {
672
+ if (typeof media.image === 'string') {
673
+ return { image: this.toPluginUrl(pck, media.image), ...(altText !== undefined && { altText }) };
674
+ }
675
+ // Only `dark` and `light` are mandatory; the high contrast variants fall back to them.
676
+ const dark = this.toPluginUrl(pck, media.image.dark);
677
+ const light = this.toPluginUrl(pck, media.image.light);
678
+ return {
679
+ image: {
680
+ dark,
681
+ light,
682
+ hc: media.image.hc ? this.toPluginUrl(pck, media.image.hc) : dark,
683
+ hcLight: media.image.hcLight ? this.toPluginUrl(pck, media.image.hcLight) : light
684
+ },
685
+ ...(altText !== undefined && { altText })
686
+ };
687
+ }
688
+ return undefined;
689
+ }
690
+
596
691
  protected readCommand({ command, title, shortTitle, original, category, icon, enablement }: PluginPackageCommand, pck: PluginPackage): PluginCommand {
597
692
  const { themeIcon, iconUrl } = this.transformIconUrl(pck, icon) ?? {};
598
693
  return { command, title, shortTitle, originalTitle: original, category, iconUrl, themeIcon, enablement };