├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── build.yml │ ├── check-release.yml │ ├── enforce-label.yml │ ├── prep-release.yml │ ├── publish-release.yml │ └── rtd-preview.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .readthedocs.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── RELEASE.md ├── docs ├── conf.py ├── environment.yml └── index.md ├── install.json ├── jupyterlite_p5_kernel └── __init__.py ├── lerna.json ├── package.json ├── packages ├── p5-kernel-extension │ ├── package.json │ ├── src │ │ ├── declarations.d.ts │ │ └── index.ts │ ├── style │ │ ├── base.css │ │ ├── icons │ │ │ └── p5js.png │ │ ├── index.css │ │ └── index.js │ └── tsconfig.json └── p5-kernel │ ├── package.json │ ├── src │ ├── index.ts │ └── kernel.ts │ ├── style │ ├── base.css │ ├── index.css │ └── index.js │ └── tsconfig.json ├── pyproject.toml ├── scripts └── bump-version.py ├── setup.py ├── style ├── base.css ├── index.css └── index.js ├── tsconfig.eslint.json ├── tsconfigbase.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | lint-staged.config.js 2 | .eslintrc.js 3 | scripts/serve.js 4 | 5 | .yarn-packages 6 | node_modules 7 | **/build 8 | **/lib 9 | **/node_modules 10 | **/mock_packages 11 | **/static 12 | **/typings 13 | **/schemas 14 | **/themes 15 | coverage 16 | *.map.js 17 | *.bundle.js 18 | docs/_build 19 | app/lab/extensions/ 20 | 21 | # jetbrains IDE stuff 22 | .idea/ 23 | 24 | # ms IDE stuff 25 | .history/ 26 | .vscode/ 27 | 28 | # JS templating 29 | bootstrap.js 30 | index.template.js 31 | config-utils.js 32 | 33 | docs 34 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'eslint:recommended', 4 | 'plugin:@typescript-eslint/eslint-recommended', 5 | 'plugin:@typescript-eslint/recommended', 6 | 'plugin:prettier/recommended' 7 | ], 8 | parser: '@typescript-eslint/parser', 9 | parserOptions: { 10 | project: 'tsconfig.eslint.json', 11 | sourceType: 'module' 12 | }, 13 | plugins: ['@typescript-eslint'], 14 | rules: { 15 | '@typescript-eslint/naming-convention': [ 16 | 'error', 17 | { 18 | selector: 'interface', 19 | format: ['PascalCase'], 20 | custom: { 21 | regex: '^I[A-Z]', 22 | match: true 23 | } 24 | } 25 | ], 26 | '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }], 27 | '@typescript-eslint/no-explicit-any': 'off', 28 | '@typescript-eslint/no-namespace': 'off', 29 | '@typescript-eslint/no-use-before-define': 'off', 30 | '@typescript-eslint/quotes': [ 31 | 'error', 32 | 'single', 33 | { avoidEscape: true, allowTemplateLiterals: false } 34 | ], 35 | curly: ['error', 'all'], 36 | eqeqeq: 'error', 37 | 'prefer-arrow-callback': 'error' 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: main 6 | pull_request: 7 | branches: '*' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: Base Setup 18 | uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 19 | 20 | - name: Install dependencies 21 | run: python -m pip install -U jupyterlab~=3.1 22 | 23 | - name: Lint the extension 24 | run: | 25 | set -eux 26 | jlpm 27 | jlpm run lint:check 28 | 29 | - name: Build the extension 30 | run: | 31 | set -eux 32 | python -m pip install .[test] 33 | 34 | jupyter labextension list 35 | jupyter labextension list 2>&1 | grep -ie "@jupyterlite/p5-kernel.*OK" 36 | 37 | - name: Package the extension 38 | run: | 39 | set -eux 40 | 41 | pip install build 42 | python -m build 43 | pip uninstall -y "jupyterlite_p5_kernel" jupyterlab 44 | 45 | - name: Upload extension packages 46 | uses: actions/upload-artifact@v3 47 | with: 48 | name: extension-artifacts 49 | path: dist/jupyterlite_p5_kernel* 50 | if-no-files-found: error 51 | 52 | test_isolated: 53 | needs: build 54 | runs-on: ubuntu-latest 55 | 56 | steps: 57 | - name: Checkout 58 | uses: actions/checkout@v3 59 | - name: Install Python 60 | uses: actions/setup-python@v4 61 | with: 62 | python-version: '3.9' 63 | architecture: 'x64' 64 | - uses: actions/download-artifact@v3 65 | with: 66 | name: extension-artifacts 67 | - name: Install and Test 68 | run: | 69 | set -eux 70 | # Remove NodeJS, twice to take care of system and locally installed node versions. 71 | sudo rm -rf $(which node) 72 | sudo rm -rf $(which node) 73 | 74 | pip install "jupyterlab~=3.1" jupyterlite_p5_kernel*.whl 75 | 76 | 77 | jupyter labextension list 78 | jupyter labextension list 2>&1 | grep -ie "@jupyterlite/p5-kernel.*OK" 79 | 80 | 81 | check_links: 82 | name: Check Links 83 | runs-on: ubuntu-latest 84 | timeout-minutes: 15 85 | steps: 86 | - uses: actions/checkout@v3 87 | - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 88 | - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 89 | with: 90 | ignore_links: "./lite/lab.*" 91 | -------------------------------------------------------------------------------- /.github/workflows/check-release.yml: -------------------------------------------------------------------------------- 1 | name: Check Release 2 | on: 3 | push: 4 | branches: ["main"] 5 | pull_request: 6 | branches: ["*"] 7 | 8 | jobs: 9 | check_release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | - name: Base Setup 15 | uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 16 | - name: Install Dependencies 17 | run: | 18 | pip install -e . 19 | - name: Check Release 20 | uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 21 | with: 22 | version_spec: 99.9.9 23 | token: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | - name: Upload Distributions 26 | uses: actions/upload-artifact@v3 27 | with: 28 | name: jupyterlite-p5-kernel-releaser-dist-${{ github.run_number }} 29 | path: .jupyter_releaser_checkout/dist 30 | -------------------------------------------------------------------------------- /.github/workflows/enforce-label.yml: -------------------------------------------------------------------------------- 1 | name: Enforce PR label 2 | 3 | on: 4 | pull_request: 5 | types: [labeled, unlabeled, opened, edited, synchronize] 6 | jobs: 7 | enforce-label: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | pull-requests: write 11 | steps: 12 | - name: enforce-triage-label 13 | uses: jupyterlab/maintainer-tools/.github/actions/enforce-label@v1 14 | -------------------------------------------------------------------------------- /.github/workflows/prep-release.yml: -------------------------------------------------------------------------------- 1 | name: "Step 1: Prep Release" 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | version_spec: 6 | description: "New Version Specifier" 7 | default: "next" 8 | required: false 9 | branch: 10 | description: "The branch to target" 11 | required: false 12 | post_version_spec: 13 | description: "Post Version Specifier" 14 | required: false 15 | since: 16 | description: "Use PRs with activity since this date or git reference" 17 | required: false 18 | since_last_stable: 19 | description: "Use PRs with activity since the last stable git tag" 20 | required: false 21 | type: boolean 22 | jobs: 23 | prep_release: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 27 | 28 | - name: Prep Release 29 | id: prep-release 30 | uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2 31 | with: 32 | token: ${{ secrets.ADMIN_GITHUB_TOKEN }} 33 | version_spec: ${{ github.event.inputs.version_spec }} 34 | post_version_spec: ${{ github.event.inputs.post_version_spec }} 35 | target: ${{ github.event.inputs.target }} 36 | branch: ${{ github.event.inputs.branch }} 37 | since: ${{ github.event.inputs.since }} 38 | since_last_stable: ${{ github.event.inputs.since_last_stable }} 39 | 40 | - name: "** Next Step **" 41 | run: | 42 | echo "Optional): Review Draft Release: ${{ steps.prep-release.outputs.release_url }}" 43 | -------------------------------------------------------------------------------- /.github/workflows/publish-release.yml: -------------------------------------------------------------------------------- 1 | name: "Step 2: Publish Release" 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | branch: 6 | description: "The target branch" 7 | required: false 8 | release_url: 9 | description: "The URL of the draft GitHub release" 10 | required: false 11 | steps_to_skip: 12 | description: "Comma separated list of steps to skip" 13 | required: false 14 | 15 | jobs: 16 | publish_release: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 20 | 21 | - name: Populate Release 22 | id: populate-release 23 | uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2 24 | with: 25 | token: ${{ secrets.ADMIN_GITHUB_TOKEN }} 26 | target: ${{ github.event.inputs.target }} 27 | branch: ${{ github.event.inputs.branch }} 28 | release_url: ${{ github.event.inputs.release_url }} 29 | steps_to_skip: ${{ github.event.inputs.steps_to_skip }} 30 | 31 | - name: Finalize Release 32 | id: finalize-release 33 | env: 34 | PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} 35 | PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }} 36 | TWINE_USERNAME: __token__ 37 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 38 | uses: jupyter-server/jupyter-releaser/.github/actions/finalize-release@v2 39 | with: 40 | token: ${{ secrets.ADMIN_GITHUB_TOKEN }} 41 | target: ${{ github.event.inputs.target }} 42 | release_url: ${{ steps.populate-release.outputs.release_url }} 43 | 44 | - name: "** Next Step **" 45 | if: ${{ success() }} 46 | run: | 47 | echo "Verify the final release" 48 | echo ${{ steps.finalize-release.outputs.release_url }} 49 | 50 | - name: "** Failure Message **" 51 | if: ${{ failure() }} 52 | run: | 53 | echo "Failed to Publish the Draft Release Url:" 54 | echo ${{ steps.populate-release.outputs.release_url }} 55 | -------------------------------------------------------------------------------- /.github/workflows/rtd-preview.yml: -------------------------------------------------------------------------------- 1 | name: RTD Preview 2 | on: 3 | pull_request_target: 4 | types: [opened] 5 | 6 | permissions: 7 | pull-requests: write 8 | 9 | jobs: 10 | binder: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Comment on the PR with the RTD preview 14 | uses: actions/github-script@v6 15 | with: 16 | github-token: ${{secrets.GITHUB_TOKEN}} 17 | script: | 18 | var PR_NUMBER = context.issue.number 19 | github.rest.issues.createComment({ 20 | issue_number: context.issue.number, 21 | owner: context.repo.owner, 22 | repo: context.repo.repo, 23 | body: `[![lite-badge](https://jupyterlite.rtfd.io/en/latest/_static/badge.svg)](https://jupyterlite-p5-kernel--${PR_NUMBER}.org.readthedocs.build/en/${PR_NUMBER}/_static/lab/index.html) :point_left: Try it on ReadTheDocs` 24 | }) 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bundle.* 2 | lib/ 3 | node_modules/ 4 | *.egg-info/ 5 | .ipynb_checkpoints 6 | *.tsbuildinfo 7 | jupyterlite_p5_kernel/labextension 8 | jupyterlite_p5_kernel/_version.py 9 | 10 | # Created by https://www.gitignore.io/api/python 11 | # Edit at https://www.gitignore.io/?templates=python 12 | 13 | ### Python ### 14 | # Byte-compiled / optimized / DLL files 15 | __pycache__/ 16 | *.py[cod] 17 | *$py.class 18 | 19 | # C extensions 20 | *.so 21 | 22 | # Distribution / packaging 23 | .Python 24 | build/ 25 | develop-eggs/ 26 | dist/ 27 | downloads/ 28 | eggs/ 29 | .eggs/ 30 | lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | wheels/ 36 | pip-wheel-metadata/ 37 | share/python-wheels/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | 48 | # Installer logs 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # Unit test / coverage reports 53 | htmlcov/ 54 | .tox/ 55 | .nox/ 56 | .coverage 57 | .coverage.* 58 | .cache 59 | nosetests.xml 60 | coverage.xml 61 | *.cover 62 | .hypothesis/ 63 | .pytest_cache/ 64 | 65 | # Translations 66 | *.mo 67 | *.pot 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # pyenv 79 | .python-version 80 | 81 | # celery beat schedule file 82 | celerybeat-schedule 83 | 84 | # SageMath parsed files 85 | *.sage.py 86 | 87 | # Spyder project settings 88 | .spyderproject 89 | .spyproject 90 | 91 | # Rope project settings 92 | .ropeproject 93 | 94 | # Mr Developer 95 | .mr.developer.cfg 96 | .project 97 | .pydevproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | .dmypy.json 105 | dmypy.json 106 | 107 | # Pyre type checker 108 | .pyre/ 109 | 110 | # End of https://www.gitignore.io/api/python 111 | 112 | # OSX files 113 | .DS_Store 114 | .vscode 115 | 116 | # JupyterLite 117 | *.doit* 118 | _output 119 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/node_modules 3 | **/lib 4 | **/package.json 5 | jupyterlite_p5_kernel 6 | docs 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "none", 4 | "arrowParens": "avoid" 5 | } 6 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: "ubuntu-20.04" 5 | tools: 6 | python: "mambaforge-4.10" 7 | 8 | conda: 9 | environment: docs/environment.yml 10 | 11 | sphinx: 12 | configuration: docs/conf.py 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | 5 | ## 0.1.1 6 | 7 | ([Full Changelog](https://github.com/jupyterlite/p5-kernel/compare/@jupyterlite/p5-kernel-extension@0.1.0...3dd4b3c779cdb12f4dde130eab2f6c95f9530e97)) 8 | 9 | ### Maintenance and upkeep improvements 10 | 11 | - Update to p5 1.5.0 [#23](https://github.com/jupyterlite/p5-kernel/pull/23) ([@jtpio](https://github.com/jtpio)) 12 | - Add releaser workflows [#22](https://github.com/jupyterlite/p5-kernel/pull/22) ([@jtpio](https://github.com/jtpio)) 13 | 14 | ### Documentation improvements 15 | 16 | - Use `mamba` to activate the environment [#21](https://github.com/jupyterlite/p5-kernel/pull/21) ([@jtpio](https://github.com/jtpio)) 17 | 18 | ### Contributors to this release 19 | 20 | ([GitHub contributors page for this release](https://github.com/jupyterlite/p5-kernel/graphs/contributors?from=2023-01-21&to=2023-02-10&type=c)) 21 | 22 | [@github-actions](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Agithub-actions+updated%3A2023-01-21..2023-02-10&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Ajtpio+updated%3A2023-01-21..2023-02-10&type=Issues) 23 | 24 | 25 | 26 | ## 0.1.0 27 | 28 | ([Full Changelog](https://github.com/jupyterlite/p5-kernel/compare/f45a8d32cbae40472fa1e0a0e9fcc8351486005b...27da1b9b7087582dde632dfb2627e45e615733f1)) 29 | 30 | ### New features added 31 | 32 | - Switch to a federated serverlite extension [#1](https://github.com/jupyterlite/p5-kernel/pull/1) ([@jtpio](https://github.com/jtpio)) 33 | 34 | ### Enhancements made 35 | 36 | - Update P5.js to version 1.4.2 [#15](https://github.com/jupyterlite/p5-kernel/pull/15) ([@M0JPI](https://github.com/M0JPI)) 37 | - Handle updating display data [#11](https://github.com/jupyterlite/p5-kernel/pull/11) ([@jtpio](https://github.com/jtpio)) 38 | 39 | ### Bugs fixed 40 | 41 | - Fix handling of the logo [#9](https://github.com/jupyterlite/p5-kernel/pull/9) ([@jtpio](https://github.com/jtpio)) 42 | 43 | ### Maintenance and upkeep improvements 44 | 45 | - Various maintenance tasks [#18](https://github.com/jupyterlite/p5-kernel/pull/18) ([@jtpio](https://github.com/jtpio)) 46 | - Fix links to the GitHub repo [#5](https://github.com/jupyterlite/p5-kernel/pull/5) ([@jtpio](https://github.com/jtpio)) 47 | - Use consistent naming for the lab extension [#4](https://github.com/jupyterlite/p5-kernel/pull/4) ([@jtpio](https://github.com/jtpio)) 48 | 49 | ### Documentation improvements 50 | 51 | - Add JupyterLite badge in the README.md [#20](https://github.com/jupyterlite/p5-kernel/pull/20) ([@jtpio](https://github.com/jtpio)) 52 | - Add config files for ReadTheDocs [#19](https://github.com/jupyterlite/p5-kernel/pull/19) ([@jtpio](https://github.com/jtpio)) 53 | - DOC: README.md: links, capitalization [#13](https://github.com/jupyterlite/p5-kernel/pull/13) ([@westurner](https://github.com/westurner)) 54 | - changed readme [#7](https://github.com/jupyterlite/p5-kernel/pull/7) ([@DerThorsten](https://github.com/DerThorsten)) 55 | 56 | ### Contributors to this release 57 | 58 | ([GitHub contributors page for this release](https://github.com/jupyterlite/p5-kernel/graphs/contributors?from=2021-09-29&to=2023-01-21&type=c)) 59 | 60 | [@bollwyvl](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Abollwyvl+updated%3A2021-09-29..2023-01-21&type=Issues) | [@DerThorsten](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3ADerThorsten+updated%3A2021-09-29..2023-01-21&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Ajtpio+updated%3A2021-09-29..2023-01-21&type=Issues) | [@M0JPI](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3AM0JPI+updated%3A2021-09-29..2023-01-21&type=Issues) | [@westurner](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Awesturner+updated%3A2021-09-29..2023-01-21&type=Issues) 61 | 62 | ## 0.1.0a12 63 | 64 | ([Full Changelog](https://github.com/jupyterlite/p5-kernel/compare/v0.1.0a11...a14b3b80924870e6eac71dd1982594df1cb102a2)) 65 | 66 | ### Bugs fixed 67 | 68 | - Fix handling of the logo [#9](https://github.com/jupyterlite/p5-kernel/pull/9) ([@jtpio](https://github.com/jtpio)) 69 | 70 | ### Documentation improvements 71 | 72 | - changed readme [#7](https://github.com/jupyterlite/p5-kernel/pull/7) ([@DerThorsten](https://github.com/DerThorsten)) 73 | 74 | ### Contributors to this release 75 | 76 | ([GitHub contributors page for this release](https://github.com/jupyterlite/p5-kernel/graphs/contributors?from=2021-10-01&to=2021-10-14&type=c)) 77 | 78 | [@DerThorsten](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3ADerThorsten+updated%3A2021-10-01..2021-10-14&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Ajtpio+updated%3A2021-10-01..2021-10-14&type=Issues) 79 | 80 | ## 0.1.0a11 81 | 82 | ([Full Changelog](https://github.com/jupyterlite/p5-kernel/compare/@jupyterlite/p5-kernel-extension@0.1.0-alpha.10...16bed8258f82806a188f070ee8024b16228dfdd4)) 83 | 84 | ### Maintenance and upkeep improvements 85 | 86 | - Fix links to the GitHub repo [#5](https://github.com/jupyterlite/p5-kernel/pull/5) ([@jtpio](https://github.com/jtpio)) 87 | - Use consistent naming for the lab extension [#4](https://github.com/jupyterlite/p5-kernel/pull/4) ([@jtpio](https://github.com/jtpio)) 88 | 89 | ### Contributors to this release 90 | 91 | ([GitHub contributors page for this release](https://github.com/jupyterlite/p5-kernel/graphs/contributors?from=2021-09-30&to=2021-10-01&type=c)) 92 | 93 | [@jtpio](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Ajtpio+updated%3A2021-09-30..2021-10-01&type=Issues) 94 | 95 | ## 0.1.0a10 96 | 97 | ([Full Changelog](https://github.com/jupyterlite/p5-kernel/compare/first-commit...b91d19f351a4e130a446bb45e0715d29aca24666)) 98 | 99 | ### New features added 100 | 101 | - Switch to a federated serverlite extension [#1](https://github.com/jupyterlite/p5-kernel/pull/1) ([@jtpio](https://github.com/jtpio)) 102 | 103 | ### Contributors to this release 104 | 105 | ([GitHub contributors page for this release](https://github.com/jupyterlite/p5-kernel/graphs/contributors?from=2021-09-29&to=2021-09-30&type=c)) 106 | 107 | [@bollwyvl](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Abollwyvl+updated%3A2021-09-29..2021-09-30&type=Issues) | [@jtpio](https://github.com/search?q=repo%3Ajupyterlite%2Fp5-kernel+involves%3Ajtpio+updated%3A2021-09-29..2021-09-30&type=Issues) 108 | 109 | ## 0.0.1 110 | 111 | Initial Version 112 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, JupyterLite Contributors All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | * Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jupyterlite-p5-kernel 2 | 3 | [![Github Actions Status](https://github.com/jupyterlite/p5-kernel/workflows/Build/badge.svg)](https://github.com/jupyterlite/p5-kernel/actions/workflows/build.yml) 4 | [![JupyterLite](https://jupyterlite.rtfd.io/en/latest/_static/badge-launch.svg)](https://jupyterlite-p5-kernel.readthedocs.io/en/latest/lite/lab) 5 | 6 | A p5.js kernel for JupyterLite. 7 | 8 | ![image](https://user-images.githubusercontent.com/591645/135318337-8e63861c-c598-48db-8c90-2c86d3a8936b.png) 9 | 10 | ## Requirements 11 | 12 | - [JupyterLite](https://github.com/jupyterlite/jupyterlite) `0.1.0b18+` 13 | 14 | ## Install 15 | 16 | This JupyterLite kernel can be installed as a federated server extension. 17 | 18 | ```bash 19 | # Install the kernel 20 | pip install jupyterlite-p5-kernel 21 | 22 | # Build a new JupyterLite site 23 | jupyter lite build 24 | ``` 25 | 26 | See the JupyterLite documentation for more information on how to build sites and include additional extensions: https://jupyterlite.readthedocs.io/en/latest/howto/index.html 27 | 28 | ## Uninstall 29 | 30 | ```bash 31 | pip uninstall jupyterlite-p5-kernel 32 | ``` 33 | 34 | ## Contributing 35 | 36 | ### Development install 37 | 38 | ```bash 39 | # Clone the repo to your local environment 40 | # Change directory to the fork directory 41 | 42 | # create a new enviroment 43 | mamba create --name jupyterlite-p5-kernel -c conda-forge python=3.9 yarn jupyterlab 44 | mamba activate jupyterlite-p5-kernel 45 | 46 | # Install package in development mode 47 | python -m pip install -e . 48 | 49 | # Link your development version of the extension with JupyterLab 50 | jlpm run install:extension 51 | 52 | # Rebuild the extension Typescript source after making changes 53 | jlpm run build 54 | ``` 55 | 56 | The extension should be linked to `PREFIX/share/jupyter/labextensions` and can be picked up by `jupyterlite`: 57 | 58 | ```bash 59 | # Install jupyterlite 60 | python -m pip install jupyterlite 61 | 62 | # Build a new JupyterLite site 63 | jupyter lite build 64 | 65 | # Serve the site 66 | jupyter lite serve 67 | 68 | # Launch a browser to the Jupyterlite server url 69 | python -m webbrowser http://localhost:8000/ 70 | ``` 71 | 72 | ## References 73 | 74 | ### p5.js 75 | 76 | - Processing > ProcessingJS > p5.js 77 | https://en.wikipedia.org/wiki/Processing#p5.js 78 | - https://github.com/processing/p5.js 79 | - https://p5js.org/learn/ 80 | - https://p5js.org/reference/ API docs 81 | - https://p5js.org/examples/ 82 | - https://p5js.org/examples/math-additive-wave.html 83 | - https://p5js.org/examples/interaction-wavemaker.html 84 | - https://p5js.org/examples/objects-objects.html 85 | - https://github.com/processing/p5.js/wiki/Beyond-the-canvas#creating-html-images 86 | - https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5#introducing-webgl-in-p5js 87 | - Summer of Code 88 | https://github.com/processing/p5.js/wiki#google-summer-of-code-and-processing-fellowships 89 | - Season of Docs 90 | https://github.com/processing/p5.js/wiki#season-of-docs 91 | 92 | #### p5.js Learning Resources 93 | 94 | - https://github.com/processing/p5.js/wiki/Educational-Resources 95 | - https://www.khanacademy.org/computing/computer-programming/pjs-documentation 96 | - https://www.khanacademy.org/computing/computer-programming/programming-games-visualizations/advanced-development-tools/a/using-processingjs-outside-khan-academy 97 | - Khan Academy > Computer Programming > "Intro to JS: Drawing & Animation" 98 | https://www.khanacademy.org/computing/computer-programming/programming 99 | - https://github.com/processing/p5.js/wiki/Processing-transition#overview-of-differences 100 | - https://github.com/processing/p5.js/wiki/p5.js-overview#how-is-this-different-than-processingjs 101 | - Khan Academy > Computing > Pixar in a Box 102 | https://www.khanacademy.org/computing/pixar 103 | - https://www.khanacademy.org/computing/pixar/simulation#hair-simulation-code 104 | - https://www.khanacademy.org/computing/pixar/pixar-rigging#code-character 105 | - https://en.wikipedia.org/wiki/Lorentz_transformation Rotation about a point other than the origin 106 | - https://en.wikipedia.org/wiki/Quaternion 107 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Making a new release of jupyterlite-p5-kernel 2 | 3 | ## Automated releases with the Jupyter Releaser 4 | 5 | The recommended way to make a relaase is to use the the Jupyter Releaser. 6 | 7 | Check out the [workflow documentation](https://github.com/jupyter-server/jupyter_releaser#typical-workflow) for more information. 8 | 9 | Here is a summary of the steps to cut a new release: 10 | 11 | - Fork the [`jupyter-releaser` repo](https://github.com/jupyter-server/jupyter_releaser) 12 | - Add `ADMIN_GITHUB_TOKEN`, `PYPI_TOKEN` and `NPM_TOKEN` to the Github Secrets in the fork 13 | - Go to the Actions panel 14 | - Run the "Draft Changelog" workflow 15 | - Merge the Changelog PR 16 | - Run the "Draft Release" workflow 17 | - Run the "Publish Release" workflow 18 | 19 | ## Publishing to `conda-forge` 20 | 21 | If the package is not on conda forge yet, check the documentation to learn how to add it: https://conda-forge.org/docs/maintainer/adding_pkgs.html 22 | 23 | Otherwise a bot should pick up the new version publish to PyPI, and open a new PR on the feedstock repository automatically. 24 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | extensions = ["myst_parser", "jupyterlite_sphinx"] 2 | 3 | master_doc = "index" 4 | source_suffix = ".md" 5 | 6 | # General information about the project. 7 | project = "JupyterLite p5 kernel" 8 | author = "JupyterLite Contributors" 9 | 10 | exclude_patterns = [] 11 | highlight_language = "python" 12 | pygments_style = "sphinx" 13 | 14 | html_theme = "pydata_sphinx_theme" 15 | html_static_path = ["_static"] 16 | 17 | html_css_files = ["custom.css"] 18 | -------------------------------------------------------------------------------- /docs/environment.yml: -------------------------------------------------------------------------------- 1 | name: jupyterlite-p5-kernel 2 | 3 | channels: 4 | - conda-forge 5 | 6 | dependencies: 7 | - build 8 | - python=3.10 9 | - mamba 10 | - pydata-sphinx-theme 11 | - myst-parser 12 | - ipywidgets>=8.0,<9 13 | - jupyterlab>=3.5.0,<4 14 | - nodejs=18 15 | - pip: 16 | - jupyterlite-sphinx 17 | - jupyterlite==0.1.0b17 18 | - .. -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ```{include} ../README.md 2 | ``` -------------------------------------------------------------------------------- /install.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageManager": "python", 3 | "packageName": "jupyterlite_p5_kernel", 4 | "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlite_p5_kernel" 5 | } 6 | -------------------------------------------------------------------------------- /jupyterlite_p5_kernel/__init__.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | 4 | from ._version import __version__ 5 | 6 | HERE = Path(__file__).parent.resolve() 7 | 8 | with (HERE / "labextension" / "package.json").open() as fid: 9 | data = json.load(fid) 10 | 11 | 12 | def _jupyter_labextension_paths(): 13 | return [{"src": "labextension", "dest": data["name"]}] 14 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "version": "0.1.1", 4 | "useWorkspaces": true 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jupyterlite/p5-kernel-root", 3 | "private": true, 4 | "version": "0.1.1", 5 | "keywords": [ 6 | "jupyter", 7 | "jupyterlab", 8 | "jupyterlab-extension" 9 | ], 10 | "homepage": "https://github.com/jupyterlite/p5-kernel", 11 | "bugs": { 12 | "url": "https://github.com/jupyterlite/p5-kernel/issues" 13 | }, 14 | "license": "BSD-3-Clause", 15 | "author": { 16 | "name": "JupyterLite Contributors", 17 | "email": "" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/jupyterlite/p5-kernel.git" 22 | }, 23 | "workspaces": { 24 | "packages": [ 25 | "packages/*" 26 | ] 27 | }, 28 | "scripts": { 29 | "build": "lerna run build", 30 | "build:prod": "lerna run build:prod", 31 | "build:test": "lerna run build:test", 32 | "bump:js:version": "lerna version --no-push --force-publish --no-git-tag-version --yes", 33 | "clean": "lerna run clean", 34 | "install": "lerna bootstrap", 35 | "install:dev": "yarn run build:prod && yarn run develop", 36 | "install:extension": "jupyter labextension develop --overwrite .", 37 | "eslint": "eslint . --ext .ts,.tsx --fix", 38 | "eslint:check": "eslint . --ext .ts,.tsx", 39 | "lint": "yarn run eslint && yarn run prettier", 40 | "lint:check": "yarn run eslint:check && yarn run prettier:check", 41 | "prettier": "prettier --write \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"", 42 | "prettier:check": "prettier --list-different \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"", 43 | "publish": "yarn run clean && yarn run build && lerna publish", 44 | "test": "lerna run test", 45 | "watch": "lerna run watch" 46 | }, 47 | "devDependencies": { 48 | "@typescript-eslint/eslint-plugin": "^4.32.0", 49 | "@typescript-eslint/parser": "^4.32.0", 50 | "eslint": "^7.32.0", 51 | "eslint-config-prettier": "^8.3.0", 52 | "eslint-plugin-prettier": "^4.0.0", 53 | "lerna": "^6.4.1", 54 | "lint-staged": "^10.4.0", 55 | "npm-run-all": "^4.1.5", 56 | "prettier": "^2.4.1", 57 | "rimraf": "^3.0.2", 58 | "shell-quote": "^1.7.2" 59 | } 60 | } -------------------------------------------------------------------------------- /packages/p5-kernel-extension/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jupyterlite/p5-kernel-extension", 3 | "version": "0.1.1", 4 | "description": "JupyterLite - p5.js Kernel Extension", 5 | "homepage": "https://github.com/jupyterlite/p5-kernel", 6 | "bugs": { 7 | "url": "https://github.com/jupyterlite/p5-kernel/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/jupyterlite/p5-kernel.git" 12 | }, 13 | "license": "BSD-3-Clause", 14 | "author": { 15 | "name": "JupyterLite Contributors", 16 | "email": "" 17 | }, 18 | "sideEffects": [ 19 | "style/*.css", 20 | "style/index.js" 21 | ], 22 | "main": "lib/index.js", 23 | "types": "lib/index.d.ts", 24 | "style": "style/index.css", 25 | "styleModule": "style/index.js", 26 | "directories": { 27 | "lib": "lib/" 28 | }, 29 | "files": [ 30 | "lib/*.d.ts", 31 | "lib/*.js.map", 32 | "lib/*.js", 33 | "style/*.css", 34 | "style/index.js" 35 | ], 36 | "scripts": { 37 | "build": "jlpm run build:lib && jlpm run build:labextension:dev", 38 | "build:labextension": "jupyter labextension build .", 39 | "build:labextension:dev": "jupyter labextension build --development True .", 40 | "build:lib": "tsc", 41 | "build:prod": "jlpm run build:lib && jlpm run build:labextension", 42 | "clean": "jlpm run clean:lib && jlpm run clean:labextension", 43 | "clean:labextension": "rimraf ../../jupyterlite_p5_kernel/labextension", 44 | "clean:lib": "rimraf lib tsconfig.tsbuildinfo", 45 | "eslint": "eslint . --ext .ts,.tsx --fix", 46 | "eslint:check": "eslint . --ext .ts,.tsx", 47 | "watch": "run-p watch:src watch:labextension", 48 | "watch:labextension": "jupyter labextension watch .", 49 | "watch:src": "tsc -w" 50 | }, 51 | "dependencies": { 52 | "@jupyterlite/kernel": "^0.1.0-beta.18", 53 | "@jupyterlite/p5-kernel": "^0.1.1", 54 | "@jupyterlite/server": "^0.1.0-beta.18" 55 | }, 56 | "devDependencies": { 57 | "@jupyterlab/builder": "^3.1.0", 58 | "rimraf": "~3.0.0", 59 | "typescript": "~4.2.3" 60 | }, 61 | "publishConfig": { 62 | "access": "public" 63 | }, 64 | "jupyterlab": { 65 | "extension": true, 66 | "outputDir": "../../jupyterlite_p5_kernel/labextension", 67 | "sharedPackages": { 68 | "@jupyterlite/kernel": { 69 | "bundled": false, 70 | "singleton": true 71 | } 72 | } 73 | }, 74 | "jupyterlite": { 75 | "liteExtension": true 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/p5-kernel-extension/src/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png' { 2 | const value: string; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /packages/p5-kernel-extension/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | import { PageConfig, URLExt } from '@jupyterlab/coreutils'; 5 | 6 | import { 7 | JupyterLiteServer, 8 | JupyterLiteServerPlugin 9 | } from '@jupyterlite/server'; 10 | 11 | import { IKernel, IKernelSpecs } from '@jupyterlite/kernel'; 12 | 13 | import { P5Kernel } from '@jupyterlite/p5-kernel'; 14 | 15 | import p5Logo from '../style/icons/p5js.png'; 16 | 17 | /** 18 | * The default CDN fallback for p5.js 19 | */ 20 | const P5_CDN_URL = 'https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js'; 21 | 22 | /** 23 | * A plugin to register the p5.js kernel. 24 | */ 25 | const kernel: JupyterLiteServerPlugin = { 26 | id: '@jupyterlite/p5-kernel-extension:kernel', 27 | autoStart: true, 28 | requires: [IKernelSpecs], 29 | activate: (app: JupyterLiteServer, kernelspecs: IKernelSpecs) => { 30 | const url = PageConfig.getOption('p5Url') || P5_CDN_URL; 31 | const p5Url = URLExt.isLocal(url) 32 | ? URLExt.join(window.location.origin, url) 33 | : url; 34 | kernelspecs.register({ 35 | spec: { 36 | name: 'p5js', 37 | display_name: 'p5.js', 38 | language: 'javascript', 39 | argv: [], 40 | spec: { 41 | argv: [], 42 | env: {}, 43 | display_name: 'p5.js', 44 | language: 'javascript', 45 | interrupt_mode: 'message', 46 | metadata: {} 47 | }, 48 | resources: { 49 | 'logo-32x32': 'TODO', 50 | 'logo-64x64': p5Logo 51 | } 52 | }, 53 | create: async (options: IKernel.IOptions): Promise => { 54 | return new P5Kernel({ 55 | ...options, 56 | p5Url 57 | }); 58 | } 59 | }); 60 | } 61 | }; 62 | 63 | const plugins: JupyterLiteServerPlugin[] = [kernel]; 64 | 65 | export default plugins; 66 | -------------------------------------------------------------------------------- /packages/p5-kernel-extension/style/base.css: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | -------------------------------------------------------------------------------- /packages/p5-kernel-extension/style/icons/p5js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyterlite/p5-kernel/fbda9a78adde48e7ed9012886c28f68c81e9270d/packages/p5-kernel-extension/style/icons/p5js.png -------------------------------------------------------------------------------- /packages/p5-kernel-extension/style/index.css: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | 6 | @import url('./base.css'); 7 | -------------------------------------------------------------------------------- /packages/p5-kernel-extension/style/index.js: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | 6 | import './base.css'; 7 | -------------------------------------------------------------------------------- /packages/p5-kernel-extension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfigbase", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../p5-kernel" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/p5-kernel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jupyterlite/p5-kernel", 3 | "version": "0.1.1", 4 | "description": "JupyterLite - p5.js Kernel", 5 | "homepage": "https://github.com/jupyterlite/p5-kernel", 6 | "bugs": { 7 | "url": "https://github.com/jupyterlite/p5-kernel/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/jupyterlite/p5-kernel.git" 12 | }, 13 | "license": "BSD-3-Clause", 14 | "author": { 15 | "name": "JupyterLite Contributors", 16 | "email": "" 17 | }, 18 | "sideEffects": [ 19 | "style/*.css", 20 | "style/index.js" 21 | ], 22 | "main": "lib/index.js", 23 | "types": "lib/index.d.ts", 24 | "style": "style/index.css", 25 | "directories": { 26 | "lib": "lib/" 27 | }, 28 | "files": [ 29 | "lib/*.d.ts", 30 | "lib/*.js.map", 31 | "lib/*.js", 32 | "style/*.css", 33 | "style/index.js" 34 | ], 35 | "scripts": { 36 | "build": "tsc -b", 37 | "build:prod": "tsc -b", 38 | "build:test": "tsc --build tsconfig.test.json", 39 | "clean": "rimraf lib && rimraf tsconfig.tsbuildinfo", 40 | "docs": "typedoc src", 41 | "prepublishOnly": "npm run build", 42 | "test": "jest", 43 | "test:cov": "jest --collect-coverage", 44 | "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand", 45 | "test:debug:watch": "node --inspect-brk node_modules/.bin/jest --runInBand --watch", 46 | "watch": "tsc -b --watch" 47 | }, 48 | "dependencies": { 49 | "@jupyterlite/kernel": "^0.1.0-beta.18" 50 | }, 51 | "devDependencies": { 52 | "@babel/core": "^7.11.6", 53 | "@babel/preset-env": "^7.12.1", 54 | "@jupyterlab/testutils": "~3.1.12", 55 | "@types/jest": "^26.0.10", 56 | "jest": "^26.4.2", 57 | "rimraf": "~3.0.0", 58 | "ts-jest": "^26.3.0", 59 | "typescript": "~4.2.3" 60 | }, 61 | "publishConfig": { 62 | "access": "public" 63 | }, 64 | "styleModule": "style/index.js" 65 | } 66 | -------------------------------------------------------------------------------- /packages/p5-kernel/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | export * from './kernel'; 5 | -------------------------------------------------------------------------------- /packages/p5-kernel/src/kernel.ts: -------------------------------------------------------------------------------- 1 | import { KernelMessage } from '@jupyterlab/services'; 2 | 3 | import { BaseKernel, IKernel } from '@jupyterlite/kernel'; 4 | 5 | import { PromiseDelegate } from '@lumino/coreutils'; 6 | 7 | /** 8 | * The mimetype for mime bundle results 9 | */ 10 | const MIME_TYPE = 'text/html-sandboxed'; 11 | 12 | /** 13 | * A kernel for making p5 sketches in the browser 14 | */ 15 | export class P5Kernel extends BaseKernel implements IKernel { 16 | /** 17 | * Instantiate a new P5Kernel. 18 | * 19 | * @param options The instantiation options for a new P5Kernel. 20 | */ 21 | constructor(options: P5Kernel.IOptions) { 22 | super(options); 23 | const { p5Url } = options; 24 | 25 | // use the kernel id as a display id 26 | this._displayId = this.id; 27 | 28 | // create the main IFrame 29 | this._iframe = document.createElement('iframe'); 30 | this._iframe.style.visibility = 'hidden'; 31 | this._iframe.style.position = 'absolute'; 32 | // position outside of the page 33 | this._iframe.style.top = '-100000px'; 34 | 35 | // p5 bootstrap code 36 | this._bootstrap = ` 37 | import('${p5Url}').then(() => { 38 | // create the p5 global instance 39 | window.__globalP5 = new p5(); 40 | return Promise.resolve(); 41 | }) 42 | `; 43 | 44 | this._iframe.onload = async () => { 45 | await this._initIFrame(); 46 | this._eval(this._bootstrap); 47 | this._ready.resolve(); 48 | window.addEventListener('message', (e: MessageEvent) => { 49 | const msg = e.data; 50 | if (msg.event === 'stream') { 51 | const content = msg as KernelMessage.IStreamMsg['content']; 52 | this.stream(content); 53 | } 54 | }); 55 | }; 56 | document.body.appendChild(this._iframe); 57 | } 58 | 59 | /** 60 | * A promise that is fulfilled when the kernel is ready. 61 | */ 62 | get ready(): Promise { 63 | return this._ready.promise; 64 | } 65 | 66 | /** 67 | * Dispose the kernel. 68 | */ 69 | dispose(): void { 70 | if (this.isDisposed) { 71 | return; 72 | } 73 | this._iframe.remove(); 74 | super.dispose(); 75 | } 76 | 77 | /** 78 | * Handle a kernel_info_request message 79 | */ 80 | async kernelInfoRequest(): Promise { 81 | const content: KernelMessage.IInfoReply = { 82 | implementation: 'p5.js', 83 | implementation_version: '0.1.0', 84 | language_info: { 85 | codemirror_mode: { 86 | name: 'javascript' 87 | }, 88 | file_extension: '.js', 89 | mimetype: 'text/javascript', 90 | name: 'p5js', 91 | nbconvert_exporter: 'javascript', 92 | pygments_lexer: 'javascript', 93 | version: 'es2017' 94 | }, 95 | protocol_version: '5.3', 96 | status: 'ok', 97 | banner: 'A p5.js kernel', 98 | help_links: [ 99 | { 100 | text: 'p5.js Kernel', 101 | url: 'https://github.com/jupyterlite/p5-kernel' 102 | } 103 | ] 104 | }; 105 | return content; 106 | } 107 | 108 | /** 109 | * Handle an `execute_request` message 110 | * 111 | * @param msg The parent message. 112 | */ 113 | async executeRequest( 114 | content: KernelMessage.IExecuteRequestMsg['content'] 115 | ): Promise { 116 | const { code } = content; 117 | const transient = { 118 | display_id: this._displayId 119 | }; 120 | // handle magics first 121 | if (code.startsWith('%show')) { 122 | const magics = await this._magics(code); 123 | const res = { 124 | ...magics, 125 | transient 126 | }; 127 | if (res) { 128 | this.displayData(res); 129 | this._parentHeaders.push(this['_parentHeader']); 130 | 131 | return { 132 | status: 'ok', 133 | execution_count: this.executionCount, 134 | user_expressions: {} 135 | }; 136 | } 137 | } 138 | 139 | try { 140 | const result = this._eval(code); 141 | 142 | this.publishExecuteResult({ 143 | execution_count: this.executionCount, 144 | data: { 145 | 'text/plain': result 146 | }, 147 | metadata: {} 148 | }); 149 | 150 | // only store the input if the execution is successful 151 | if (!code.trim().startsWith('%')) { 152 | this._inputs.push(code); 153 | } 154 | 155 | // update existing displays since the executed code might affect the rendering 156 | // of existing sketches 157 | 158 | const magics = await this._magics(); 159 | const { data, metadata } = magics; 160 | this._parentHeaders.forEach(h => { 161 | this.clearOutput({ wait: false }); 162 | this.updateDisplayData( 163 | { 164 | data, 165 | metadata, 166 | transient 167 | }, 168 | h 169 | ); 170 | }); 171 | 172 | return { 173 | status: 'ok', 174 | execution_count: this.executionCount, 175 | user_expressions: {} 176 | }; 177 | } catch (e) { 178 | const { name, stack, message } = e as any as Error; 179 | 180 | this.publishExecuteError({ 181 | ename: name, 182 | evalue: message, 183 | traceback: [`${stack}`] 184 | }); 185 | 186 | return { 187 | status: 'error', 188 | execution_count: this.executionCount, 189 | ename: name, 190 | evalue: message, 191 | traceback: [`${stack}`] 192 | }; 193 | } 194 | } 195 | 196 | /** 197 | * Handle an complete_request message 198 | * 199 | * @param msg The parent message. 200 | */ 201 | async completeRequest( 202 | content: KernelMessage.ICompleteRequestMsg['content'] 203 | ): Promise { 204 | // naive completion on window names only 205 | // TODO: improve and move logic to the iframe 206 | const vars = this._evalFunc( 207 | this._iframe.contentWindow, 208 | 'Object.keys(window)' 209 | ) as string[]; 210 | const { code, cursor_pos } = content; 211 | const words = code.slice(0, cursor_pos).match(/(\w+)$/) ?? []; 212 | const word = words[0] ?? ''; 213 | const matches = vars.filter(v => v.startsWith(word)); 214 | 215 | return { 216 | matches, 217 | cursor_start: cursor_pos - word.length, 218 | cursor_end: cursor_pos, 219 | metadata: {}, 220 | status: 'ok' 221 | }; 222 | } 223 | 224 | async inspectRequest( 225 | content: KernelMessage.IInspectRequestMsg['content'] 226 | ): Promise { 227 | throw new Error('not implemented'); 228 | } 229 | 230 | async isCompleteRequest( 231 | content: KernelMessage.IIsCompleteRequestMsg['content'] 232 | ): Promise { 233 | throw new Error('not implemented'); 234 | } 235 | 236 | async commInfoRequest( 237 | content: KernelMessage.ICommInfoRequestMsg['content'] 238 | ): Promise { 239 | throw new Error('not implemented'); 240 | } 241 | 242 | inputReply(content: KernelMessage.IInputReplyMsg['content']): void { 243 | throw new Error('not implemented'); 244 | } 245 | 246 | async commOpen(msg: KernelMessage.ICommOpenMsg): Promise { 247 | throw new Error('not implemented'); 248 | } 249 | 250 | async commMsg(msg: KernelMessage.ICommMsgMsg): Promise { 251 | throw new Error('not implemented'); 252 | } 253 | 254 | async commClose(msg: KernelMessage.ICommCloseMsg): Promise { 255 | throw new Error('not implemented'); 256 | } 257 | 258 | /** 259 | * Execute code in the kernel IFrame. 260 | * 261 | * @param code The code to execute. 262 | */ 263 | protected _eval(code: string): string { 264 | return this._evalFunc(this._iframe.contentWindow, code); 265 | } 266 | 267 | /** 268 | * Handle magics coming from execute requests. 269 | * 270 | * @param code The code block to handle. 271 | */ 272 | private async _magics( 273 | code = '' 274 | ): Promise { 275 | const input = this._inputs 276 | .map(c => { 277 | const exec = ['try {', `window.eval(\`${c}\`);`, '} catch(e) {}'].join( 278 | '\n' 279 | ); 280 | return exec; 281 | }) 282 | .join('\n'); 283 | const script = ` 284 | ${this._bootstrap}.then(() => { 285 | ${input} 286 | window.__globalP5._start(); 287 | }) 288 | `; 289 | 290 | // add metadata 291 | const re = /^%show(?: (.+)\s+(.+))?\s*$/; 292 | const matches = code.match(re); 293 | const width = matches?.[1] ?? undefined; 294 | const height = matches?.[2] ?? undefined; 295 | return { 296 | execution_count: this.executionCount, 297 | data: { 298 | [MIME_TYPE]: [ 299 | '', 300 | ``, 301 | '' 302 | ].join('\n') 303 | }, 304 | metadata: { 305 | [MIME_TYPE]: { 306 | width, 307 | height 308 | } 309 | } 310 | }; 311 | } 312 | 313 | /** 314 | * Create a new IFrame 315 | * 316 | * @param iframe The IFrame to initialize. 317 | */ 318 | protected async _initIFrame(): Promise { 319 | if (!this._iframe.contentWindow) { 320 | return; 321 | } 322 | this._evalFunc( 323 | this._iframe.contentWindow, 324 | ` 325 | console._log = console.log; 326 | console._error = console.error; 327 | window._bubbleUp = function(msg) { 328 | window.parent.postMessage(msg); 329 | } 330 | console.log = function() { 331 | const args = Array.prototype.slice.call(arguments); 332 | window._bubbleUp({ 333 | "event": "stream", 334 | "name": "stdout", 335 | "text": args.join(' ') + '\\n' 336 | }); 337 | }; 338 | console.info = console.log; 339 | console.error = function() { 340 | const args = Array.prototype.slice.call(arguments); 341 | window._bubbleUp({ 342 | "event": "stream", 343 | "name": "stderr", 344 | "text": args.join(' ') + '\\n' 345 | }); 346 | }; 347 | console.warn = console.error; 348 | window.onerror = function(message, source, lineno, colno, error) { 349 | console.error(message); 350 | } 351 | ` 352 | ); 353 | } 354 | 355 | private _displayId = ''; 356 | private _bootstrap = ''; 357 | private _iframe: HTMLIFrameElement; 358 | private _evalFunc = new Function( 359 | 'window', 360 | 'code', 361 | 'return window.eval(code);' 362 | ); 363 | private _inputs: string[] = []; 364 | private _ready = new PromiseDelegate(); 365 | private _parentHeaders: KernelMessage.IHeader[] = 366 | []; 367 | } 368 | 369 | /** 370 | * A namespace for P5Kernel statics. 371 | */ 372 | export namespace P5Kernel { 373 | /** 374 | * The instantiation options for a P5Kernel 375 | */ 376 | export interface IOptions extends IKernel.IOptions { 377 | /** 378 | * The URL to fetch p5.js 379 | */ 380 | p5Url: string; 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /packages/p5-kernel/style/base.css: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | -------------------------------------------------------------------------------- /packages/p5-kernel/style/index.css: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | 6 | @import url('./base.css'); 7 | -------------------------------------------------------------------------------- /packages/p5-kernel/style/index.js: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | | Copyright (c) Jupyter Development Team. 3 | | Distributed under the terms of the Modified BSD License. 4 | |----------------------------------------------------------------------------*/ 5 | 6 | import './base.css'; 7 | -------------------------------------------------------------------------------- /packages/p5-kernel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfigbase", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling>=1.4.0", "jupyterlab>=3.4.7,<4.0.0", "hatch-nodejs-version"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "jupyterlite-p5-kernel" 7 | readme = "README.md" 8 | license = { file = "LICENSE" } 9 | requires-python = ">=3.7" 10 | classifiers = [ 11 | "Framework :: Jupyter", 12 | "License :: OSI Approved :: BSD License", 13 | "Programming Language :: Python", 14 | "Programming Language :: Python :: 3", 15 | "Programming Language :: Python :: 3.7", 16 | "Programming Language :: Python :: 3.8", 17 | "Programming Language :: Python :: 3.9", 18 | "Programming Language :: Python :: 3.10", 19 | "Programming Language :: Python :: 3.11", 20 | ] 21 | dependencies = [] 22 | dynamic = ["version", "description", "authors", "urls", "keywords"] 23 | 24 | [tool.hatch.version] 25 | source = "nodejs" 26 | 27 | [tool.hatch.metadata.hooks.nodejs] 28 | fields = ["description", "authors", "urls"] 29 | 30 | [tool.hatch.build.targets.sdist] 31 | artifacts = ["jupyterlite_p5_kernel/labextension"] 32 | exclude = [".github", ".binder"] 33 | 34 | [tool.hatch.build.targets.wheel.shared-data] 35 | "jupyterlite_p5_kernel/labextension" = "share/jupyter/labextensions/@jupyterlite/p5-kernel" 36 | "install.json" = "share/jupyter/labextensions/@jupyterlite/p5-kernel/install.json" 37 | 38 | [tool.hatch.build.hooks.version] 39 | path = "jupyterlite_p5_kernel/_version.py" 40 | 41 | [tool.hatch.build.hooks.jupyter-builder] 42 | dependencies = ["hatch-jupyter-builder>=0.5"] 43 | build-function = "hatch_jupyter_builder.npm_builder" 44 | ensured-targets = [ 45 | "jupyterlite_p5_kernel/labextension/static/style.js", 46 | "jupyterlite_p5_kernel/labextension/package.json", 47 | ] 48 | skip-if-exists = ["jupyterlite_p5_kernel/labextension/static/style.js"] 49 | 50 | [tool.hatch.build.hooks.jupyter-builder.build-kwargs] 51 | build_cmd = "build:prod" 52 | npm = ["jlpm"] 53 | 54 | [tool.hatch.build.hooks.jupyter-builder.editable-build-kwargs] 55 | build_cmd = "install:extension" 56 | npm = ["jlpm"] 57 | source_dir = "src" 58 | build_dir = "jupyterlite_p5_kernel/labextension" 59 | 60 | [tool.jupyter-releaser.options] 61 | version_cmd = "python scripts/bump-version.py" 62 | 63 | [tool.jupyter-releaser.hooks] 64 | before-bump-version = ["python -m pip install jupyterlab~=3.1"] 65 | before-build-npm = ["python -m pip install jupyterlab~=3.1", "jlpm", "jlpm build:prod"] 66 | before-build-python = ["jlpm clean"] 67 | 68 | [tool.check-wheel-contents] 69 | ignore = ["W002"] 70 | -------------------------------------------------------------------------------- /scripts/bump-version.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | 4 | from pathlib import Path 5 | from subprocess import run 6 | 7 | parser = argparse.ArgumentParser() 8 | parser.add_argument("version") 9 | args = parser.parse_args() 10 | version = args.version 11 | 12 | run(f'jlpm run bump:js:version {version}', shell=True, check=True) 13 | 14 | root = Path(__file__).parent.parent 15 | version_file = root / "packages" / "p5-kernel-extension" / "package.json" 16 | package_file = root / "package.json" 17 | 18 | version_json = json.loads(version_file.read_text()) 19 | version = version_json["version"] 20 | 21 | package_json = json.loads(package_file.read_text()) 22 | package_json["version"] = version 23 | 24 | package_file.write_text(json.dumps(package_json, indent=2)) 25 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # setup.py shim for use with applications that require it. 2 | __import__("setuptools").setup() 3 | -------------------------------------------------------------------------------- /style/base.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyterlite/p5-kernel/fbda9a78adde48e7ed9012886c28f68c81e9270d/style/base.css -------------------------------------------------------------------------------- /style/index.css: -------------------------------------------------------------------------------- 1 | @import url('base.css'); 2 | -------------------------------------------------------------------------------- /style/index.js: -------------------------------------------------------------------------------- 1 | import './base.css'; 2 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfigbase", 3 | "include": ["packages/**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfigbase.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "composite": true, 5 | "declaration": true, 6 | "esModuleInterop": true, 7 | "incremental": true, 8 | "jsx": "react", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "noEmitOnError": true, 12 | "noImplicitAny": true, 13 | "noUnusedLocals": true, 14 | "preserveWatchOutput": true, 15 | "resolveJsonModule": true, 16 | "strict": true, 17 | "strictNullChecks": true, 18 | "target": "es2019", 19 | "types": [] 20 | } 21 | } 22 | --------------------------------------------------------------------------------