jupyter-ijavascript-utils 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js ADDED
@@ -0,0 +1,33 @@
1
+ module.exports = {
2
+ root: true,
3
+ parser: 'babel-eslint',
4
+ env: {
5
+ commonjs: true,
6
+ es2021: true,
7
+ node: true,
8
+ jest: true
9
+ },
10
+ extends: [
11
+ 'airbnb-base',
12
+ ],
13
+ parserOptions: {
14
+ ecmaVersion: 12
15
+ },
16
+ rules: {
17
+ 'no-trailing-spaces': ['error', { skipBlankLines: true, ignoreComments: true }],
18
+ 'comma-dangle': 'off',
19
+ 'spaced-comment': 'off',
20
+ 'no-confusing-arrow': 'off',
21
+ 'no-console': 'off',
22
+ 'no-unused-vars': ['error', { args: 'none' }],
23
+ 'arrow-parens': ['error', 'always'],
24
+ 'no-nested-ternary': 'off',
25
+ 'no-restricted-syntax': 'off',
26
+ 'consistent-return': 'off',
27
+ 'object-curly-newline': 'off',
28
+ 'no-multi-spaces': 'off',
29
+ 'lines-between-class-members': 'off',
30
+ 'no-unneeded-ternary': 'off',
31
+ 'no-else-return': ['error', { allowElseIf: true }],
32
+ }
33
+ };
package/.screenrc ADDED
@@ -0,0 +1,75 @@
1
+ #!/bin/bash
2
+
3
+ # sets a screen session for the current project
4
+
5
+ # sets the current window's name
6
+ screen -X title "notebooks"
7
+ screen -X stuff "cd ../^M"
8
+ screen -X number 0
9
+
10
+ # uncomment below to make the tabs only run those commands
11
+ # but note that restarting will lose that tab
12
+
13
+ screen -X dynamictitle off
14
+ screen -X defdynamictitle off
15
+
16
+ screen -t "ijsUtils"
17
+ screen -p ijsUtils -X stuff "cd ../jupyter-ijavascript-utils^M"
18
+ screen -t "jsUtils"
19
+ screen -p jsUtils -X stuff "cd ../jupyterJsUtils^M"
20
+ screen -t "scratchpad"
21
+ screen -p scratchpad -X stuff "cd ../jupyterScratchpad^M"
22
+ screen -t "p4js"
23
+ screen -p p4js -X stuff "cd '../python-for-js-developers'^M"
24
+
25
+ screen -t lint
26
+ screen -p lint -X stuff "npm run lint:watch"
27
+ screen -t test
28
+ screen -p test -X stuff "npm run test:watch"
29
+ screen -t debug
30
+
31
+ screen -t "server" 10
32
+ screen -p server -X stuff "cd ../^Mjupyter lab"
33
+ screen -t plantuml 11
34
+ screen -p plantuml -X stuff "plantuml -picoweb"
35
+ screen -t codeserver 12
36
+ screen -p codeserver -X stuff "code-server .."
37
+
38
+ screen -X select 0
39
+
40
+ # create layouts
41
+
42
+ screen -X layout new default
43
+ screen -X select ijsUtils
44
+
45
+ screen -X layout new dev
46
+ #screen -X select micro
47
+ #screen -X split -h
48
+ #screen -X resize 70%
49
+ #screen -X focus
50
+ screen -X select lint
51
+ screen -X split -v
52
+ screen -X focus
53
+ screen -X select test
54
+
55
+ screen -X layout new test
56
+ screen -X select test
57
+ screen -X split -h
58
+ screen -X resize 60%
59
+ screen -X focus
60
+ screen -X select lint
61
+
62
+ screen -X layout new server
63
+ screen -X select server
64
+ screen -X split -v
65
+ screen -X focus right
66
+ screen -X select plantuml
67
+
68
+ screen -X layout select default
69
+
70
+ # key bindings
71
+
72
+ # screen -X bindkey -k k1 layout select 0
73
+ # screen -X bindkey -k k2 layout select 1
74
+ # screen -X bindkey -k k3 layout select 2
75
+
package/DOCS.md ADDED
@@ -0,0 +1,79 @@
1
+ # Overview
2
+
3
+ This is a simple Library for using Jupyter with the IJavaScript kernel
4
+
5
+ See the [#Installation section for requirements and installation](#install)
6
+
7
+ | Export | Description |
8
+ |-----------|----------------------------------------------------------------------------------|
9
+ | [ijs](./IJSUtils.html) | Utility methods to support working within the iJavaScript kernel within Jupyter. |
10
+ | [datasets](./module-datasets.html) | Utilities to facilitate working with example datasets provided by vega. |
11
+ | [vega](./module-vega.html) | Simple utility to streamline showing Vega-Lite charts within iJS Notebooks. |
12
+
13
+ -------
14
+
15
+ ## For Example
16
+
17
+ ```
18
+ //-- get the data
19
+ utils.dataset.fetch('barley.json').then((data) => barley = data);
20
+
21
+ //-- get the min max of the types of barley
22
+ barleyByVarietySite = d3.group(barley, d => d.variety, d => d.site)
23
+
24
+ // InternMap(10) [Map] {
25
+ // 'Manchuria' => InternMap(6) [Map] {
26
+ // 'University Farm' => [ [Object], [Object] ],
27
+ // 'Waseca' => [ [Object], [Object] ],
28
+ // ...
29
+ // }, ...
30
+ // }
31
+
32
+ //-- now group by variety and year
33
+ barleyByVarietyYear = d3.group(barley, d => d.variety, d => d.year)
34
+
35
+ // nternMap(10) [Map] {
36
+ // 'Manchuria' => InternMap(2) [Map] {
37
+ // 1931 => [ [Object], [Object], [Object], [Object], [Object], [Object] ],
38
+ // 1932 => [ [Object], [Object], [Object], [Object], [Object], [Object] ]
39
+ // }, ...
40
+ //
41
+ ```
42
+
43
+ [note: See here to learn more about d3 grouping](https://observablehq.com/@d3/d3-group)
44
+
45
+ then later
46
+
47
+ ```
48
+ utils.ijs.listGlobals();
49
+ // ['barley','d3','barleyByVariety','barleyByVarietySite',...]
50
+ ```
51
+
52
+ now show a graph
53
+
54
+ ```
55
+ utils.vega.svg($$, utils.vega.markPoint()
56
+ .data(barley)
57
+ .title('Barley Yield by Site')
58
+ .width(600)
59
+ .encode(
60
+ utils.vega.x().fieldN('site'),
61
+ utils.vega.y().fieldQ('yield'),
62
+ utils.vega.color().fieldN('year')
63
+ )
64
+ )
65
+ ```
66
+
67
+ ![Screenshot of Vega Cell](img/BarleyYieldBySite.png)
68
+
69
+ <a name="install">&nbsp;</a>
70
+ # Install
71
+
72
+ Note that some of the utilities assumes you are running within Jupyter - within n-riesco's iJavaScript kernel (that provides JavaScript language support within Jupyter)
73
+
74
+ `npm install jupyter-ijavascript-utils`
75
+
76
+ Depends on:
77
+
78
+ * [Jupyter Tools - such as Jupyter Lab](https://jupyter.org/)
79
+ * [n-riesco/ijavascript jupyter kernel](https://github.com/n-riesco/ijavascript#installation)
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2022 Paul Roth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ <p align="center">
2
+ <a href="https://jupyter-ijavascript-utils.onrender.com/" alt="Documentation">
3
+ <img src="https://img.shields.io/badge/Documentation-here-informational" />
4
+ </a>
5
+ <a href="https://jupyter-ijavascript-utils.onrender.com/LICENSE" alt="License">
6
+ <img src="https://img.shields.io/badge/License-MIT-green" />
7
+ </a>
8
+ </p>
9
+
10
+ # Overview
11
+
12
+ Simple library for working with Jupyter - through IJavaScript kernel.
13
+
14
+ ## For Example
15
+
16
+ ```
17
+ //-- get the data
18
+ utils.dataset.fetch('barley.json').then((data) => barley = data);
19
+
20
+ //-- get the min max of the types of barley
21
+ barleyByVarietySite = d3.group(barley, d => d.variety, d => d.site)
22
+
23
+ // InternMap(10) [Map] {
24
+ // 'Manchuria' => InternMap(6) [Map] {
25
+ // 'University Farm' => [ [Object], [Object] ],
26
+ // 'Waseca' => [ [Object], [Object] ],
27
+ // ...
28
+ // }, ...
29
+ // }
30
+
31
+ //-- now group by variety and year
32
+ barleyByVarietyYear = d3.group(barley, d => d.variety, d => d.year)
33
+
34
+ // nternMap(10) [Map] {
35
+ // 'Manchuria' => InternMap(2) [Map] {
36
+ // 1931 => [ [Object], [Object], [Object], [Object], [Object], [Object] ],
37
+ // 1932 => [ [Object], [Object], [Object], [Object], [Object], [Object] ]
38
+ // }, ...
39
+ //
40
+ ```
41
+
42
+ [note: See here to learn more about d3 grouping](https://observablehq.com/@d3/d3-group)
43
+
44
+ then later
45
+
46
+ ```
47
+ utils.ijs.listGlobals();
48
+ // ['barley','d3','barleyByVariety','barleyByVarietySite',...]
49
+ ```
50
+
51
+ now show a graph
52
+
53
+ ```
54
+ utils.vega.svg($$, utils.vega.markPoint()
55
+ .data(barley)
56
+ .title('Barley Yield by Site')
57
+ .width(600)
58
+ .encode(
59
+ utils.vega.x().fieldN('site'),
60
+ utils.vega.y().fieldQ('yield'),
61
+ utils.vega.color().fieldN('year')
62
+ )
63
+ )
64
+ ```
65
+
66
+ ![Screenshot of Vega Cell](https://jupyter-ijavascript-utils.onrender.com/img/BarleyYieldBySite.png)
67
+
68
+ # Documentation
69
+
70
+ See documentation at: [https://jupyter-ijavascript-utils.onrender.com/](https://jupyter-ijavascript-utils.onrender.com/)
71
+
72
+ # License
73
+
74
+ See [License](https://jupyter-ijavascript-utils.onrender.com/LICENSE) (MIT License).
75
+
76
+ # Issues
77
+
78
+ If you have any questions first file it on [issues](https://github.com/paulroth3d/jupyter-ijavascript-utils/issues) before contacting authors.
79
+
80
+ # Contributions
81
+
82
+ Your contributions are welcome: both by reporting issues on [GitHub issues](https://github.com/paulroth3d/jupyter-ijavascript-utils/issues) or pull-requesting patches.
83
+
84
+ If you want to implement any additional features, to be added to JSforce to our master branch, which may or may not be merged please first check current [opening issues](https://github.com/paulroth3d/jupyter-ijavascript-utils/issues?q=is%3Aopen) with milestones and confirm whether the feature is on road map or not.
85
+
86
+ If your feature implementation is brand-new or fixing unsupposed bugs in the library's test cases, please include addtional test codes in the `src/__tests__/` directory.
87
+
88
+
89
+ ## Further Reading
90
+
91
+ * [JSDoc Templates](https://cancerberosgx.github.io/jsdoc-templates-demo/demo/)
92
+ * [DocDash Template](http://clenemt.github.io/docdash/)
93
+ * [DocDash Example Code](http://clenemt.github.io/docdash/base_chains.js.html)
94
+ * [Gist creating JSDoc to MD](https://gist.github.com/slorber/0bf8c8c8001505f0f99a062ac55bf442)
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2022 Paul Roth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/jsdoc.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "tags": {
3
+ "allowUnknownTags": false
4
+ },
5
+ "source": {
6
+ "include": "./src",
7
+ "includePattern": "\\.js$",
8
+ "excludePattern": "(node_modules/|docs)"
9
+ },
10
+ "plugins": [
11
+ "plugins/markdown"
12
+ ],
13
+ "opts": {
14
+ "template": "node_modules/docdash",
15
+ "encoding": "utf8",
16
+ "destination": "docs/",
17
+ "recurse": true,
18
+ "verbose": true
19
+ },
20
+ "templates": {
21
+ "default":{
22
+ "outputSourceFiles":false,
23
+ "staticFiles": {
24
+ "paths": ["./docResources/"]
25
+ }
26
+ },
27
+ "cleverLinks": false,
28
+ "monospaceLinks": false
29
+ }
30
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "jupyter-ijavascript-utils",
3
+ "version": "1.0.0",
4
+ "description": "Utilities for working with iJavaScript - a Jupyter Kernel",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "lint": "esw src",
8
+ "lint:watch": "npm run lint -- --watch",
9
+ "test": "jest src",
10
+ "test:watch": "npm run test -- --watch",
11
+ "test:debug": "node --inspect-brk node_modules/jest/bin/jest.js --runInBand",
12
+ "doc": "node_modules/.bin/jsdoc -c ./jsdoc.json ./DOCS.md"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git@github.com:paulroth3d/jupyter-ijavascript-utils.git"
17
+ },
18
+ "keywords": [
19
+ "ijavascript",
20
+ "jupyter"
21
+ ],
22
+ "author": "Paul Roth",
23
+ "license": "MIT",
24
+ "devDependencies": {
25
+ "babel-eslint": "^10.1.0",
26
+ "docdash": "^1.2.0",
27
+ "eslint": "^7.29.0",
28
+ "eslint-config-airbnb-base": "^14.2.1",
29
+ "eslint-plugin-import": "^2.23.4",
30
+ "eslint-watch": "^7.0.0",
31
+ "jest": "^27.0.6",
32
+ "jsdoc": "^3.6.10",
33
+ "sinon": "^11.1.1"
34
+ },
35
+ "dependencies": {
36
+ "fs-extra": "^10.0.0",
37
+ "generate-schema": "^2.6.0",
38
+ "node-fetch": "^2.6.5",
39
+ "pino": "^6.12.0",
40
+ "pino-pretty": "^5.1.2",
41
+ "plantuml-encoder": "^1.4.0",
42
+ "promise-sequential": "^1.1.1",
43
+ "rxjs": "^7.1.0",
44
+ "vega": "^5.20.2",
45
+ "vega-datasets": "^2.2.0",
46
+ "vega-lite": "^5.1.0",
47
+ "vega-lite-api": "^5.0.0"
48
+ }
49
+ }
@@ -0,0 +1,8 @@
1
+ // const codeBlockHelper = require('../codeBlockHelper');
2
+ // const ijsUtils = require('../ijsUtils');
3
+
4
+ global.describe('codeBlockHelper', () => {
5
+ global.it('test', () => {
6
+ global.expect(1 + 2).toBe(3);
7
+ });
8
+ });
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @fileoverview
3
+ * Utilities to facilitate working with [vega/vega-datasets](https://github.com/vega/vega-datasets)
4
+ *
5
+ * Vega datasets are a collection of datasets used in Vega and in Vega-Lite examples.
6
+ *
7
+ * The data lives at [https://github.com/vega/vega-datasets](https://github.com/vega/vega-datasets)
8
+ * and [https://cdn.jsdelivr.net/npm/vega-datasets](https://cdn.jsdelivr.net/npm/vega-datasets)
9
+ *
10
+ * @module datasets
11
+ * @exports datasets
12
+ *
13
+ * @example
14
+ *
15
+ * datasets.list(); //-- prints the list of the datasets supported
16
+ * myDataset = datasets.fetch('cars.json');
17
+ *
18
+ * @see #~list
19
+ * @see #~fetch
20
+ *
21
+ */
22
+ const datasets = require('vega-datasets');
23
+ const fetch = require('node-fetch');
24
+
25
+ //-- setup datasets
26
+ /**
27
+ * This will polyfill 'fetch' if your node instance does not have an implementation.
28
+ * @method setupFetch
29
+ * @private
30
+ */
31
+ datasets.setupFetch = () => {
32
+ if ((typeof global.fetch) === 'undefined') {
33
+ global.fetch = fetch;
34
+ }
35
+ };
36
+
37
+ /**
38
+ * Prints the lists of datasets available
39
+ * @method list
40
+ * @returns {String[]} - list of dataset ids that can be fetched.
41
+ *
42
+ * @example
43
+ *
44
+ * [
45
+ * 'annual-precip.json',
46
+ * 'anscombe.json',
47
+ * 'barley.json',
48
+ * 'budget.json',
49
+ * 'budgets.json',
50
+ * 'burtin.json',
51
+ * 'cars.json',
52
+ * 'countries.json',
53
+ * 'crimea.json',
54
+ * 'driving.json',
55
+ * ... ];
56
+ ]
57
+ */
58
+ datasets.list = () => Object.keys(datasets).filter((r) => r.endsWith('.json'));
59
+
60
+ /**
61
+ * Shim for fetching things through the node-fetch library
62
+ * @method nodeFetch
63
+ * @private
64
+ */
65
+ datasets.nodeFetch = fetch;
66
+
67
+ /**
68
+ * Fetches a specific dataset from within the list available from [vega-datasets](https://github.com/vega/vega-datasets)
69
+ *
70
+ * @method fetch
71
+ * @param {string} library - one of the names of the libraries available from list
72
+ * @returns {Object[]} - results from the dataset
73
+ * @see #~list
74
+ *
75
+ * @example
76
+ *
77
+ * Example:
78
+ * datasets.list(); //-- see the list of datasets.
79
+ * // cars.json
80
+ * datasets.fetch('cars.json').then(results => cars = results);
81
+ * [
82
+ * {
83
+ * Name: 'chevrolet chevelle malibu',
84
+ * Miles_per_Gallon: 18,
85
+ * Cylinders: 8,
86
+ * Displacement: 307,
87
+ * Horsepower: 130,
88
+ * Weight_in_lbs: 3504,
89
+ * Acceleration: 12,
90
+ * Year: '1970-01-01',
91
+ * Origin: 'USA'
92
+ * },
93
+ * {
94
+ * Name: 'buick skylark 320',
95
+ * Miles_per_Gallon: 15,
96
+ * Cylinders: 8,
97
+ * Displacement: 350,
98
+ * Horsepower: 165,
99
+ * Weight_in_lbs: 3693,
100
+ * Acceleration: 11.5,
101
+ * Year: '1970-01-01',
102
+ * Origin: 'USA'
103
+ * },
104
+ * ...
105
+ * ];
106
+ */
107
+ datasets.fetch = (library) => {
108
+ const listSet = new Set(datasets.list());
109
+ if (!listSet.has(library)) {
110
+ throw new Error(`datasets do not contain[${library}] : ${listSet}`);
111
+ }
112
+
113
+ datasets.setupFetch();
114
+ return datasets[library]();
115
+ };
116
+
117
+ module.exports = datasets;
@@ -0,0 +1,161 @@
1
+ /* eslint-disable no-use-before-define, function-paren-newline */
2
+
3
+ /**
4
+ * @typedef {Object} IJavaScriptContext
5
+ * @property {any} $$ - current display
6
+ * @property {any} console - current console
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} StaticMember
11
+ * @property {Boolean} isMethod -
12
+ * @property {String} type - the typeof for the member
13
+ * @property {String} constructor - the type of constructor for the class
14
+ * @property {String} name - the name of the member
15
+ */
16
+
17
+ /**
18
+ * Simple library to support working within the [iJavaScript kernel within Jupyter](https://github.com/n-riesco/ijavascript)
19
+ *
20
+ * Note that this is available as `ijs` from within the
21
+ * [jupyter-ijavascript-utils module](./index.html)
22
+ *
23
+ * For example:
24
+ *
25
+ * ```
26
+ * //-- get the data
27
+ * utils.dataset.fetch('barley.json').then((data) => barley = data);
28
+ * //-- get the min max of the types of barley
29
+ * barleyByVarietySite = d3.group(barley, d => d.variety, d => d.site)
30
+ * //-- now group by variety and year
31
+ * barleyByVarietyYear = d3.group(barley, d => d.variety, d => d.year)
32
+ * ```
33
+ *
34
+ * then later
35
+ *
36
+ * ```
37
+ * utils.ijs.listGlobals();
38
+ * // ['barley','d3','barleyByVariety','barleyByVarietySite',...]
39
+ * ```
40
+ *
41
+ * @module ijs
42
+ * @exports ijs
43
+ */
44
+ class IJSUtils {
45
+ /**
46
+ * Set with names of common global variables that aren't needed to be listed.
47
+ * @see #.listGlobals
48
+ */
49
+ static COMMON_GLOBALS = new Set([
50
+ 'global', 'clearInterval', 'clearTimeout', 'setInterval', 'setTimeout', 'queueMicrotask',
51
+ 'clearImmediate', 'setImmediate', 'module', 'exports', 'require', '$$mimer$$', '$$done$$'
52
+ ]);
53
+
54
+ /**
55
+ * Set with names of static methods that often belong to a class.
56
+ * @see #.listStatic
57
+ */
58
+ static COMMON_STATIC = new Set(['length', 'prototype', 'name']);
59
+
60
+ /**
61
+ * Determines the current global display and console from iJavaScript
62
+ * (or null if not within iJavaScript)
63
+ * @returns {IJavaScriptContext} or null if not within iJavaScript
64
+ * @method detectContext
65
+ */
66
+ static detectContext() {
67
+ if (
68
+ ((typeof global.$$) === 'undefined')
69
+ && ((typeof global.console) === 'undefined')
70
+ ) {
71
+ return null;
72
+ }
73
+
74
+ return {
75
+ $$: global.$$,
76
+ console: global.console
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Determines if we are currently within the iJavaScript context
82
+ * @returns {Boolean} - true if the code is running within an iJavaScript kernel
83
+ * @method detectIJS
84
+ */
85
+ static detectIJS() {
86
+ return IJSUtils.detectContext() ? true : false;
87
+ }
88
+
89
+ /**
90
+ * Prints markdown if in the context of iJavaScript
91
+ * @param {String} markdownText - The markdown to be rendered
92
+ * @method markdown
93
+ * @example
94
+ *
95
+ * utils.ijs.markdown(`# Overview
96
+ * This is markdown rendered in a cell.`);
97
+ */
98
+ static markdown(markdownText, display) {
99
+ if (!IJSUtils.detectIJS()) return;
100
+ const displayToUse = display || global.$$;
101
+ displayToUse.mime({ 'text/markdown': markdownText });
102
+ }
103
+
104
+ /**
105
+ * List the globals currently defined.
106
+ *
107
+ * This can be very useful when keeping track of values after a few cells.
108
+ *
109
+ * For example:
110
+ *
111
+ * ```
112
+ * cars = utils.datasets.fetch('cars.json').then(data => global.cars = data);
113
+ * ```
114
+ *
115
+ * then later
116
+ *
117
+ * ```
118
+ * utils.ijs.listGlobals();
119
+ * // cars
120
+ * ```
121
+ *
122
+ * @returns {String[]} - list of the global variables
123
+ * @method listGlobals
124
+ */
125
+ static listGlobals() {
126
+ return Object.keys(global)
127
+ .filter((key) => !IJSUtils.COMMON_GLOBALS.has(key));
128
+ }
129
+
130
+ /**
131
+ * List the static members and functions of a class.
132
+ *
133
+ * @method listStatic
134
+ * @param {class} target - the target class
135
+ * @returns {StaticMember[]}
136
+ *
137
+ * @example
138
+ *
139
+ * utils.ijs.listStatic(utils.ijs)
140
+ * // [{type:'function', constructor:'Function', isMethod:true, name:'listStatic'}, ...]
141
+ */
142
+ static listStatic(target) {
143
+ if (!target) return [];
144
+
145
+ return Object.getOwnPropertyNames(target)
146
+ .filter((prop) => !IJSUtils.COMMON_STATIC.has(prop))
147
+ .map((prop) => {
148
+ const propType = typeof target[prop];
149
+ const constructor = target[prop].constructor.name;
150
+ const isMethod = propType === 'function';
151
+ return ({
152
+ type: propType,
153
+ constructor,
154
+ isMethod,
155
+ name: prop
156
+ });
157
+ });
158
+ }
159
+ }
160
+
161
+ module.exports = IJSUtils;
package/src/index.js ADDED
@@ -0,0 +1,18 @@
1
+ const datasets = require('./datasets');
2
+ const ijsUtils = require('./IJSUtils');
3
+ const vega = require('./vega');
4
+
5
+ /**
6
+ * Default module
7
+ * @module index
8
+ * @exports index
9
+ * @private
10
+ */
11
+ module.exports = {
12
+ /** @see module:datasets */
13
+ datasets,
14
+ /** @see IJSUtils */
15
+ ijs: ijsUtils,
16
+ /** @see module:vega */
17
+ vega
18
+ };
package/src/vega.js ADDED
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Helper for working with Vega-Lite within iJavaScript notebooks.
3
+ *
4
+ * * (see [@vega/vega-lite-api-v5 on observablehq](https://observablehq.com/@vega/vega-lite-api-v5) for a great introduction)
5
+ * * (see [vega-lite documentation](https://observablehq.com/@vega/vega-lite-api-v5) for deeper options)
6
+ *
7
+ * Vega-Lite is a charting library that provides a great deal of flexibility
8
+ * while also allowing for very simple use cases.
9
+ *
10
+ * The Vega-Lite JavaScript API provides a convenient way to write Vega-Lite
11
+ * specifications in a programmatic fashion.
12
+ *
13
+ * ## Getting Started
14
+ *
15
+ * The simplext example is to have a small dataset we want to render:
16
+ *
17
+ * ```
18
+ * simpleData = [{fruit:'Apples',yield:20,year:'2020'},{fruit:'Apples',yield:22,year:'2021'},
19
+ * {fruit:'Bananas',yield:15,year:'2020'},{fruit:'Bananas',yield:12,year:'2021'},
20
+ * {fruit:'Pears',yield:18,year:'2020'},{fruit:'Pears',yield:19,year:'2021'}];
21
+ * ```
22
+ *
23
+ * We would like to render this into a chart, say with points first:
24
+ *
25
+ * ```
26
+ * utils.vega.svg(
27
+ * // pass the iJavaScript variable of the current cell
28
+ * $$,
29
+ * // render as points
30
+ * utils.vega.markPoint()
31
+ * // use simpleData as the data source
32
+ * .data(simpleData)
33
+ * // title
34
+ * .title('Fruit by Yield')
35
+ * // this is where the x, and y are encoded
36
+ * .encode(
37
+ * // use the 'yield' property as the y axis
38
+ * // note this is fieldQ - a qualitative number
39
+ * utils.vega.y().fieldQ('yield'),
40
+ * // use the 'fruit' property as the x axis
41
+ * // note this is fieldN - a nominative string
42
+ * utils.vega.x().fieldN('fruit')
43
+ * )
44
+ * )
45
+ * ```
46
+ *
47
+ * ![Screenshot](img/FruitFruitByYield.png)
48
+ *
49
+ * Instead, let's separate out by year instead
50
+ *
51
+ * ```
52
+ * utils.vega.svg(
53
+ * $$,
54
+ * // change from `markPoint` to `markLine`
55
+ * utils.vega.markLine()
56
+ * .data(simpleData)
57
+ * .title('Fruit by Yield')
58
+ * // set the width of the graph
59
+ * .width(150)
60
+ * .encode(
61
+ * utils.vega.y().fieldQ('yield'),
62
+ * // change the field to 'year' from 'fruit'
63
+ * utils.vega.x().fieldN('year'),
64
+ * // add a new series coloration, using 'fruit'
65
+ * utils.vega.color().fieldN('fruit')
66
+ * )
67
+ * )
68
+ * ```
69
+ *
70
+ * ![Screenshot](img/FruitYearByYield.png)
71
+ *
72
+ * Other examples could use the `utils.datasets.fetch` for data
73
+ *
74
+ * ```
75
+ * utils.datasets.fetch('cars.json').then(d => cars = d);
76
+ * ```
77
+ *
78
+ * Then use transforms to only care about cylinders 4 and above:
79
+ *
80
+ * ```
81
+ * utils.vega.svg($$, utils.vega.markPoint()
82
+ * .data(cars)
83
+ * .title('Displacement vs Horsepower')
84
+ * .width(500)
85
+ * .height(500)
86
+ * .transform(
87
+ * utils.vega.filter('datum.Cylinders > 4')
88
+ * )
89
+ * .encode(
90
+ * utils.vega.x().fieldQ('Displacement'),
91
+ * utils.vega.y().fieldQ('Horsepower'),
92
+ * utils.vega.color().fieldN('Origin')
93
+ * .title('Car Origin')
94
+ * .scale({range:['green','red','blue']})
95
+ * )
96
+ * )
97
+ * ```
98
+ *
99
+ * ![Screenshot](img/CarsDisplacementByHorsepower.png)
100
+ *
101
+ * Types of fields:
102
+ * * fieldT (type: 'temporal') - time based
103
+ * * fieldN (type: 'nominal') - Represents a discrete category (string)
104
+ * * fieldQ (type: 'qualitative') - Represents a number
105
+ *
106
+ * You can also explicitly define the field like this:
107
+ *
108
+ * [See the Vega-Lite Axis Documentation](https://vega.github.io/vega-lite/docs/axis.html)
109
+ *
110
+ * ```
111
+ * utils.vega.svg($$, utils.vega.markPoint()
112
+ * .data(cars)
113
+ * .title('Displacement vs Horsepower')
114
+ * .width(500)
115
+ * .height(500)
116
+ * .transform(
117
+ * utils.vega.filter('datum.Cylinders > 4')
118
+ * )
119
+ * .encode(
120
+ * utils.vega.x({field:'Displacement', type:'quantitative'}),
121
+ * utils.vega.y({field:'Horsepower', type:'quantitative'}),
122
+ * utils.vega.color({
123
+ * field:'Origin', title:'Car Origin', type:'nominal',
124
+ * scale: {range: ['green', 'red', 'blue']
125
+ * }}
126
+ * )
127
+ * )
128
+ * )
129
+ * ```
130
+ *
131
+ * ![Screenshot](img/CarsDisplacementByHorsepower.png)
132
+ *
133
+ * other examples
134
+ *
135
+ * ## Bins
136
+ *
137
+ * ```
138
+ * utils.vega.svg($$,
139
+ * utils.vega.markCircle()
140
+ * .title('Binned Rotten Tomatoes Rating by IMDB Rating')
141
+ * .data(movies)
142
+ * .encode(
143
+ * utils.vega.x().fieldQ('Rotten Tomatoes Rating').bin({maxbins: 20}),
144
+ * utils.vega.y().fieldQ('IMDB Rating').bin({maxbins: 20}),
145
+ * utils.vega.size().count()
146
+ * ));
147
+ * ```
148
+ *
149
+ * ![Screenshot](img/MoviesRTbyIMDB.png)
150
+ *
151
+ * or
152
+ *
153
+ * ## Transformations
154
+ *
155
+ * ```
156
+ * utils.vega.svg($$,
157
+ * utils.vega.markBar()
158
+ * .title('Gross by Director')
159
+ * .width(400).height(400)
160
+ * .data(movies)
161
+ * .transform(
162
+ * utils.vega.filter('datum.Director != null'),
163
+ * utils.vega.aggregate(
164
+ * utils.vega.sum('Worldwide Gross').as('Gross')
165
+ * ).groupby('Director'),
166
+ * utils.vega.window(utils.vega.rank().as('Rank'))
167
+ * .sort(utils.vega.field('Gross').order('descending')),
168
+ * utils.vega.filter('datum.Rank < 20')
169
+ * )
170
+ * .encode(
171
+ * utils.vega.x().fieldQ('Gross'),
172
+ * utils.vega.y().fieldN('Director')
173
+ * .sort(utils.vega.field('Gross').order('descending'))
174
+ * ))
175
+ * ```
176
+ *
177
+ * ![Screenshot](img/MoviewGrossByDirector.png)
178
+ *
179
+ * -----
180
+ *
181
+ * * (see [@vega/vega-lite-api-v5 on observablehq](https://observablehq.com/@vega/vega-lite-api-v5) for a great introduction)
182
+ * * (see [vega-lite documentation](https://observablehq.com/@vega/vega-lite-api-v5) for deeper options)
183
+ *
184
+ * @module vega
185
+ */
186
+ const Vega = require('vega');
187
+ const VegaLite = require('vega-lite');
188
+ const VegaLiteApi = require('vega-lite-api');
189
+
190
+ const vl = VegaLiteApi.register(Vega, VegaLite, {
191
+ config: {
192
+ // vega-lite default configuration
193
+ config: {
194
+ view: { continuousWidth: 400, continuousHeight: 300 },
195
+ mark: { tooltip: null }
196
+ }
197
+ },
198
+ view: {
199
+ renderer: 'svg'
200
+ }
201
+ });
202
+
203
+ /**
204
+ * Renders an svg of a vega lite diagram.
205
+ *
206
+ * ObservableHQ has some great examples available here:
207
+ * [https://observablehq.com/@vega/vega-lite-api-v5](https://observablehq.com/@vega/vega-lite-api-v5)
208
+ *
209
+ * @method svg
210
+ * @param {Display} display - the iJavaScript Display.
211
+ * (Note: $$ refers to the current display within the iJavaScript kernel)
212
+ * See [the NEL documentation for more](http://n-riesco.github.io/ijavascript/doc/custom.ipynb.html#Setting-the-output-using-the-global-object-$$)
213
+ * @param {Object} vlInstance - the vega-lite instance
214
+ * (This is the vega-lite instance)
215
+ *
216
+ * @example
217
+ *
218
+ * vl.svg($$,
219
+ * vl.markCircle()
220
+ * .title('Binned Rotten Tomatoes Rating by IMDB Rating')
221
+ * .data(movies)
222
+ * .encode(
223
+ * vl.x().fieldQ('Rotten Tomatoes Rating').bin({maxbins: 20}),
224
+ * vl.y().fieldQ('IMDB Rating').bin({maxbins: 20}),
225
+ * vl.size().count()
226
+ * ));
227
+ */
228
+ const vegaLiteSvg = async (display, vlInstance) => {
229
+ const spec = vlInstance.toSpec();
230
+ const view = new Vega.View(Vega.parse(VegaLite.compile(spec).spec));
231
+ const svgText = await view.toSVG();
232
+ display.svg(svgText);
233
+ };
234
+ vl.svg = vegaLiteSvg.bind(vl);
235
+
236
+ vl.help = () => console.log(`
237
+ --
238
+ Helper for working with Vega-Lite within iJavaScript notebooks.
239
+ (see https://observablehq.com/@vega/vega-lite-api-v5)
240
+
241
+ Vega-Lite is a charting library that provides a great deal of flexibility
242
+ while also allowing for very simple use cases.
243
+
244
+ The Vega-Lite JavaScript API provides a convenient way to write Vega-Lite
245
+ specifications in a programmatic fashion.
246
+
247
+ utils.vega.svg($$, utils.vega.markPoint()
248
+ .data(cars)
249
+ .title('Displacement vs Horsepower')
250
+ .width(600)
251
+ .height(600)
252
+ .transform(
253
+ vl.filter('datum.Cylinders > 4')
254
+ )
255
+ .encode(
256
+ utils.vega.x().fieldQ('Displacement'),
257
+ utils.vega.y().fieldQ('Horsepower')
258
+ )
259
+ )
260
+
261
+ Types of fields:
262
+ * fieldT - time based
263
+ * fieldN - Nominal category
264
+ * fieldQ - qualitative number
265
+
266
+ You can also explicitly define the field like this:
267
+
268
+ utils.vega.svg( $$,
269
+ vl.markPoint()
270
+ .data(testExecution)
271
+ .width(500)
272
+ .encode(
273
+ vl.x().fieldQ('runtimeMinutes'),
274
+ vl.y({field:'classMethod', sort: '-x', axis: { labelLimit: 800}})
275
+ )
276
+ );
277
+
278
+ other examples
279
+
280
+ vl.svg($$,
281
+ vl.markCircle()
282
+ .title('Binned Rotten Tomatoes Rating by IMDB Rating')
283
+ .data(movies)
284
+ .encode(
285
+ vl.x().fieldQ('Rotten Tomatoes Rating').bin({maxbins: 20}),
286
+ vl.y().fieldQ('IMDB Rating').bin({maxbins: 20}),
287
+ vl.size().count()
288
+ ));
289
+
290
+ vl.svg($$,
291
+ vl.markBar()
292
+ .title('Gross by Director')
293
+ .width(400).height(400)
294
+ .data(movies)
295
+ .transform(
296
+ vl.filter('datum.Director != null'),
297
+ vl.aggregate(vl.sum('Worldwide Gross').as('Gross')).groupby('Director'),
298
+ vl.window(vl.rank().as('Rank')).sort(vl.field('Gross').order('descending')),
299
+ vl.filter('datum.Rank < 20')
300
+ )
301
+ .encode(
302
+ vl.x().fieldQ('Gross'),
303
+ vl.y().fieldN('Director').sort(vl.field('Gross').order('descending'))
304
+ ))
305
+ --
306
+ `);
307
+
308
+ module.exports = vl;