{"id":13701245,"url":"https://github.com/ines/juniper","last_synced_at":"2025-04-07T07:08:55.336Z","repository":{"id":44962743,"uuid":"131633800","full_name":"ines/juniper","owner":"ines","description":"🍇 Edit and execute code snippets in the browser using Jupyter kernels","archived":false,"fork":false,"pushed_at":"2019-04-10T15:00:46.000Z","size":372,"stargazers_count":223,"open_issues_count":9,"forks_count":36,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-31T06:01:55.764Z","etag":null,"topics":["binder","binderhub","ipython","javascript-library","jupyter","jupyter-notebook","jupyterlab","python","widget"],"latest_commit_sha":null,"homepage":"https://ines.github.io/juniper/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ines.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-30T18:46:44.000Z","updated_at":"2025-02-16T04:30:08.000Z","dependencies_parsed_at":"2022-07-13T14:00:31.450Z","dependency_job_id":null,"html_url":"https://github.com/ines/juniper","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fjuniper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fjuniper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fjuniper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ines%2Fjuniper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ines","download_url":"https://codeload.github.com/ines/juniper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608151,"owners_count":20965952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binder","binderhub","ipython","javascript-library","jupyter","jupyter-notebook","jupyterlab","python","widget"],"created_at":"2024-08-02T20:01:23.931Z","updated_at":"2025-04-07T07:08:55.301Z","avatar_url":"https://github.com/ines.png","language":"JavaScript","readme":"# Juniper: Edit and execute code snippets in the browser using Jupyter kernels\n\nJuniper is a lightweight JavaScript library for adding interactive, editable\nand runnable code snippets to any website. It uses\n[JupyterLab](https://github.com/jupyterlab/jupyterlab) components and\n[Binder](https://mybinder.org) (or your own self-hosted version of\n[BinderHub](https://github.com/jupyterhub/binderhub)) to launch Python, R or\nJulia environments based on a GitHub repository and an auto-built\nJupyter-enabled Docker image.\n\nThis project was heavily inspired by [Min RK](https://github.com/minrk)'s\n[Thebelab](https://github.com/minrk/thebelab) package – thanks for the great\nwork on this. It was also instrumental in helping me understand how JupyterLab\nworks under the hood. Also thanks to [Binder](https://mybinder.org) for making\ntheir great service available and allowing such a smooth integration.\n\n![juniper](https://user-images.githubusercontent.com/13643239/39436623-c367b108-4c9e-11e8-8749-08f4f162a7f1.gif)\n\n[![npm](https://img.shields.io/npm/v/juniper-js.svg?style=flat-square)](https://www.npmjs.com/package/juniper-js)\n[![GitHub](https://img.shields.io/github/release/ines/juniper/all.svg?style=flat-square)](https://github.com/ines/juniper)\n[![unpkg](https://img.shields.io/badge/unpkg-juniper.min.js-brightgreen.svg?style=flat-square)](https://unpkg.com/juniper-js)\n\n## Quickstart\n\nTo add interactive code widgets to your site, you'll need a GitHub repository\nwith a `requirements.txt` listing the packages you want to install in the\nenvironment. Using the repository, you can build a Docker image on\n[Binder](https://mybinder.org), which will provide the Jupyter kernels.\nWhen a user connects to the code widget, Binder will start up a Docker\ncontainer for them.\n\nYou'll also need to include [`juniper.min.js`](dist/juniper.min.js), add a\n`data-executable` attribute to elements containing code and initialise the\nmodule. See [the list of options](#options) for a full overview of the available\nsettings.\n\n```html\n\u003cpre data-executable\u003eprint('Hello world!')\u003c/pre\u003e\n```\n\n```javascript\nnew Juniper({\n    repo: 'username/repo'\n})\n```\n\n### Setting up the environment\n\nThe `requirements.txt` can either live in the repository root, or in a\nsubdirectory `binder`. It can include PyPi packages with version identifiers, as\nwell as URLs to installable packages. This lets us install both spaCy *and* the\nsmall English model via [its direct link](https://spacy.io/usage/models#download-pip):\n\n```txt\nspacy\u003e=2.0.11,\u003c3.0.0\nhttps://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz#egg=en_core_web_sm==2.0.0\n```\n\nI'd recommend running the very first build via the interface on the\n[Binder website](https://mybinder.org), as this gives you a detailed build log\nand feedback on whether everything worked as expected. Enter your repository\nURL, click \"launch\" and wait for it to install the dependencies and build the\nimage.\n\n![Binder](https://user-images.githubusercontent.com/13643239/39412757-a518d416-4c21-11e8-9dad-8b4cc14737bc.png)\n\nDepending on the requirements, building the initial Docker image may take a\nwhile. However, once it's built, launching a new container for each session will\nbe much faster.\n\nI've mostly been using Binder with Python environments, but it should also work\nnatively with R and Julia projects.For more details and examples, see the\n[`binder-examples`](https://github.com/binder-examples) repo or check out the\n[`jupyter-repo2docker`](https://github.com/jupyter/repo2docker) project, which\nlets you turn git repositories into Jupyter-enabled Docker images.\n\n## Using Juniper with existing markup\n\nJuniper is designed as a simple, drop-in script that you can add to your\nexisting markup – for example, your blog template or your package's API\ndocumentation.\n\n```diff\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eYour website\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n-       \u003cpre\u003e\n+       \u003cpre data-executable\u003e\n            print('hello world!')\n        \u003c/pre\u003e\n\n+       \u003cscript src=\"juniper.min.js\"\u003e\u003c/script\u003e\n+       \u003cscript\u003enew Juniper({ repo: 'ines/juniper' })\u003c/script\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nWhen initialised, `Juniper` will look for elements with the `data-executable` attribute, extract their contents and replace them with an interactive widget. This also means that if your users have JavaScript disabled, they'll still get to see the static code and no information is lost.\n\n### Customising the theme\n\nThe editable code widget is powered by [CodeMirror](https://codemirror.net) which offers flexible customisation, and a variety of [syntax themes](https://codemirror.net/demo/theme.html) (also see this [user-curated collection](https://github.com/FarhadG/code-mirror-themes)). Note that Juniper only ships with the `default` theme – so if you want to use a different one, you need to include its stylesheet separately. Make sure the theme name assigned via the setting matches the name used in the stylesheet, e.g. `monokai` and `.cm-s-monokai`.\n\n```diff\n\u003chead\u003e\n    \u003ctitle\u003eYour website\u003c/title\u003e\n+   \u003clink rel=\"stylesheet\" href=\"monokai.css\" /\u003e\n\u003c/head\u003e\n```\n\n```diff\nnew Juniper({\n    repo: 'ines/juniper',\n+   theme: 'monokai'\n})\n```\n\nYou can also change the theme of individual cells using the `data-theme` attribute:\n\n```html\n\u003cpre data-executable data-theme=\"cobalt\"\u003eprint('Cobalt theme!')\u003c/pre\u003e\n```\n\n## Options\n\nThe following options are available when initialising `Juniper`:\n\n| Name | Type | Description | Default |\n| --- | --- | --- | --- |\n| `repo` | string | Binder repository in the format `user/repo`. | - |\n| `branch` | string | Repository branch to use. | `'master'` |\n| `url` | string | URL of the binder deployment. | `'https://mybinder.org'` |\n| `kernelType` | string | Type of the kernel to start. | `'python3'` |\n| `defaultLang` | string | Default language for syntax highlighting. | `'python'` |\n| `defaultTheme` | string | Default [CodeMirror](https://codemirror.net) theme. (Don't forget to include the CSS!) | `'default'` |\n| `isolateCells` | boolean | Treat each sell as an independent, isolated example. If set to `false`, code from previous cells will be availabe in the current cell, just like in a Jupyer Notebook. | `true` |\n| `noAutoInit` | boolean | Don't initialise the cells on load. You then have to call the `renderCell` method manually on each element. | `false` |\n| `useStorage` | boolean | Experimental: Use the browser's `localStorage` to save the connection parameters. If the user navigates to a different page, the binder won't have to be requested from scratch. | `true` |\n| `storageKey` | string | Key used to save the parameters in the `localStorage`. Change this if you don't want your settings to clash with other sites using Juniper. | `'juniper'` |\n| `storageExpire` | number | Time in minutes after which parameters in the local storage expire. Ensures that Juniper reconnects if the connection isn't available anymore. | `60` |\n| `useBinder` | boolean | Use [Binder](https://mybinder.org) or another BinderHub deployment to request a kernel. If set to `false`, the `serverSettings` are passed to JupyterLab directly. Use at your own risk. | `true` |\n| `serverSettings` | object | Experimental: Use different server settings and connect to request a kernel from a notebook server. Can include a `baseUrl`, a `wsUrl` (websockets) and a `token`. | `{}` |\n| `eventName` | string | Name of the custom event dispatched for status updates. | `'juniper'` |\n| `msgLoading` | string | Text displayed after successful connection and before the response is ready. | `'Loading...'` |\n| `msgError` | string | Text displayed if connecting failed. | `'Connecting failed. Please reload and try again.'` |\n| `selector` | string | Element selector for code blocks. | `'[data-executable]'` |\n| `classNames` | object | Overwrite the class names for `cell`, `input`, `button` and `output`. | [see here](#customising-the-widget-style) |\n\n## Advanced Usage\n\n### Notebook mode vs. isolated cells\n\nBy default, Juniper treats all cells as independent and isolated code examples.\nIf you're used to working in Jupyter Notebooks, you might prefer splitting your\ncode into cells like this:\n\n```html\n\u003cpre data-excutable\u003e\nsome_variable = 'some value'\n\u003cpre\u003e\n\n\u003cpre data-excutable\u003e\nprint(some_variable)\n\u003cpre\u003e\n```\n\nWith the default settings, the above example will raise an error because\n`some_variable` isn't defined. However, if `isolateCells` is set to `false` in\nthe Juniper settings, the individual cells will be treated as a concurrent\nscript, just like a Jupyter Notebook.\n\n```diff\nnew Juniper({\n    repo: 'user/repo',\n+   isolateCells: false\n})\n```\n\n### Listening to events\n\nIn some cases, you might want to display additional information about the server\nstatus to the user. Juniper dispatches custom events along the way, which you\ncan catch by adding an event listener for `'juniper'` (or a custom name defined\nvia the `eventName` option):\n\n```javascript\ndocument.addEventListener('juniper', event =\u003e {\n    if (event.detail.status == 'failed') {\n        // do something here\n    }\n})\n```\n\nThe event status is available as `event.detail.status`. The following event\ntypes are dispatched:\n\n| Event | Description |\n| --- | --- |\n| `building` | Building the [Binder](https://mybinder.org) image. |\n| `server-ready` | The Binder server is ready. |\n| `ready` | The Binder image and session is ready. |\n| `executing` | Executing the user action, i.e. a click on the \"run\" button. |\n| `requesting-kernel` | Requesting a kernel from the Binder image. |\n| `failed` | Connecting to the server failed. |\n\n### Customising the widget style\n\nThe Juniper widget is kept fairly minimalistic, to make it easier to integrate\nand adjust. See [`juniper.css`](src/juniper.css) for the existing styles. The\nelements created in place of the original code block look like this:\n\n```html\n\u003cdiv class=\"juniper-cell\"\u003e\n    \u003cdiv class=\"juniper-input\"\u003e\n        \u003c!-- CodeMirror code widget --\u003e\n    \u003c/div\u003e\n    \u003cbutton class=\"juniper-button\"\u003erun\u003c/button\u003e\n    \u003cdiv class=\"juniper-output\"\u003e\n        \u003c!-- Jupyter output area widget --\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\nYou can also change the class names via the `classNames` setting – for example,\nlike this to implement a BEM-style scheme:\n\n```javascript\nnew Juniper({\n    repo: 'user/repo',\n    classNames: {\n        cell: 'c-juniper',\n        input: 'c-juniper__input',\n        button: 'c-juniper__button',\n        output: 'c-juniper__output'\n    }\n})\n```\n\nThe [CodeMirror](https://codemirror.net) widget is also exposed as\n`window.CodeMirror`, so you can add plugins and tweak the options.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fines%2Fjuniper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fines%2Fjuniper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fines%2Fjuniper/lists"}