diff --git a/README.md b/README.md index d46dc2b94..a957c24c6 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,14 @@ This is a [monorepo](https://github.com/lerna/lerna#what-does-a-lerna-repo-look- | [geojson-extension](packages/geojson-extension) | `application/geo+json` | `.geojson`, `.geo.json` | | [json-extension](packages/json-extension) | `application/json` | `.json`, `.ipynb` | | [plotly-extension](packages/plotly-extension) | `application/vnd.plotly.v1+json` | `.plotly`, `.plotly.json` | +| [vdom-extension](packages/vdom-extension) | `application/vdom.v1+json` | `.vdom`, `.vdom.json` | ## Install * geojson-extension: `jupyter labextension install @jupyterlab/geojson-extension` * json-extension: `jupyter labextension install @jupyterlab/json-extension` * plotly-extension: `jupyter labextension install @jupyterlab/plotly-extension` +* vdom-extension: `jupyter labextension install @jupyterlab/vdom-extension` ## Contributing diff --git a/lerna.json b/lerna.json index 228d7d09b..c0b556e4e 100644 --- a/lerna.json +++ b/lerna.json @@ -3,5 +3,5 @@ "packages": [ "packages/*" ], - "version": "0.10.0" + "version": "0.10.1" } diff --git a/packages/geojson-extension/package.json b/packages/geojson-extension/package.json index 47d2e9031..54d5ea802 100644 --- a/packages/geojson-extension/package.json +++ b/packages/geojson-extension/package.json @@ -1,6 +1,6 @@ { "name": "@jupyterlab/geojson-extension", - "version": "0.10.0", + "version": "0.10.1", "description": "JupyterLab - GeoJSON Renderer", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/geojson-extension/src/index.tsx b/packages/geojson-extension/src/index.tsx index 0de14e17a..456d1d1cb 100644 --- a/packages/geojson-extension/src/index.tsx +++ b/packages/geojson-extension/src/index.tsx @@ -151,16 +151,16 @@ const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [ rank: 0, dataType: 'json', fileTypes: [{ - name: 'GeoJSON', + name: 'geojson', mimeTypes: [MIME_TYPE], extensions: ['.geojson', '.geo.json'], iconClass: CSS_ICON_CLASS }], documentWidgetFactoryOptions: { name: 'GeoJSON', - primaryFileType: 'GeoJSON', - fileTypes: ['GeoJSON'], - defaultFor: ['GeoJSON'] + primaryFileType: 'geojson', + fileTypes: ['geojson', 'json'], + defaultFor: ['geojson'] } } ]; diff --git a/packages/json-extension/package.json b/packages/json-extension/package.json index 2818d7250..198435994 100644 --- a/packages/json-extension/package.json +++ b/packages/json-extension/package.json @@ -1,6 +1,6 @@ { "name": "@jupyterlab/json-extension", - "version": "0.10.0", + "version": "0.10.1", "description": "JupyterLab - JSON Renderer", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,8 +18,8 @@ "dependencies": { "@jupyterlab/rendermime-interfaces": "^0.3.0", "@phosphor/widgets": "^1.3.0", - "react": "^15.6.1", - "react-dom": "^15.6.1", + "react": "^15.6.2", + "react-dom": "^15.6.2", "react-highlighter": "^0.4.0", "react-json-tree": "^0.10.9" }, diff --git a/packages/json-extension/src/index.tsx b/packages/json-extension/src/index.tsx index d0bebad96..1d70fc488 100644 --- a/packages/json-extension/src/index.tsx +++ b/packages/json-extension/src/index.tsx @@ -26,10 +26,7 @@ import '../style/index.css'; const CSS_CLASS = 'jp-RenderedJSON'; /** - * The MIME type for Vega. - * - * #### Notes - * The version of this follows the major version of Vega. + * The MIME type for JSON. */ export const MIME_TYPE = 'application/json'; @@ -38,7 +35,7 @@ const MIME_TYPE = 'application/json'; export class RenderedJSON extends Widget implements IRenderMime.IRenderer { /** - * Create a new widget for rendering Vega/Vega-Lite. + * Create a new widget for rendering JSON. */ constructor(options: IRenderMime.IRendererOptions) { super(); @@ -65,7 +62,7 @@ class RenderedJSON extends Widget implements IRenderMime.IRenderer { /** - * A mime renderer factory for GeoJSON data. + * A mime renderer factory for JSON data. */ export const rendererFactory: IRenderMime.IRendererFactory = { diff --git a/packages/plotly-extension/package.json b/packages/plotly-extension/package.json index b1aee307d..4bb435e2d 100644 --- a/packages/plotly-extension/package.json +++ b/packages/plotly-extension/package.json @@ -1,6 +1,6 @@ { "name": "@jupyterlab/plotly-extension", - "version": "0.10.0", + "version": "0.10.1", "description": "JupyterLab - Plotly Renderer", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/plotly-extension/src/index.tsx b/packages/plotly-extension/src/index.tsx index 7fe15d987..c9fa81325 100644 --- a/packages/plotly-extension/src/index.tsx +++ b/packages/plotly-extension/src/index.tsx @@ -41,14 +41,12 @@ namespace Private { const CSS_CLASS = 'jp-RenderedPlotly'; /** - * The CSS class for a GeoJSON icon. + * The CSS class for a Plotly icon. */ const CSS_ICON_CLASS = 'jp-MaterialIcon jp-PlotlyIcon'; /** - * The MIME type for Vega. - * - * #### Notes + * The MIME type for Plotly. * The version of this follows the major version of Plotly. */ export @@ -63,7 +61,7 @@ interface PlotlySpec { export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { /** - * Create a new widget for rendering Vega/Vega-Lite. + * Create a new widget for rendering Plotly. */ constructor(options: IRenderMime.IRendererOptions) { super(); @@ -115,7 +113,7 @@ class RenderedPlotly extends Widget implements IRenderMime.IRenderer { /** - * A mime renderer factory for GeoPlotly data. + * A mime renderer factory for Plotly data. */ export const rendererFactory: IRenderMime.IRendererFactory = { @@ -140,7 +138,7 @@ const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [ documentWidgetFactoryOptions: { name: 'Plotly', primaryFileType: 'plotly', - fileTypes: ['plotly'], + fileTypes: ['plotly', 'json'], defaultFor: ['plotly'] } } diff --git a/packages/vdom-extension/README.md b/packages/vdom-extension/README.md new file mode 100644 index 000000000..96b81fd19 --- /dev/null +++ b/packages/vdom-extension/README.md @@ -0,0 +1,104 @@ +# vdom-extension + +A JupyterLab extension for rendering VirtualDOM using React + +![demo](http://g.recordit.co/EIwAIBsGBh.gif) + +## Prerequisites + +* JupyterLab ^0.27.0 + +## Usage + +To render VDOM output in IPython: + +```python +from IPython.display import display + +def VDOM(data={}): + bundle = {} + bundle['application/vdom.v1+json'] = data + display(bundle, raw=True) + +VDOM({ + 'tagName': 'div', + 'attributes': {}, + 'children': [{ + 'tagName': 'h1', + 'attributes': {}, + 'children': 'Our Incredibly Declarative Example', + 'key': 0 + }, { + 'tagName': 'p', + 'attributes': {}, + 'children': ['Can you believe we wrote this ', { + 'tagName': 'b', + 'attributes': {}, + 'children': 'in Python', + 'key': 1 + }, '?'], + 'key': 1 + }, { + 'tagName': 'img', + 'attributes': { + 'src': 'https://media.giphy.com/media/xUPGcguWZHRC2HyBRS/giphy.gif' + }, + 'key': 2 + }, { + 'tagName': 'p', + 'attributes': {}, + 'children': ['What will ', { + 'tagName': 'b', + 'attributes': {}, + 'children': 'you', + 'key': 1 + }, ' create next?'], + 'key': 3 + }] +}) +``` + +Using the [vdom Python library](https://github.com/nteract/vdom): + +```python +from vdom import h1, p, img, div, b + +div([ + h1('Our Incredibly Declarative Example'), + p(['Can you believe we wrote this ', b('in Python'), '?']), + img(src="https://media.giphy.com/media/xUPGcguWZHRC2HyBRS/giphy.gif"), + p(['What will ', b('you'), ' create next?']), +]) +``` + +To render a `.vdom` or `.vdom.json` file as a tree, simply open it: + +## Install + +```bash +jupyter labextension install @jupyterlab/vdom-extension +``` + +## Development + +```bash +# Clone the repo to your local environment +git clone https://github.com/jupyterlab/jupyter-renderers.git +cd jupyter-renderers +# Install dependencies +npm install +# Build Typescript source +npm run build +# Link your development version of the extension with JupyterLab +jupyter labextension link packages/vdom-extension +# Rebuild Typescript source after making changes +npm run build +# Rebuild JupyterLab after making any changes +jupyter lab build +``` + +## Uninstall + +```bash +jupyter labextension uninstall @jupyterlab/vdom-extension +``` diff --git a/packages/vdom-extension/package.json b/packages/vdom-extension/package.json new file mode 100644 index 000000000..c811e3c1b --- /dev/null +++ b/packages/vdom-extension/package.json @@ -0,0 +1,46 @@ +{ + "name": "@jupyterlab/vdom-extension", + "version": "0.10.0", + "description": "JupyterLab - VDOM Renderer", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "files": [ + "lib/*.d.ts", + "lib/*.js", + "style/*" + ], + "directories": { + "lib": "lib/" + }, + "jupyterlab": { + "mimeExtension": true + }, + "dependencies": { + "@jupyterlab/rendermime-interfaces": "^0.3.0", + "@phosphor/widgets": "^1.3.0", + "@nteract/transform-vdom": "^1.1.1", + "react": "^15.6.2", + "react-dom": "^15.6.2" + }, + "devDependencies": { + "@types/react": "^15.0.33", + "@types/react-dom": "^15.5.1", + "rimraf": "^2.5.2", + "typescript": "~2.3.1" + }, + "scripts": { + "build": "tsc", + "clean": "rimraf lib", + "watch": "tsc -w" + }, + "repository": { + "type": "git", + "url": "https://github.com/jupyterlab/jupyter-renderers.git" + }, + "author": "Project Jupyter", + "license": "BSD-3-Clause", + "bugs": { + "url": "https://github.com/jupyterlab/jupyter-renderers/issues" + }, + "homepage": "https://github.com/jupyterlab/jupyter-renderers" +} diff --git a/packages/vdom-extension/src/index.tsx b/packages/vdom-extension/src/index.tsx new file mode 100644 index 000000000..ce9790d87 --- /dev/null +++ b/packages/vdom-extension/src/index.tsx @@ -0,0 +1,98 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +import { + Widget +} from '@phosphor/widgets'; + +import { + IRenderMime +} from '@jupyterlab/rendermime-interfaces'; + +import * as React from 'react'; + +import * as ReactDOM from 'react-dom'; + +import VDOM from '@nteract/transform-vdom'; + +import '../style/index.css'; + + +/** + * The CSS class to add to the VDOM Widget. + */ +const CSS_CLASS = 'jp-RenderedVDOM'; + +/** + * The CSS class for a VDOM icon. + */ +const CSS_ICON_CLASS = 'jp-MaterialIcon jp-VDOMIcon'; + +/** + * The MIME type for VDOM. + */ +export +const MIME_TYPE = 'application/vdom.v1+json'; + + +export +class RenderedVDOM extends Widget implements IRenderMime.IRenderer { + /** + * Create a new widget for rendering DOM. + */ + constructor(options: IRenderMime.IRendererOptions) { + super(); + this.addClass(CSS_CLASS); + this._mimeType = options.mimeType; + } + + /** + * Render VDOM into this widget's node. + */ + renderModel(model: IRenderMime.IMimeModel): Promise { + const data = model.data[this._mimeType] as any; + // const metadata = model.metadata[this._mimeType] as any || {}; + return new Promise((resolve, reject) => { + ReactDOM.render(, this.node, () => { + resolve(undefined); + }); + }); + } + + private _mimeType: string; +} + + +/** + * A mime renderer factory for VDOM data. + */ +export +const rendererFactory: IRenderMime.IRendererFactory = { + safe: true, + mimeTypes: [MIME_TYPE], + createRenderer: options => new RenderedVDOM(options) +}; + + +const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [ + { + name: 'VDOM', + rendererFactory, + rank: 0, + dataType: 'json', + fileTypes: [{ + name: 'vdom', + mimeTypes: [MIME_TYPE], + extensions: ['.vdom', '.vdom.json'], + iconClass: CSS_ICON_CLASS + }], + documentWidgetFactoryOptions: { + name: 'VDOM', + primaryFileType: 'vdom', + fileTypes: ['vdom', 'json'], + defaultFor: ['vdom'] + } + } +]; + +export default extensions; diff --git a/packages/vdom-extension/src/transform-vdom.d.ts b/packages/vdom-extension/src/transform-vdom.d.ts new file mode 100644 index 000000000..eb223f1a9 --- /dev/null +++ b/packages/vdom-extension/src/transform-vdom.d.ts @@ -0,0 +1,23 @@ +// Type definitions for @nteract/transform-vdom v1.1.1 +// https://github.com/jupyterlab/jupyter-renderers +// Definitions by: Grant Nestor + + +declare module '@nteract/transform-vdom' { + + import * as React from 'react'; + + interface VDOMElement { + tagName: 'string'; + attributes: Object; + children: Array; + key?: number | string | null; + } + + interface VDOMProps extends React.Props { + data: VDOMElement; + } + + export default class VDOM extends React.Component { } + +} diff --git a/packages/vdom-extension/style/index.css b/packages/vdom-extension/style/index.css new file mode 100644 index 000000000..0711698bf --- /dev/null +++ b/packages/vdom-extension/style/index.css @@ -0,0 +1,34 @@ +/** + Copyright (c) Jupyter Development Team. + Distributed under the terms of the Modified BSD License. +*/ + +/* Add CSS variables to :root */ +:root { + --jp-icon-vdom: url('./react.svg'); +} + +/* Base styles */ +.jp-RenderedVDOM { + width: 100%; + height: 100%; + padding: 0; + overflow: auto; +} + +/* Document styles */ +.jp-MimeDocument .jp-RenderedVDOM { + padding: 5px; +} + +/* Output styles */ +.jp-OutputArea .jp-RenderedVDOM { + +} + +/* Document icon */ +.jp-VDOMIcon { + background-image: var(--jp-icon-vdom); + background-size: 24px; + background-position: center !important; +} diff --git a/packages/vdom-extension/style/react.svg b/packages/vdom-extension/style/react.svg new file mode 100644 index 000000000..5592ebec6 --- /dev/null +++ b/packages/vdom-extension/style/react.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/packages/vdom-extension/tsconfig.json b/packages/vdom-extension/tsconfig.json new file mode 100644 index 000000000..3e7427e47 --- /dev/null +++ b/packages/vdom-extension/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "declaration": true, + "noImplicitAny": true, + "noEmitOnError": true, + "noUnusedLocals": true, + "module": "commonjs", + "moduleResolution": "node", + "target": "ES5", + "outDir": "./lib", + "lib": ["ES5", "ES2015.Promise", "DOM", "ES2015.Collection", "es2016"], + "jsx": "react", + "types": [] + }, + "include": ["src/*"] +} diff --git a/postBuild b/postBuild index 72214803c..cfff9054d 100755 --- a/postBuild +++ b/postBuild @@ -1,3 +1,3 @@ #!/bin/bash -jupyter labextension install @jupyterlab/geojson-extension @jupyterlab/json-extension @jupyterlab/plotly-extension +jupyter labextension install @jupyterlab/geojson-extension @jupyterlab/json-extension @jupyterlab/plotly-extension @jupyterlab/vdom-extension