Вебвью
Вебвью отображает ваш собственный HTML/JS-интерфейс внутри Fragmenta — во вкладке панели или в модальном окне. Вебвью, объявленные в contributes.webviews, регистрируются автоматически. Вы также можете создавать вебвью из кода, если нужен динамический контент или обмен сообщениями.
Создание и получение вебвью
createWebview(id: string, options?: ExtensionSdkCreateWebviewOptions): Promise<WebviewHandle>
getWebview(id: string): Promise<WebviewHandle | undefined>
Идентификаторы дополняются идентификатором вашего расширения: глобальный идентификатор вебвью— <extensionId>.<id>. createWebview ничего не открывает — отобразите веб-представление с помощью show() или откройте его в модальном окне.
Повторный вызов createWebview с тем же идентификатором возвращает существующий дескриптор, а новые опции игнорируются. Для идентификатора, объявленного в манифесте, используйте getWebview, при этом вызов createWebview будет отклонён.
getWebview возвращает дескриптор существующего вебвью вашего расширения по его идентификатору — включая вебвью, объявленные в манифесте, — или undefined.
| Опция | Описание |
| --- | --- |
| displayName | Заголовок вкладки. По умолчанию 'Webview'. |
| icon | Имя иконки Lucide для вкладки. |
| html | Начальный контент. |
| options | Настройки песочницы, см. ниже. |
| when | Сейчас ни на что не влияет. |
Настройки песочницы (options):
| Настройка | Описание |
| --- | --- |
| allowScripts | Разрешить скрипты, диалоги и всплывающие окна. Также нужна для acquireSDK(). По умолчанию true. |
| allowForms | Разрешить отправку форм. По умолчанию true. |
| localResourceRoots | Если список не пуст, asWebviewUri отклоняет локальные пути, которые не начинаются с одного из этих корней (сравнение идёт с итоговым абсолютным путём). По умолчанию [] — без ограничений. |
| stylesUrl | URL таблицы стилей, подключаемой в страницу. |
| injectBaseStyles | Базовые стили: html, body и #root на весь размер, цвета фона и текста из темы, моноширинный шрифт. По умолчанию true. |
| enableCommandUris | Сейчас ни на что не влияет. |
| retainContextWhenHidden | Сейчас ни на что не влияет. |
| trustedDomains | Сейчас ни на что не влияет. |
| cspOverride | Сейчас ни на что не влияет. |
ExtensionSdkCreateWebviewOptions
interface ExtensionSdkCreateWebviewOptions {
displayName?: string // по умолчанию 'Webview'
icon?: string // имя иконки Lucide
html?: string
options?: Partial<WebviewOptions>
when?: string // сейчас ни на что не влияет
}
interface WebviewOptions {
readonly allowScripts?: boolean // по умолчанию true
readonly allowForms?: boolean // по умолчанию true
readonly localResourceRoots?: readonly string[] // по умолчанию []
readonly stylesUrl?: string
readonly injectBaseStyles?: boolean // по умолчанию true
readonly enableCommandUris?: boolean // сейчас ни на что не влияет
readonly retainContextWhenHidden?: boolean // сейчас ни на что не влияет
readonly trustedDomains?: readonly string[] // сейчас ни на что не влияет
readonly cspOverride?: string // сейчас ни на что не влияет
}
Дескриптор вебвью
| Опция | Описание |
| --- | --- |
| id | Глобальный id webview, <extensionId>.<id> (используйте его в showModal({ webviewId })). |
| html | Контент, последним заданный через этот handle (для getWebview — контент на момент вызова). |
| setHtml(html) | Заменить контент. Страница перезагружается, её состояние теряется. |
| postMessage(message) | Отправить сериализуемое значение в страницу. Сообщения до загрузки страницы ставятся в очередь. После dispose() ничего не делает. |
| onDidReceiveMessage | Event<unknown> — сообщения, отправленные страницей. |
| onDidContentReady | Срабатывает при каждой загрузке страницы, в том числе после setHtml и reload(). |
| onDidDispose | Вебвью уничтожен. |
| asWebviewUri(localPath) | Превращает путь в URI, доступный вебвью. Относительные пути отсчитываются от папки расширения, пути с / в начале используются как есть, URL со схемой возвращаются без изменений. |
| show(options?) | Открыть вебвью во вкладке панели. |
| focus() | Фокус на странице. Ничего не возвращает. |
| reload() | Перезагрузить страницу. Ничего не возвращает. |
| dispose() | Уничтожить вебвью. |
setHtml, postMessage, asWebviewUri и show возвращают promise, которые отклоняются, если вызов завершается неудачно, — например, если вебвью больше не существует.
Опции show():
| Опция | Описание |
| --- | --- |
| panel | Id целевой панели: sdk.project.panel.left.panelId (или right, bottom) либо ProjectPanelIds.Browser для центральной области. |
| activate | Сделать вкладку активной. По умолчанию true. |
| pinned | Закрепить вкладку. |
WebviewHandle
interface WebviewHandle {
readonly id: string
readonly html: string
readonly onDidReceiveMessage: Event<unknown>
readonly onDidContentReady: Event<void>
readonly onDidDispose: Event<void>
setHtml(html: string): Promise<void>
postMessage(message: unknown): Promise<void>
asWebviewUri(localPath: string): Promise<string>
show(options?: { panel?: PanelId; activate?: boolean; pinned?: boolean }): Promise<void>
focus(): void
reload(): void
dispose(): void
}
Загрузка собранных ресурсов
Соберите ваш интерфейс (например, Vite-сборка внутри расширения) и подключите файлы через asWebviewUri:
const webview = await sdk.window.createWebview('mapper-view', { displayName: 'Mapper' })
const scriptUri = await webview.asWebviewUri('dist/webview/mapper/mapper.js')
const styleUri = await webview.asWebviewUri('dist/webview/mapper/index.css')
await webview.setHtml(`<!doctype html>
<html>
<head><link rel="stylesheet" href="${styleUri}" /></head>
<body>
<div id="root"></div>
<script type="module" src="${scriptUri}"></script>
</body>
</html>`)
webview.onDidReceiveMessage((message) => {
// обработка сообщений из UI
})
await webview.show({ panel: sdk.project.panel.bottom.panelId, activate: true })
Внутри вебвью
Если allowScripts не false, каждая страница получает небольшой API ещё до запуска ваших скриптов:
| Опция | Описание |
| --- | --- |
| window.acquireSDK() | Возвращает { postMessage, onMessage }. |
| postMessage(message) | Отправить сериализуемое значение в расширение (onDidReceiveMessage). Возвращает false, если отправка не удалась. |
| onMessage(callback) | Получать значения, отправленные через webview.postMessage. Возвращает функцию отписки. |
| window.webviewId | Глобальный id webview. |
Сообщения, которые расширение отправило до загрузки страницы, ставятся в очередь и доставляются, когда страница готова.
Активная тема доступна как CSS-переменные --ds-* (например, --ds-color-background, --ds-color-foreground-secondary, --ds-color-border). Они обновляются при смене темы; с injectBaseStyles страница уже использует их для фона, текста и рамок. Нажатия клавиш вне полей ввода передаются в Fragmenta, так что сочетания клавиш приложения работают, пока фокус в webview.
Типы для страницы не поставляются — объявите их сами:
declare function acquireSDK(): {
postMessage(message: unknown): boolean
onMessage(callback: (message: unknown) => void): () => void
}
const api = acquireSDK()
const unsubscribe = api.onMessage((message) => {
// значения из webview.postMessage()
})
api.postMessage({ type: 'ready' })
webview.onDidReceiveMessage((message) => {
if ((message as { type?: string }).type === 'ready') {
webview.postMessage({ type: 'init', items })
}
})
.card {
background: var(--ds-color-background);
color: var(--ds-color-foreground-secondary);
border: 1px solid var(--ds-color-border);
}