mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Remove the renderer from this sample, add a "create" command
This commit is contained in:
@ -1,9 +0,0 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to the "notebook-serializer-example" extension will be documented in this file.
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- Initial release
|
||||
@ -1,28 +1,15 @@
|
||||
# notebook-serializer-example
|
||||
# notebook-serializer-sample
|
||||
|
||||
⚠️ Work-in-progress starter code for custom notebook renderers in VS Code. Expect this to change as notebooks matures. ⚠️
|
||||
This is a very simple extension sample demonstrating the use of the notebook serializer and controller APIs. This sample includes:
|
||||
|
||||
This starter 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.
|
||||
|
||||
- 🖥️ TypeScript code to create a simple `NotebookOutputRenderer`
|
||||
- 📦 A Webpack build for renderer client code
|
||||
- ⚡ Support for hot module reloading and safe boilerplate
|
||||
- 🎨 CSS modules support
|
||||
## Running this sample
|
||||
|
||||
### Running this Sample
|
||||
|
||||
1. `cd notebook-serializer-example`
|
||||
1. `code-insiders .`: Open the folder in VS Code Insiders
|
||||
1. `cd notebook-serializer-sample`
|
||||
1. `code .`: Open the folder in VS Code
|
||||
1. Hit `F5` to build+debug
|
||||
|
||||
### Structure
|
||||
|
||||
A Notebook Renderer consists of code that runs in the VS Code Extension Host (Node.js), which registers the renderer and passes data into the UI code running inside a WebView (Browser/DOM).
|
||||
|
||||
This uses TypeScript project references. There are three projects in the `src` directory:
|
||||
|
||||
- `extension` contains the code running in Node.js extension host. It's compiled with `tsc`.
|
||||
- `client` is the UI code, built by Webpack, with access to the DOM.
|
||||
- `common` contains code shared between the extension and client.
|
||||
|
||||
When you run `watch`, `compile`, or `dev`, we invoke both `tsc` and `webpack` to compile the extension and the client portion of the code.
|
||||
1. Run the command "Create JSON Notebook"
|
||||
1. Add and edit cells, and click the run button to invoke the controller
|
||||
|
||||
3541
notebook-serializer/package-lock.json
generated
3541
notebook-serializer/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,8 @@
|
||||
{
|
||||
"name": "notebook-serializer-example",
|
||||
"displayName": "notebook-serializer-example",
|
||||
"description": "Notebook using Serializer API example",
|
||||
"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"
|
||||
@ -10,23 +11,20 @@
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onNotebook:test-notebook-renderer"
|
||||
"onNotebook:test-notebook-serializer",
|
||||
"onCommand:notebook-serializer-sample.createJsonNotebook"
|
||||
],
|
||||
"main": "./out/extension/extension.js",
|
||||
"main": "./out/extension.js",
|
||||
"contributes": {
|
||||
"notebookRenderer": [
|
||||
{
|
||||
"id": "notebook-serializer-example",
|
||||
"entrypoint": "./out/client/index.js",
|
||||
"displayName": "notebook-serializer-example",
|
||||
"mimeTypes": [
|
||||
"x-application/sample-json-renderer"
|
||||
]
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"command": "notebook-serializer-sample.createJsonNotebook",
|
||||
"title": "Create JSON Notebook"
|
||||
}
|
||||
],
|
||||
"notebooks": [
|
||||
{
|
||||
"type": "test-notebook-renderer",
|
||||
"type": "test-notebook-serializer",
|
||||
"displayName": "Sample Notebook",
|
||||
"selector": [
|
||||
{
|
||||
@ -37,35 +35,19 @@
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "npm run compile && node out/test/checkNoTestProvider.js",
|
||||
"compile": "npm run compile:extension && npm run compile:client",
|
||||
"compile:extension": "tsc -b",
|
||||
"compile:client": "webpack --mode production",
|
||||
"vscode:prepublish": "npm run compile",
|
||||
"compile": "tsc -b",
|
||||
"lint": "eslint src --ext ts",
|
||||
"watch": "concurrently -r \"npm:watch:*\"",
|
||||
"watch:extension": "tsc -b --watch",
|
||||
"watch:client": "webpack --mode development --watch"
|
||||
"watch": "tsc -b --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/node": "14.x",
|
||||
"@types/vscode": "^1.74.0",
|
||||
"@types/vscode-notebook-renderer": "^1.72.0",
|
||||
"@types/webpack-env": "^1.16.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.26.0",
|
||||
"@typescript-eslint/parser": "^4.26.0",
|
||||
"concurrently": "^5.3.0",
|
||||
"css-loader": "^4.2.0",
|
||||
"eslint": "^7.27.0",
|
||||
"fork-ts-checker-webpack-plugin": "^5.0.14",
|
||||
"glob": "^7.1.7",
|
||||
"mocha": "^10.2.0",
|
||||
"style-loader": "^1.2.1",
|
||||
"ts-loader": "^9.2.2",
|
||||
"typescript": "^4.3.2",
|
||||
"vscode-notebook-error-overlay": "^1.0.1",
|
||||
"webpack": "^5.38.1",
|
||||
"webpack-cli": "^4.7.0"
|
||||
"typescript": "^4.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
4
notebook-serializer/src/client/css.d.ts
vendored
4
notebook-serializer/src/client/css.d.ts
vendored
@ -1,4 +0,0 @@
|
||||
declare module '*.css' {
|
||||
const classes: { [className: string]: string };
|
||||
export = classes;
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
import { render } from './render';
|
||||
import errorOverlay from 'vscode-notebook-error-overlay';
|
||||
import type { ActivationFunction } from 'vscode-notebook-renderer';
|
||||
|
||||
// Fix the public path so that any async import()'s work as expected.
|
||||
declare const __webpack_relative_entrypoint_to_root__: string;
|
||||
declare const scriptUrl: string;
|
||||
|
||||
__webpack_public_path__ = new URL(scriptUrl.replace(/[^/]+$/, '') + __webpack_relative_entrypoint_to_root__).toString();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// This is the entrypoint to the notebook renderer's webview client-side code.
|
||||
// This contains some boilerplate that calls the `render()` function when new
|
||||
// output is available. You probably don't need to change this code; put your
|
||||
// rendering logic inside of the `render()` function.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export const activate: ActivationFunction = context => {
|
||||
return {
|
||||
renderOutputItem(outputItem, element) {
|
||||
let shadow = element.shadowRoot;
|
||||
if (!shadow) {
|
||||
shadow = element.attachShadow({ mode: 'open' });
|
||||
const root = document.createElement('div');
|
||||
root.id = 'root';
|
||||
shadow.append(root);
|
||||
}
|
||||
const root = shadow.querySelector<HTMLElement>('#root')!;
|
||||
errorOverlay.wrap(root, () => {
|
||||
root.innerHTML = '';
|
||||
const node = document.createElement('div');
|
||||
root.appendChild(node);
|
||||
|
||||
render({ container: node, mime: outputItem.mime, value: outputItem.json(), context });
|
||||
});
|
||||
},
|
||||
disposeOutputItem(outputId) {
|
||||
// Do any teardown here. outputId is the cell output being deleted, or
|
||||
// undefined if we're clearing all outputs.
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -1,32 +0,0 @@
|
||||
// We've set up this sample using CSS modules, which lets you import class
|
||||
// names into JavaScript: https://github.com/css-modules/css-modules
|
||||
// You can configure or change this in the webpack.config.js file.
|
||||
import * as style from './style.css';
|
||||
import type { RendererContext } from 'vscode-notebook-renderer';
|
||||
|
||||
interface IRenderInfo {
|
||||
container: HTMLElement;
|
||||
mime: string;
|
||||
value: any;
|
||||
context: RendererContext<unknown>;
|
||||
}
|
||||
|
||||
// This function is called to render your contents.
|
||||
export function render({ container, mime, value }: IRenderInfo) {
|
||||
// Format the JSON and insert it as <pre><code>{ ... }</code></pre>
|
||||
// Replace this with your custom code!
|
||||
const pre = document.createElement('pre');
|
||||
pre.classList.add(style.json);
|
||||
const code = document.createElement('code');
|
||||
code.className = 'output';
|
||||
code.textContent = `mime type: ${mime}\n\n${JSON.stringify(value, null, 2)}`;
|
||||
pre.appendChild(code);
|
||||
container.appendChild(pre);
|
||||
}
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.addDisposeHandler(() => {
|
||||
// In development, this will be called before the renderer is reloaded. You
|
||||
// can use this to clean up or stash any state.
|
||||
});
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
.json code {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.output {
|
||||
background-color: lightblue;
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig-base.json",
|
||||
"compilerOptions": {
|
||||
// noEmit prevents the default tsc from building this--we use webpack instead
|
||||
"noEmit": true,
|
||||
"rootDir": ".",
|
||||
"module": "esnext",
|
||||
"lib": ["ES2019", "dom"],
|
||||
"types": ["webpack-env", "vscode-notebook-renderer"],
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class SampleKernel {
|
||||
private readonly _id = 'test-notebook-renderer-kernel';
|
||||
private readonly _id = 'test-notebook-serializer-kernel';
|
||||
private readonly _label = 'Sample Notebook Kernel';
|
||||
private readonly _supportedLanguages = ['json'];
|
||||
|
||||
@ -11,7 +11,7 @@ export class SampleKernel {
|
||||
constructor() {
|
||||
|
||||
this._controller = vscode.notebooks.createNotebookController(this._id,
|
||||
'test-notebook-renderer',
|
||||
'test-notebook-serializer',
|
||||
this._label);
|
||||
|
||||
this._controller.supportedLanguages = this._supportedLanguages;
|
||||
@ -37,7 +37,6 @@ export class SampleKernel {
|
||||
|
||||
try {
|
||||
execution.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.json(JSON.parse(cell.document.getText()), "x-application/sample-json-renderer"),
|
||||
vscode.NotebookCellOutputItem.json(JSON.parse(cell.document.getText()))
|
||||
])]);
|
||||
|
||||
33
notebook-serializer/src/extension.ts
Normal file
33
notebook-serializer/src/extension.ts
Normal 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()
|
||||
);
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
// The module 'vscode' contains the VS Code extensibility API
|
||||
// Import the module and reference it with the alias vscode in your code below
|
||||
import * as vscode from 'vscode';
|
||||
import { SampleKernel } from './controller';
|
||||
|
||||
import { SampleContentSerializer } from './provider';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(
|
||||
vscode.workspace.registerNotebookSerializer(
|
||||
'test-notebook-renderer', new SampleContentSerializer(), { transientOutputs: true }
|
||||
),
|
||||
new SampleKernel()
|
||||
);
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig-base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "../../out/extension",
|
||||
},
|
||||
"references": []
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES2019",
|
||||
"lib": [
|
||||
"ES2019"
|
||||
],
|
||||
"types": ["node"],
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"strict": true /* enable all strict type-checking options */
|
||||
/* Additional Checks */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,17 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./src/client"
|
||||
},
|
||||
{
|
||||
"path": "./src/extension"
|
||||
}
|
||||
]
|
||||
}
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2020",
|
||||
"lib": [
|
||||
"es2020"
|
||||
],
|
||||
"outDir": "out",
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"rootDir": "src"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".vscode-test"
|
||||
]
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const { DefinePlugin } = require('webpack');
|
||||
const path = require('path');
|
||||
|
||||
const outputFilename = 'index.js';
|
||||
const devServerPort = 8111;
|
||||
|
||||
module.exports = (env, argv) => ({
|
||||
mode: argv.mode,
|
||||
devtool: argv.mode === 'production' ? false : 'inline-source-map',
|
||||
entry: './src/client/index.ts',
|
||||
output: {
|
||||
path: path.join(__dirname, 'out', 'client'),
|
||||
filename: outputFilename,
|
||||
publicPath: '',
|
||||
libraryTarget: 'module',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.css'],
|
||||
},
|
||||
experiments: {
|
||||
outputModule: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
// Allow importing ts(x) files:
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
configFile: 'src/client/tsconfig.json',
|
||||
// transpileOnly enables hot-module-replacement
|
||||
transpileOnly: true,
|
||||
compilerOptions: {
|
||||
// Overwrite the noEmit from the client's tsconfig
|
||||
noEmit: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Allow importing CSS modules:
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
modules: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
devServer: {
|
||||
port: devServerPort,
|
||||
hot: true,
|
||||
// Disable the host check, otherwise the bundle running in VS Code won't be
|
||||
// able to connect to the dev server
|
||||
disableHostCheck: true,
|
||||
writeToDisk: true,
|
||||
headers: { 'Access-Control-Allow-Origin': '*' },
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: {
|
||||
tsconfig: 'src/client/tsconfig.json',
|
||||
},
|
||||
}),
|
||||
new DefinePlugin({
|
||||
// Path from the output filename to the output directory
|
||||
__webpack_relative_entrypoint_to_root__: JSON.stringify(
|
||||
path.posix.relative(path.posix.dirname(`/${outputFilename}`), '/'),
|
||||
),
|
||||
scriptUrl: 'import.meta.url',
|
||||
}),
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user