252 lines
7.2 KiB
Markdown
252 lines
7.2 KiB
Markdown
# 03 — VS Code API Integration
|
||
|
||
Маппинг функциональности расширения на конкретные VS Code API.
|
||
|
||
## Contribution Points (package.json)
|
||
|
||
### `contributes.customEditors`
|
||
Открытие `.fig` файлов в VS Code как custom editor.
|
||
|
||
```jsonc
|
||
{
|
||
"customEditors": [{
|
||
"viewType": "openPencil.figEditor",
|
||
"displayName": "OpenPencil Design",
|
||
"selector": [{ "filenamePattern": "*.fig" }],
|
||
"priority": "default"
|
||
}]
|
||
}
|
||
```
|
||
|
||
**API:** `CustomReadonlyEditorProvider` (не `CustomEditorProvider` — .fig файлы не редактируются в VS Code, только просматриваются).
|
||
|
||
Почему `CustomReadonlyEditorProvider`, а не `CustomEditorProvider`:
|
||
- .fig — бинарный формат, VS Code TextDocument не подходит
|
||
- Редактирование .fig требует полный editor (OpenPencil app), не VS Code
|
||
- Readonly избавляет от имплементации save, backup, undo в extension
|
||
|
||
### `contributes.viewsContainers`
|
||
Activity Bar иконка OpenPencil.
|
||
|
||
```jsonc
|
||
{
|
||
"viewsContainers": {
|
||
"activitybar": [{
|
||
"id": "openPencil",
|
||
"title": "OpenPencil",
|
||
"icon": "media/icon.svg"
|
||
}]
|
||
}
|
||
}
|
||
```
|
||
|
||
### `contributes.views`
|
||
Tree views в sidebar.
|
||
|
||
```jsonc
|
||
{
|
||
"views": {
|
||
"openPencil": [
|
||
{ "id": "openPencil.pages", "name": "Pages", "type": "tree" },
|
||
{ "id": "openPencil.components", "name": "Components", "type": "tree" },
|
||
{ "id": "openPencil.preview", "name": "Preview", "type": "webview" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### `contributes.commands`
|
||
|
||
| Command | Title | Когда |
|
||
|---------|-------|-------|
|
||
| `openPencil.openFile` | Open .fig File | Всегда |
|
||
| `openPencil.copyCSS` | Copy CSS | Элемент выбран |
|
||
| `openPencil.copyTailwind` | Copy Tailwind | Элемент выбран |
|
||
| `openPencil.inspectElement` | Inspect Element | Элемент выбран |
|
||
| `openPencil.refreshTokens` | Refresh Design Tokens | .fig файл открыт |
|
||
| `openPencil.openInApp` | Open in OpenPencil | .fig файл открыт |
|
||
|
||
### `contributes.configuration`
|
||
|
||
```jsonc
|
||
{
|
||
"configuration": {
|
||
"title": "OpenPencil",
|
||
"properties": {
|
||
"openPencil.tokenFormat": {
|
||
"type": "string",
|
||
"enum": ["css-custom-properties", "tailwind", "w3c-design-tokens"],
|
||
"default": "css-custom-properties",
|
||
"description": "Output format for design tokens"
|
||
},
|
||
"openPencil.autoDetectFigFiles": {
|
||
"type": "boolean",
|
||
"default": true,
|
||
"description": "Auto-detect .fig files in workspace"
|
||
},
|
||
"openPencil.tokenNamingConvention": {
|
||
"type": "string",
|
||
"enum": ["kebab-case", "camelCase", "snake_case"],
|
||
"default": "kebab-case"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### `contributes.jsonValidation`
|
||
Валидация `.openpencil.json` конфига.
|
||
|
||
```jsonc
|
||
{
|
||
"jsonValidation": [{
|
||
"fileMatch": ".openpencil.json",
|
||
"url": "./schemas/openpencil-config.schema.json"
|
||
}]
|
||
}
|
||
```
|
||
|
||
## Language Feature Providers
|
||
|
||
### `DocumentColorProvider`
|
||
Inline color swatches для дизайн-токенов в CSS/SCSS/Vue/TSX файлах.
|
||
|
||
```typescript
|
||
vscode.languages.registerColorProvider(
|
||
[
|
||
{ language: 'css' },
|
||
{ language: 'scss' },
|
||
{ language: 'vue' },
|
||
{ language: 'typescriptreact' }
|
||
],
|
||
colorProvider
|
||
)
|
||
```
|
||
|
||
Сканирует документ на вхождения CSS custom properties (--op-color-*) или hex-значений, совпадающих с дизайн-токенами. Показывает VS Code color picker с привязкой к token registry.
|
||
|
||
### `CompletionItemProvider`
|
||
Autocomplete для дизайн-токенов.
|
||
|
||
```typescript
|
||
vscode.languages.registerCompletionItemProvider(
|
||
[{ language: 'css' }, { language: 'scss' }, { language: 'vue' }],
|
||
tokenCompletionProvider,
|
||
'-' // trigger на '--'
|
||
)
|
||
```
|
||
|
||
Предлагает `--op-primary-500`, `--op-font-heading`, `--op-spacing-md` и т.д. при наборе CSS custom properties. Каждый CompletionItem содержит:
|
||
- `detail`: hex-значение или размер
|
||
- `documentation`: MarkdownString с preview
|
||
- `kind`: CompletionItemKind.Color / .Value
|
||
|
||
### `HoverProvider`
|
||
Hover на CSS custom property → popup с превью цвета/значения из дизайна.
|
||
|
||
```typescript
|
||
vscode.languages.registerHoverProvider(
|
||
[{ language: 'css' }, { language: 'scss' }, { language: 'vue' }],
|
||
tokenHoverProvider
|
||
)
|
||
```
|
||
|
||
### `CodeLensProvider`
|
||
CodeLens над Vue/React компонентами, связанными с дизайн-компонентами.
|
||
|
||
```typescript
|
||
vscode.languages.registerCodeLensProvider(
|
||
[{ language: 'vue' }, { language: 'typescriptreact' }],
|
||
codeLensProvider
|
||
)
|
||
```
|
||
|
||
Показывает "🎨 View in OpenPencil" над компонентами с аннотацией `@openpencil-component`.
|
||
|
||
## TreeDataProvider
|
||
|
||
### Pages Tree
|
||
Показывает все страницы (CANVAS nodes) из .fig файла:
|
||
```
|
||
📄 Page 1
|
||
📄 Page 2
|
||
📄 Components
|
||
```
|
||
|
||
### Components Tree
|
||
Показывает все COMPONENT и COMPONENT_SET nodes:
|
||
```
|
||
◇ Button
|
||
◇ Button/Primary
|
||
◇ Button/Secondary
|
||
◇ Card
|
||
◇ Input
|
||
```
|
||
|
||
Каждый TreeItem имеет `contextValue` для контекстного меню ("Copy CSS", "Inspect").
|
||
|
||
## WebviewViewProvider
|
||
|
||
### Preview Panel
|
||
Рендерит выбранный элемент дизайна через CanvasKit в webview.
|
||
|
||
CSP для webview (подтверждено на примерах pixcil, crabviz, audio-preview):
|
||
```html
|
||
<meta http-equiv="Content-Security-Policy" content="
|
||
default-src 'none';
|
||
script-src 'nonce-${nonce}' 'wasm-unsafe-eval';
|
||
style-src ${webview.cspSource};
|
||
img-src ${webview.cspSource} blob:;
|
||
connect-src ${webview.cspSource};
|
||
">
|
||
```
|
||
|
||
Ключевое: `'wasm-unsafe-eval'` разрешает загрузку CanvasKit WASM.
|
||
|
||
Communication: extension host ↔ webview через `postMessage` / `onDidReceiveMessage`.
|
||
|
||
## FileSystemWatcher
|
||
|
||
```typescript
|
||
const watcher = vscode.workspace.createFileSystemWatcher('**/*.fig')
|
||
watcher.onDidChange(uri => refreshDesignTokens(uri))
|
||
watcher.onDidCreate(uri => indexFigFile(uri))
|
||
watcher.onDidDelete(uri => removeFromTokenRegistry(uri))
|
||
```
|
||
|
||
## StatusBarItem
|
||
|
||
```typescript
|
||
const statusBar = vscode.window.createStatusBarItem(
|
||
vscode.StatusBarAlignment.Right,
|
||
100
|
||
)
|
||
statusBar.text = '$(paintcan) OpenPencil: 3 files'
|
||
statusBar.command = 'openPencil.showFiles'
|
||
```
|
||
|
||
## Activation Events
|
||
|
||
```jsonc
|
||
{
|
||
"activationEvents": [
|
||
"onCustomEditor:openPencil.figEditor",
|
||
"workspaceContains:**/*.fig"
|
||
]
|
||
}
|
||
```
|
||
|
||
Расширение активируется при:
|
||
1. Открытии .fig файла
|
||
2. Наличии .fig файлов в workspace (для autocomplete и token indexing)
|
||
|
||
## Чего НЕ используем
|
||
|
||
| API | Причина отказа |
|
||
|-----|---------------|
|
||
| `WebviewPanel` (standalone) | Дублирует `CustomReadonlyEditorProvider` для .fig файлов |
|
||
| `CustomEditorProvider` (writable) | .fig не редактируется в VS Code |
|
||
| `CustomTextEditorProvider` | .fig — бинарный формат |
|
||
| `DebugAdapterDescriptorFactory` | Не применимо |
|
||
| `AuthenticationProvider` | Local-first, нет облака |
|