The attribute plugin is not available, 2fa disabled

Control VSIX erstellen

Anleitung zur Erstellung einer VSIX Extension für ein WvdS Control.

Übersicht

Jedes WvdS Control wird als eigenständige VSIX Extension verteilt:

wvds-vscode-ui-{control}-0.1.0.vsix
├── package.json           # Extension Manifest
├── dist/
│   └── extension_main.js  # Kompilierter Code
├── images/
│   └── icon.png           # Extension Icon
└── pas/
    └── extension_main.pas # Pascal-Quellcode

Verzeichnisstruktur

sources/extensions/wvds.vscode.ui.controls/
├── {category}/
│   └── wvds.vscode.ui.{control}/
│       ├── package.json
│       ├── build.cfg
│       ├── pas/
│       │   └── extension_main.pas
│       └── dist/              # Build-Output
│           └── extension_main.js

Schritt 1: Verzeichnis erstellen

$ControlName = "mycontrol"
$Category = "editors"
$BasePath = "sources/extensions/wvds.vscode.ui.controls"
 
New-Item -ItemType Directory -Path "$BasePath/$Category/wvds.vscode.ui.$ControlName/pas" -Force

Schritt 2: package.json

{
  "name": "wvds-vscode-ui-mycontrol",
  "displayName": "WvdS UI: MyControl",
  "description": "MyControl component for WvdS UI Framework",
  "version": "0.1.0",
  "publisher": "ArmandoFilho",
  "icon": "images/icon.png",
  "engines": {
    "vscode": "^1.85.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "onLanguage:pxaml"
  ],
  "main": "./dist/extension_main.js",
  "contributes": {
    "snippets": [
      {
        "language": "pxaml",
        "path": "./snippets/mycontrol.json"
      }
    ]
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/ArmandoFilho/WvdS.FPC"
  },
  "license": "MIT"
}

Schritt 3: extension_main.pas

library extension_main;
 
{$mode objfpc}
{$modeswitch externalclass}
 
uses
  JS, Web,
  VSCode.Base, VSCode.Commands, VSCode.Window;
 
type
  TExtension = class
  public
    class procedure Activate(AContext: TVSCodeExtensionContext);
    class procedure Deactivate;
  end;
 
class procedure TExtension.Activate(AContext: TVSCodeExtensionContext);
var
  Disposable: TVSCodeDisposable;
begin
  (* Register snippet provider *)
  Disposable := TVSCodeCommands.RegisterCommand(
    'wvds.ui.mycontrol.insert',
    @InsertSnippet
  );
  AContext.Subscriptions.Push(Disposable);
end;
 
class procedure TExtension.Deactivate;
begin
  (* Cleanup *)
end;
 
procedure InsertSnippet;
begin
  asm
    const snippet = '<MyControl Name="myControl1" />';
    vscode.window.activeTextEditor?.insertSnippet(
      new vscode.SnippetString(snippet)
    );
  end;
end;
 
exports
  Activate,
  Deactivate;
 
begin
end.

Schritt 4: build.cfg

-Mobjfpc
-Tnodejs
-O-
-Jc
-Jirtl.js
-Fu../../../common
-FUpas
-FEdist
-odist/extension_main.js

Schritt 5: Kompilieren

$ExtPath = "sources/extensions/wvds.vscode.ui.controls/editors/wvds.vscode.ui.mycontrol"
 
# Kompilieren mit pas2js
pas2js @"$ExtPath/build.cfg" "$ExtPath/pas/extension_main.pas"

Schritt 6: VSIX packen

cd $ExtPath
 
# Icon kopieren (falls nicht vorhanden)
if (-not (Test-Path "images")) {
    New-Item -ItemType Directory -Path "images" -Force
    Copy-Item "%MEDIA%/wvds_fpc.png" "images/icon.png"
}
 
# VSIX erstellen
vsce package --no-dependencies
 
# Nach dist verschieben
Move-Item "*.vsix" "%BINARIES%/dist/"

Snippet-Definition

Erstelle snippets/mycontrol.json:

{
  "WvdS MyControl": {
    "prefix": "wvds-mycontrol",
    "body": [
      "<MyControl",
      "    Name=\"${1:myControl1}\"",
      "    ${2:Property}=\"${3:Value}\"",
      "/>"
    ],
    "description": "Insert WvdS MyControl"
  }
}

Vollständiges Beispiel

Button Extension

library extension_main;
 
{$mode objfpc}
{$modeswitch externalclass}
 
uses
  JS, Web,
  VSCode.Base, VSCode.Commands, VSCode.Window,
  VSCode.Languages, VSCode.CompletionItem;
 
const
  CONTROL_NAME = 'Button';
  CONTROL_CATEGORY = 'Basic Controls';
  CONTROL_ICON = 'symbol-event';
 
type
  TButtonExtension = class
  public
    class procedure Activate(AContext: TVSCodeExtensionContext);
    class procedure Deactivate;
  private
    class procedure RegisterSnippet(AContext: TVSCodeExtensionContext);
    class procedure RegisterCompletionProvider(AContext: TVSCodeExtensionContext);
  end;
 
class procedure TButtonExtension.Activate(AContext: TVSCodeExtensionContext);
begin
  RegisterSnippet(AContext);
  RegisterCompletionProvider(AContext);
 
  asm
    console.log('WvdS UI: Button extension activated');
  end;
end;
 
class procedure TButtonExtension.Deactivate;
begin
  (* Cleanup *)
end;
 
class procedure TButtonExtension.RegisterSnippet(AContext: TVSCodeExtensionContext);
var
  Cmd: TVSCodeDisposable;
begin
  Cmd := TVSCodeCommands.RegisterCommand(
    'wvds.ui.button.insert',
    procedure
    begin
      asm
        const editor = vscode.window.activeTextEditor;
        if (editor) {
          const snippet = new vscode.SnippetString(
            '<Button\n' +
            '    Name="${1:button1}"\n' +
            '    Caption="${2:Click Me}"\n' +
            '    OnClick="${3:OnButtonClick}"\n' +
            '/>'
          );
          editor.insertSnippet(snippet);
        }
      end;
    end
  );
  AContext.Subscriptions.Push(Cmd);
end;
 
class procedure TButtonExtension.RegisterCompletionProvider(
  AContext: TVSCodeExtensionContext);
begin
  (* PXAML completion provider *)
  asm
    const provider = vscode.languages.registerCompletionItemProvider(
      { language: 'pxaml', scheme: 'file' },
      {
        provideCompletionItems(document, position) {
          const item = new vscode.CompletionItem('Button', vscode.CompletionItemKind.Class);
          item.insertText = new vscode.SnippetString(
            '<Button Name="${1:button1}" Caption="${2:Click Me}" />'
          );
          item.documentation = 'WvdS Button control';
          return [item];
        }
      },
      '<'
    );
    AContext.subscriptions.push(provider);
  end;
end;
 
procedure Activate(AContext: TJSObject);
begin
  TButtonExtension.Activate(TVSCodeExtensionContext(AContext));
end;
 
procedure Deactivate;
begin
  TButtonExtension.Deactivate;
end;
 
exports
  Activate,
  Deactivate;
 
begin
end.

Batch-Generierung

Für mehrere Controls, siehe Control-Generierung.

Troubleshooting

pas2js Fehler

Fehler Lösung
class var nicht unterstützt Unit-Level Variable verwenden
Int64 nicht unterstützt Integer verwenden
Zuletzt geändert: den 29.01.2026 um 15:13