Merge pull request #797 from microsoft/roblou/thick-primate

Add notebook serializer sample
This commit is contained in:
Rob Lourens
2023-01-10 17:03:46 -08:00
committed by GitHub
13 changed files with 3729 additions and 0 deletions

View File

@ -0,0 +1,23 @@
/**@type {import('eslint').Linter.Config} */
// eslint-disable-next-line no-undef
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
'semi': [
2,
"always"
],
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-non-null-assertion': 0,
}
};

View File

@ -0,0 +1,5 @@
{
"recommendations": [
"dbaeumer.vscode-eslint"
]
}

View File

@ -0,0 +1,36 @@
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"debugWebviews": true,
"trace": true,
"preLaunchTask": "npm: watch"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
],
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
}
]
}

View File

@ -0,0 +1,6 @@
{
"search.exclude": {
"out": true
},
"typescript.tsc.autoDetect": "off"
}

View File

@ -0,0 +1,26 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "watch",
"problemMatcher": ["$tsc-watch", "$ts-checker-webpack-watch"],
"isBackground": true,
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "npm",
"script": "compile",
"problemMatcher": ["$tsc", "$ts-checker-webpack"],
"group": "build"
}
]
}

View File

@ -0,0 +1,12 @@
.vscode/**
.vscode-test/**
out/test/**
src/**
.gitignore
.yarnrc
vsc-extension-quickstart.md
**/tsconfig.json
**/.eslintrc.json
**/*.map
**/*.ts
**/*.tsbuildinfo

View File

@ -0,0 +1,15 @@
# notebook-serializer-sample
This is a very simple extension sample demonstrating the use of the notebook serializer and controller APIs. This sample includes:
- A notebook serializer that is activated for files matching `*.sample-json-notebook`. It serializes notebook data into a simple JSON-based format.
- A notebook controller that "executes" JSON-type code cells by adding an output to the cell that includes the content of the cell parsed as JSON.
- A command "Create JSON Notebook" that creates a new untitled notebook of this type.
## Running this sample
1. `cd notebook-serializer-sample`
1. `code .`: Open the folder in VS Code
1. Hit `F5` to build+debug
1. Run the command "Create JSON Notebook"
1. Add and edit cells, and click the run button to invoke the controller

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
{
"name": "notebook-serializer-sample",
"displayName": "notebook-serializer-sample",
"description": "Notebook using Serializer API sample",
"publisher": "vscode-samples",
"version": "0.0.1",
"engines": {
"vscode": "^1.74.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onNotebook:test-notebook-serializer",
"onCommand:notebook-serializer-sample.createJsonNotebook"
],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "notebook-serializer-sample.createJsonNotebook",
"title": "Create JSON Notebook"
}
],
"notebooks": [
{
"type": "test-notebook-serializer",
"displayName": "Sample Notebook",
"selector": [
{
"filenamePattern": "*.sample-json-notebook"
}
]
}
]
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -b",
"lint": "eslint src --ext ts",
"watch": "tsc -b --watch"
},
"devDependencies": {
"@types/mocha": "^8.2.2",
"@types/node": "14.x",
"@types/vscode": "^1.74.0",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"eslint": "^7.27.0",
"mocha": "^10.2.0",
"typescript": "^4.3.2"
}
}

View File

@ -0,0 +1,51 @@
import * as vscode from 'vscode';
export class SampleKernel {
private readonly _id = 'test-notebook-serializer-kernel';
private readonly _label = 'Sample Notebook Kernel';
private readonly _supportedLanguages = ['json'];
private _executionOrder = 0;
private readonly _controller: vscode.NotebookController;
constructor() {
this._controller = vscode.notebooks.createNotebookController(this._id,
'test-notebook-serializer',
this._label);
this._controller.supportedLanguages = this._supportedLanguages;
this._controller.supportsExecutionOrder = true;
this._controller.executeHandler = this._executeAll.bind(this);
}
dispose(): void {
this._controller.dispose();
}
private _executeAll(cells: vscode.NotebookCell[], _notebook: vscode.NotebookDocument, _controller: vscode.NotebookController): void {
for (const cell of cells) {
this._doExecution(cell);
}
}
private async _doExecution(cell: vscode.NotebookCell): Promise<void> {
const execution = this._controller.createNotebookCellExecution(cell);
execution.executionOrder = ++this._executionOrder;
execution.start(Date.now());
try {
execution.replaceOutput([new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.json(JSON.parse(cell.document.getText()))
])]);
execution.end(true, Date.now());
} catch (err) {
execution.replaceOutput([new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.error(err as Error)
])]);
execution.end(false, Date.now());
}
}
}

View File

@ -0,0 +1,33 @@
import * as vscode from 'vscode';
import { SampleKernel } from './controller';
import { SampleContentSerializer } from './serializer';
const NOTEBOOK_TYPE = 'test-notebook-serializer';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('notebook-serializer-sample.createJsonNotebook', async () => {
const language = 'json';
const defaultValue = `{ "hello_world": 123 }`;
const cell = new vscode.NotebookCellData(vscode.NotebookCellKind.Code, defaultValue, language);
const data = new vscode.NotebookData([cell]);
data.metadata = {
custom: {
cells: [],
metadata: {
orig_nbformat: 4
},
nbformat: 4,
nbformat_minor: 2
}
};
const doc = await vscode.workspace.openNotebookDocument(NOTEBOOK_TYPE, data);
await vscode.window.showNotebookDocument(doc);
}));
context.subscriptions.push(
vscode.workspace.registerNotebookSerializer(
NOTEBOOK_TYPE, new SampleContentSerializer(), { transientOutputs: true }
),
new SampleKernel()
);
}

View File

@ -0,0 +1,58 @@
import * as vscode from 'vscode';
import { TextDecoder, TextEncoder } from 'util';
/**
* An ultra-minimal sample provider that lets the user type in JSON, and then
* outputs JSON cells. The outputs are transient and not saved to notebook file on disk.
*/
interface RawNotebookData {
cells: RawNotebookCell[]
}
interface RawNotebookCell {
language: string;
value: string;
kind: vscode.NotebookCellKind;
editable?: boolean;
}
export class SampleContentSerializer implements vscode.NotebookSerializer {
public readonly label: string = 'My Sample Content Serializer';
public async deserializeNotebook(data: Uint8Array, token: vscode.CancellationToken): Promise<vscode.NotebookData> {
const contents = new TextDecoder().decode(data); // convert to String
// Read file contents
let raw: RawNotebookData;
try {
raw = <RawNotebookData>JSON.parse(contents);
} catch {
raw = { cells: [] };
}
// Create array of Notebook cells for the VS Code API from file contents
const cells = raw.cells.map(item => new vscode.NotebookCellData(
item.kind,
item.value,
item.language
));
return new vscode.NotebookData(cells);
}
public async serializeNotebook(data: vscode.NotebookData, token: vscode.CancellationToken): Promise<Uint8Array> {
// Map the Notebook data into the format we want to save the Notebook data as
const contents: RawNotebookData = { cells: [] };
for (const cell of data.cells) {
contents.cells.push({
kind: cell.kind,
language: cell.languageId,
value: cell.value
});
}
return new TextEncoder().encode(JSON.stringify(contents));
}
}

View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2020",
"lib": [
"es2020"
],
"outDir": "out",
"sourceMap": true,
"strict": true,
"rootDir": "src"
},
"exclude": [
"node_modules",
".vscode-test"
]
}