diff --git a/notebook-renderer-sample/.vscode/launch.json b/notebook-renderer-sample/.vscode/launch.json index a105960d..186617b5 100644 --- a/notebook-renderer-sample/.vscode/launch.json +++ b/notebook-renderer-sample/.vscode/launch.json @@ -8,10 +8,12 @@ "request": "launch", "runtimeExecutable": "${execPath}", "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" + "--extensionDevelopmentPath=${workspaceFolder}", + "--folder-uri=${workspaceFolder}/sample/", + "${workspaceFolder}/sample/sample.ipynb" ], "outFiles": [ - "${workspaceFolder}/dist/**/*.js" + "${workspaceFolder}/out/**/*.js" ], "preLaunchTask": "npm: webpack" } diff --git a/notebook-renderer-sample/.vscode/tasks.json b/notebook-renderer-sample/.vscode/tasks.json new file mode 100644 index 00000000..0a927d3d --- /dev/null +++ b/notebook-renderer-sample/.vscode/tasks.json @@ -0,0 +1,14 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "webpack", + "problemMatcher": [ + "$ts-webpack" + ], + "label": "npm: webpack", + "detail": "webpack --mode development" + } + ] +} \ No newline at end of file diff --git a/notebook-renderer-sample/.vscodeignore b/notebook-renderer-sample/.vscodeignore index 61e4d768..0e8648f9 100644 --- a/notebook-renderer-sample/.vscodeignore +++ b/notebook-renderer-sample/.vscodeignore @@ -10,3 +10,7 @@ vsc-extension-quickstart.md **/*.map **/*.ts **/*.tsbuildinfo +node_modules/** +notebook-renderer-sample.gif +sample/** +*.vsix \ No newline at end of file diff --git a/notebook-renderer-sample/README.md b/notebook-renderer-sample/README.md index 26bf61cd..0ac2e105 100644 --- a/notebook-renderer-sample/README.md +++ b/notebook-renderer-sample/README.md @@ -4,12 +4,20 @@ Demonstrates a custom [notebook renderer](https://code.visualstudio.com/api/exte This starter includes: - - 🖥️ TypeScript code to create a simple `NotebookOutputRenderer` - - 📦 A Webpack build for the renderer - - 🎨 CSS modules support +- 🖥️ TypeScript code to create a simple `NotebookOutputRenderer` +- 📦 A Webpack build for the renderer +- 🎨 CSS modules support -### Running this Sample +## Running this Sample + +Ensure you have a Python installed to actually run the sample and invoke the renderer. 1. `cd notebook-renderer-sample` - 1. `code-insiders .`: Open the folder in VS Code Insiders + 1. `code .`: Open the folder in VS Code Insiders 1. Hit `F5` to build+debug + 1. Run the sample notebook + 1. Switch the output rendering by clicking [...] button next to the cell output and then _Change Presentation_ + +When you select the `x-application/github-issues`, the custom renderer will be invoked. + +![Notebook cell output renderer demo](notebook-renderer-sample.gif) diff --git a/notebook-renderer-sample/notebook-renderer-sample.gif b/notebook-renderer-sample/notebook-renderer-sample.gif new file mode 100644 index 00000000..eb915eea Binary files /dev/null and b/notebook-renderer-sample/notebook-renderer-sample.gif differ diff --git a/notebook-renderer-sample/package.json b/notebook-renderer-sample/package.json index ef3bd3c7..db0f1c2d 100644 --- a/notebook-renderer-sample/package.json +++ b/notebook-renderer-sample/package.json @@ -11,6 +11,10 @@ "categories": [ "Other" ], + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, "contributes": { "notebookRenderer": [ { diff --git a/notebook-renderer-sample/sample/sample.ipynb b/notebook-renderer-sample/sample/sample.ipynb new file mode 100644 index 00000000..645e69ed --- /dev/null +++ b/notebook-renderer-sample/sample/sample.ipynb @@ -0,0 +1,147 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Directing notebook cell execution output to a custom VS Code notebook renderer\n", + "\n", + "Switch the cell output rendering by clicking on the [...] button next to the cell output and then _Change Presentation_. When you select the `x-application/github-issues`, the custom renderer will be invoked.\n", + "\n", + "If you are getting _Renderer not available_ message, you are not running/debugging this sample extension.\n", + "\n", + "## Using `IPython.display.display` function and mimetypes" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/json": [ + { + "body": "Bug A description...", + "title": "Bug A", + "url": "https://github.com/project/repo/issue/123" + }, + { + "body": "Bug B description...", + "title": "Bug B", + "url": "https://github.com/project/repo/issue/456" + } + ], + "text/html": [ + "

[html] Bug A, Bug B

" + ], + "text/plain": [ + "[plain] https://github.com/project/repo/issue/123, https://github.com/project/repo/issue/456" + ], + "x-application/github-issues": "[{\"url\": \"https://github.com/project/repo/issue/123\", \"title\": \"Bug A\", \"body\": \"Bug A description...\"}, {\"url\": \"https://github.com/project/repo/issue/456\", \"title\": \"Bug B\", \"body\": \"Bug B description...\"}]" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython import display\n", + "import json\n", + "\n", + "issues = [{\n", + " \"url\": \"https://github.com/project/repo/issue/123\",\n", + " \"title\": \"Bug A\",\n", + " \"body\": \"Bug A description...\"\n", + " },\n", + " {\n", + " \"url\": \"https://github.com/project/repo/issue/456\",\n", + " \"title\": \"Bug B\",\n", + " \"body\": \"Bug B description...\"\n", + " }]\n", + "\n", + "display.display({\n", + " \"x-application/github-issues\": json.dumps(issues),\n", + " \"application/json\": json.dumps(issues, indent=2),\n", + " \"text/html\": \"

[html] \" + \", \".join([i[\"title\"] for i in issues]) + \"

\",\n", + " \"text/plain\": \"[plain] \" + \", \".join([i[\"url\"] for i in issues]),\n", + "}, raw=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using the `IPython.display.display` function with an object" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import List\n", + "from dataclasses import dataclass, is_dataclass, asdict\n", + "\n", + "@dataclass\n", + "class GitHubIssue:\n", + " url: str\n", + " title: str\n", + " body: str\n", + "\n", + "issues = [GitHubIssue(\"https://github.com/project/repo/issue/123\", \"Bug A\", \"Bug A description...\"),\n", + " GitHubIssue(\"https://github.com/project/repo/issue/456\", \"Bug B\", \"Bug B description...\")]\n", + "\n", + "class DataClassJSONEncoder(json.JSONEncoder):\n", + " \"\"\" Overrides the json serialization of dataclasses \"\"\"\n", + " def default(s, o):\n", + " if is_dataclass(o):\n", + " return asdict(o)\n", + " return super().default(o)\n", + "\n", + "class GitHubIssues(object):\n", + " def __init__(self, issues: List[GitHubIssue]):\n", + " self.issues = issues\n", + "\n", + " def json_dump(self) -> str:\n", + " return json.dumps(self.issues, cls=DataClassJSONEncoder)\n", + "\n", + " def _repr_mimebundle_(self, include, exclude):\n", + " return {\n", + " \"text/plain\": \"[plain]\\n\" + \"\\n\".join([i.url for i in self.issues]),\n", + " \"text/html\": \"

[html]

\" + \"\".join(['
  • ' + i.title + '
  • ' for i in self.issues]),\n", + " \"x-application/github-issues\": self.json_dump(),\n", + " }\n", + "\n", + "display.display(GitHubIssues(issues))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.8 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "768fe601637759c91db8ec17fe83492f1129ce8f3a2f541ec5a1b5d925da7477" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}