====== 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 = '';
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": [
""
],
"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(
''
);
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(
''
);
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|Control-Generierung]].
===== Troubleshooting =====
==== pas2js Fehler ====
| Fehler | Lösung |
^ ''class var'' nicht unterstützt | Unit-Level Variable verwenden |
^ ''Int64'' nicht unterstützt | ''Integer'' verwenden |
^ ''//'' in asm-Block | ''/* */'' für JS-Kommentare |
==== VSIX Fehler ====
| Fehler | Lösung |
^ Missing publisher | ''publisher'' in package.json setzen |
^ Icon not found | ''images/icon.png'' erstellen |
^ Invalid main | Pfad in ''main'' prüfen |
===== Siehe auch =====
* [[.:control-generierung|Control-Generierung]]
* [[.:control-architektur|Control-Architektur]]
* [[.:extension-entwicklung|Extension-Entwicklung]]