From 7bb2ddcaea5a45f6f5045b2d172f21c073845859 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Fri, 6 Mar 2026 14:04:23 -0500 Subject: [PATCH] VSCodium and Antigravity --- docz/docs/03-demos/32-extensions/05-vscode.md | 268 +++++++++++------- 1 file changed, 167 insertions(+), 101 deletions(-) diff --git a/docz/docs/03-demos/32-extensions/05-vscode.md b/docz/docs/03-demos/32-extensions/05-vscode.md index 9f6b4d3..a24cbb9 100644 --- a/docz/docs/03-demos/32-extensions/05-vscode.md +++ b/docz/docs/03-demos/32-extensions/05-vscode.md @@ -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 - -{`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 { + async openCustomDocument(uri: vscode.Uri): Promise { + return new ExcelDocument(uri); } - - export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider { - // ... - public static register(context: vscode.ExtensionContext): vscode.Disposable { - return vscode.window.registerCustomEditorProvider( - 'excelViewer.spreadsheet', - new ExcelEditorProvider(), - { webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden - ); - } - // ... - }`} - +} +``` ### 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. - -{`export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider { +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 { + // ... + async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise { + // 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 { - 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 { - 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 { - const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel); - const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); - webviewPanel.webview.html = \`\${htmlTable}\`; - } - }`} - +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 { + // ... + async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise { + // ... + // 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 `} -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 { 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 = `${htmlTable}`; + 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. \ No newline at end of file +[^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`](https://code.visualstudio.com/api/references/vscode-api#CustomEditorProvider<T>) 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. \ No newline at end of file