VSCodium and Antigravity

This commit is contained in:
SheetJS 2026-03-06 14:04:23 -05:00
parent a0e35dd7e1
commit 7bb2ddcaea

@ -39,20 +39,31 @@ is available on the SheetJS Git server. Feedback and contributions are welcome!
:::note Tested Deployments
This demo was verified in the following deployments:
This demo was tested in the following deployments:
| Platform | Architecture | Date |
|:-------------------|:-------------|:-----------|
| VSCodium 1.109 | `darwin-arm` | 2026-03-05 |
| VS Code 1.110.0 | `win11-arm` | 2026-03-05 |
| Antigravity 1.19.6 | `linux-arm` | 2026-03-05 |
| Platform | Architecture | Date |
|:--------------------------------------------------|:-------------|:-----------|
| [VSCodium 1.109.51242](https://vscodium.com/) | `darwin-arm` | 2026-03-05 |
| [VS Code 1.110.0](https://code.visualstudio.com/) | `win11-arm` | 2026-03-05 |
| [Antigravity 1.19.6](https://antigravity.google/) | `linux-arm` | 2026-03-05 |
:::
:::danger Telemetry and Data Exfiltration
VSCode and many forks embed telemetry and send code to third-party servers.
For example, Antigravity includes AI features that are powered by Google Gemini
and other cloud AI services. These features necessitate code exfiltration.
**[VSCodium](https://vscodium.com/) does not include AI features or telemetry!**
:::
## Integration Details
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
imported from any component or script in the extension.
imported from any script in the extension.
:::caution pass
@ -89,100 +100,156 @@ yarn add -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
:::
## Extension Architecture
The core extension APIs are available in the `vscode` package. A TypeScript
extension typically uses "glob imports" to load SheetJS and VSCode features:
The VS Code Spreadsheet viewer extension has three main components:
- **Extension Entry Point:** Registers the extension with VS Code
- **Custom Editor Provider:** Handles Excel files and converts them to web content
- **WebView Content:** Displays Excel data as HTML tables
The extension uses VS Code's `Custom Editor API`[^2] to register as a handler for Excel files. When a file is opened,
SheetJS parses it and displays the data in a WebView component.
### Extension Entry Point
The main entry point registers the custom editor provider:
```ts title="src/extension.ts"
```ts title="Importing SheetJS and VSCode features"
import * as vscode from 'vscode';
// highlight-start
import { ExcelEditorProvider } from './excelEditorProvider';
// highlight-end
export function activate(context: vscode.ExtensionContext) {
// SheetJS Spreadsheet Viewer extension activating...
// highlight-start
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
// highlight-end
}
export function deactivate() {}
import * as XLSX from 'xlsx';
```
The `custom editor`[^4] is configured to support specific file types, giving us complete control over how each file is
presented to the user. Additionally, `custom document`[^5] enables us to maintain and persist the state of each individual
file that's opened.
## Extension Architecture
<CodeBlock language="typescript" value="typescript" title="src/excelEditorProvider.ts">
{`import * as vscode from 'vscode';
// highlight-start
import * as XLSX from 'xlsx';
import { ExcelDocument } from './excelDocument';
// highlight-end
VSCode Extensions for processing custom file types use the Custom Editor API[^2]
for lifecycle events. This involves a number of moving parts:
// A simple class to store document state (one per opened file)
class ExcelDocument implements vscode.CustomDocument {
constructor(public readonly uri: vscode.Uri) {}
dispose() {}
1) "Custom Document" for managing file metadata
2) "Custom Editor Provider" for processing file data and generating previews
3) Registration during extension lifecycle events.
4) Advertisement of filetype support in extension metadata.
When a spreadsheet is opened, the extension will use SheetJS methods to parse
the raw file and display the data in a HTML table.
### Custom Documents
Extensions must provide a class that implements `vscode.CustomDocument`[^4].
```ts title="Simple CustomDocument"
class ExcelDocument implements vscode.CustomDocument {
constructor(public readonly uri: vscode.Uri) { }
dispose() { }
}
```
### Editor Provider
Extensions that read data should implement `vscode.CustomReadonlyEditorProvider`
with a generic parameter for the custom document type.
The `openCustomDocument` method takes a `vscode.Uri` and is expected to return a
new document:
```ts title="src/extension.ts (snippet)"
class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
return new ExcelDocument(uri);
}
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
public static register(context: vscode.ExtensionContext): vscode.Disposable {
return vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
new ExcelEditorProvider(),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
}
// ...
}`}
</CodeBlock>
}
```
### Reading Files
The extension reads Excel files using the VS Code filesystem API and passes
the data to SheetJS for parsing:
The `FileSystemProvider` API[^5], available at `vscode.workspace.fs`, exposes
common filesystem operations including reading raw data from files and watching
for changes.
<CodeBlock language="typescript" value="typescript" title="src/excelEditorProvider.ts">
{`export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
The `resolveCustomEditor`[^6] method of the `CustomEditorProvider` will be
called when a file is opened. The first argument is a `CustomDocument` whose
`uri` property points to the location of the file.
`vscode.workspace.fs.readFile`[^5] returns a promise that resolves to a
`Uint8Array` containing the raw binary data. This `Uint8Array` can be passed to
the SheetJS [`read`](/docs/api/parse-options) method:
```ts title="src/extension.ts (snippet)"
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
// read the raw bytes from the file
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
// parse the file data
const wb: XLSX.WorkBook = XLSX.read(data);
// At this point, `wb` is a SheetJS Workbook Object
// ...
private async loadWorkbook(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<XLSX.WorkBook> {
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
}
// ...
}
```
const options: XLSX.ParsingOptions = {
type: 'array',
cellStyles: true,
cellDates: true,
};
### Previewing Data
return XLSX.read(new Uint8Array(data), options); // returns a XLSX.WorkBook
}
The `resolveCustomEditor`[^6] method of the `CustomEditorProvider` will be
called when a file is opened. The second argument is a `WebviewPanel`[^7].
// This is called when the first time an editor for a given resource is opened
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
return new ExcelDocument(uri);
}
The `webview.html` nested property of the `WebviewPanel` controls the displayed
HTML. Extensions can use SheetJS [API methods](/docs/api/).
// This is called whenever the user opens a new editor
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel);
const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
webviewPanel.webview.html = \`<!DOCTYPE html><html><body>\${htmlTable}</body></html>\`;
}
}`}
</CodeBlock>
The SheetJS [`sheet_to_html`](/docs/api/utilities/html#html-table-output) method
generates a simple HTML table. The following snippet displays the data of the
first worksheet:
```ts title="src/extension.ts (snippet)"
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
// ...
// continuing from "Reading Files", `wb` is a SheetJS Workbook Object
const first_sheet = wb.Sheets[wb.SheetNames[0]];
webviewPanel.webview.html = XLSX.utils.sheet_to_html(first_sheet);
}
// ...
}
```
### Registration
The exported `activate` method registers the editor provider. The first argument
to `registerCustomEditorProvider` is expected to be a unique name that will be
referenced later.
```ts title="src/extension.ts (snippet)"
export function activate(context: vscode.ExtensionContext) {
const provider = vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
new ExcelEditorProvider(),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
context.subscriptions.push(provider);
}
```
### Filetype Support
Extensions must announce custom editor file type support in `package.json`.
The `selector` property[^8] is expected to include "Glob Pattterns"[^9].
The demo uses the following `package.json` snippet to announce support for `xls`
and `xlsx` spreadsheets:
```json title="package.json (snippet)"
"contributes": {
"customEditors": [
{
// ... other properties including displayName
// highlight-start
// The viewType must match the first argument of `registerCustomEditorProvider`
"viewType": "excelViewer.spreadsheet",
"selector": [
{ "filenamePattern": "*.xlsx" },
{ "filenamePattern": "*.xls" }
]
// highlight-end
}
],
// ...
},
```
### Usage Flow
@ -247,10 +314,9 @@ pnpm run watch
`}
</CodeBlock>
4) Launch a new editor window using the desired VSCode fork and open the newly
created `sheetjs-demo` folder.
4) Launch a new window with the VSCode fork and open the `sheetjs-demo` folder.
4) Save the following codeblock to `src/extension.ts`:
5) Save the following codeblock to `src/extension.ts`:
```ts title="src/extension.ts (replace contents)"
import * as vscode from 'vscode';
@ -271,15 +337,11 @@ class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDo
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
const options: XLSX.ParsingOptions = {
type: 'array',
cellStyles: true,
cellDates: true,
};
const options: XLSX.ParsingOptions = { cellStyles: true, cellDates: true };
const wb: XLSX.WorkBook = XLSX.read(data, options);
const wb: XLSX.WorkBook = XLSX.read(new Uint8Array(data), options);
const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
webviewPanel.webview.html = `<!DOCTYPE html><html><body>${htmlTable}</body></html>`;
const first_sheet = wb.Sheets[wb.SheetNames[0]];
webviewPanel.webview.html = XLSX.utils.sheet_to_html(first_sheet);
}
}
@ -294,7 +356,7 @@ export function activate(context: vscode.ExtensionContext) {
export function deactivate() {}
```
5) Add the highlighted lines to the `contributes` section of `package.json`:
6) Add the highlighted lines to the `contributes` section of `package.json`:
```json title="package.json (add highlighted lines)"
"contributes": {
@ -319,12 +381,12 @@ export function deactivate() {}
},
```
6) In the editor, open the Command Palette (Help > "Show All Commands" from the
7) In the editor, open the Command Palette (Help > "Show All Commands" from the
menu), type `Debug: Start` and select `Debug: Start Debugging`.
This will compile and run the extension in a new Extension Development Host window.
7) Drag and drop the `pres.xlsx` test file into the new window. If drag and drop
8) Drag and drop the `pres.xlsx` test file into the new window. If drag and drop
is not available, click "Open..." in the Welcome screen and select the file.
A new `pres.xlsx` tab will show the contents of the file.
@ -350,5 +412,9 @@ demo was last tested, it was safe to set a minimum version of `^1.100.0`:
[^1]: See [`Webview API`](https://code.visualstudio.com/api/extension-guides/webview) in the VSCode documentation for more details.
[^2]: See [`Custom Editor API`](https://code.visualstudio.com/api/extension-guides/custom-editors) in the VSCode documentation for more details.
[^3]: See [`vsce`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#vsce) in the VSCode documentation for more details.
[^4]: See [`Custom Editor`](https://code.visualstudio.com/api/extension-guides/custom-editors#custom-editor) in the VSCode documentation for more details.
[^5]: See [`CustomDocument`](https://code.visualstudio.com/api/extension-guides/custom-editors#customdocument) in the VSCode documentation for more details.
[^4]: See [`CustomDocument`](https://code.visualstudio.com/api/references/vscode-api#CustomDocument) in the VSCode API documentation for more details.
[^5]: See [`FileSystemProvider`](https://code.visualstudio.com/api/references/vscode-api#FileSystemProvider) in the VSCode API documentation for more details.
[^6]: See [`CustomEditorProvider<T>`](https://code.visualstudio.com/api/references/vscode-api#CustomEditorProvider&lt;T&gt;) in the VSCode API documentation for more details.
[^7]: See [`WebviewPanel`](https://code.visualstudio.com/api/references/vscode-api#WebviewPanel) in the VSCode API documentation for more details.
[^8]: See [`contributes.customEditors`](https://code.visualstudio.com/api/references/contribution-points#contributes.customEditors) in the VSCode API documentation for more details.
[^9]: See ["Glob Patterns Reference"](https://code.visualstudio.com/docs/editor/glob-patterns) in the VSCode documentation for more details.