diff --git a/.gitignore b/.gitignore index df708bd605..8a4bd9b648 100644 --- a/.gitignore +++ b/.gitignore @@ -1,42 +1,80 @@ -*~ -*.pyc -*.iml -.idea/ -.metadata/ -.recommenders/ -.gradle/ -.settings/ -RemoteSystemsTempFiles/ -jupyter_contrib_nbextensions/ -Groovier-1.0.0.jar -jupyter-groovy-kernel.log -jupyter-groovy-kernel-1.0.0.jar -jupyter-groovy-kernel.log -.ipynb_checkpoints/ -/*.ipynb -!StartHere.ipynb -#.gitignore -/gradle* -beaker.egg-info/ +# BeakerX gitignore + +# General +lib/ +# Beaker +VERSION beakerx/static/ -beakerx.egg-info/ beakerx/beakerx/static/ beakerx/beakerx/kernel/ beakerx/beakerx/javadoc/ -beakerx/dist +beakerx/record.txt + +# Jupyter / iPython +/.project +jupyter_contrib_nbextensions/ +.ipynb_checkpoints/ +/*.ipynb +!StartHere.ipynb +# Gradle +.gradle/ +/gradle* kernel/build/ kernel/*/build/ /build/ -/.classpath -/.project /.nb-gradle/ .nb-gradle-properties +Groovier-1.0.0.jar +jupyter-groovy-kernel.log +jupyter-groovy-kernel-1.0.0.jar +jupyter-groovy-kernel.log + +# Java +/.classpath + +# Python +*.py[cod] __pycache__/ -beakerx/__pycache__/ -beakerx/plot/__pycache__/ +beakerx/dist +*.egg-info/ + +# Node js/bower_components/ -lib/ -beakerx/record.txt -VERSION + +# Ignore tags created by etags, ctags, gtags, or cscope +TAGS +.TAGS +.TAGS/ +tags +.tags +!tags/ +gtags.files +GTAGS +GRTAGS +GPATH +GSYMS +cscope.files +cscope.out +cscope.in.out +cscope.po.out + +# Emacs +*~ + +# Vim +[._]*.s[a-v][a-v] +[._]*.sw[a-p] +[._]*s[a-v][a-z] +[._]sw[a-p] + +# IntelliJ +.idea/ +.iml + +# Eclipse +.metadata/ +.settings/ +.recommenders/ +RemoteSystemsTempFiles/ diff --git a/README.md b/README.md index fb410b31c3..5516f58aa8 100644 --- a/README.md +++ b/README.md @@ -24,14 +24,14 @@ [](http://badge.fury.io/js/beakerx) [](http://badge.fury.io/py/beakerx) [](https://anaconda.org/conda-forge/beakerx) -[](https://mybinder.org/v2/gh/twosigma/beakerx/0.11.1?filepath=StartHere.ipynb) +[](https://mybinder.org/v2/gh/twosigma/beakerx/0.13.0?filepath=StartHere.ipynb) BeakerX is a collection of JVM kernels and interactive widgets for plotting, tables, autotranslation, and other extensions to Jupyter Notebook. BeakerX is in beta and under active development. The [documentation](https://github.com/twosigma/beakerx/blob/master/StartHere.ipynb) consists of tutorial notebooks on GitHub. -You can try it in the cloud for free with [Binder](https://mybinder.org/v2/gh/twosigma/beakerx/0.11.1?filepath=StartHere.ipynb). +You can try it in the cloud for free with [Binder](https://mybinder.org/v2/gh/twosigma/beakerx/0.13.0?filepath=StartHere.ipynb). BeakerX is the successor to the [Beaker Notebook (source code archive)](https://github.com/twosigma/beaker-notebook-archive). It @@ -55,6 +55,7 @@ how to install and run BeakerX. ``` conda create -y -n beakerx 'python>=3' nodejs pandas openjdk maven source activate beakerx +conda config --env --add pinned_packages 'openjdk>8.0.121' conda install -y -c conda-forge ipywidgets (cd beakerx; pip install -e . --verbose) beakerx install @@ -63,8 +64,9 @@ beakerx install ### Build and Install for Lab ``` -conda create -y -n labx 'python>=3' nodejs pandas openjdk maven pytest +conda create -y -n labx 'python>=3' nodejs pandas openjdk maven source activate labx +conda config --env --add pinned_packages 'openjdk>8.0.121' conda install -y -c conda-forge jupyterlab (cd beakerx; pip install -e . --verbose) beakerx install @@ -107,6 +109,83 @@ The Java unit tests are run with every build. See [test/README.md] for how to ru docker run -p 8888:8888 beakerx/beakerx ``` +## Architecture and Code Overview + +BeakerX is a collection of kernels and extensions for Jupyter. +The code is organized into subdirectories as follows: + +* [beakerx](beakerx) The Python packages. The main beakerx package has: + + * a customized KernelSpec to allow BeakerX to configure the JVMs + started to run the kernels, + + * the beakerx command line program, which has the bkr2ipynb + converter as well as install and uninstall functions, + + * the Python API for the runtime (tables, plots, easyform), + including automatically installing a displayer for pandas tables, + and autotranslation; + + * the webpack (compiled JavaScript, TypeScript, CSS, fonts, images); + and + + * the compiled Java JARs. + + There is a seperate python package (beakerx_magics) for the + `%%groovy` magic so it can always be loaded *without* loading the + regular beakerx package (which would turn on display of pandas + tables with our table widget). + +* [doc](doc) Documentation consisting of executable tutorial + notebooks. [StartHere.ipynb](StartHere.ipynb) at the top level + links to these and is the intended way to navigate them. There is a + subdirectory for each language. + +* [docker](docker) configuration files for creating the Docker image. + There is a subdirectory [doc/base](doc/base) for an image with + BeakerX's dependencies (the Ubuntu and conda packages). The main + image is built by compiling BeakerX and installing BeakerX in the + base image. + +* [js](js) There are two subdirectories of JavaScript and TypeScript, + [js/lab](js/lab) and [js/notebook](js/notebook). New code is being + written in TypeScript. + + The lab subdirectory has the extension for Jupyter Lab (distributed + by npm). Notebook has two extensions, one for the widgets (which + are included in Lab as well, and are also seperately distributed + with npm for embedded applications such as nbviewer), and one for + the notebook application. This adds a tab to the tree view with our + options panel. And for regular notebook pages the extension + handles: + + * running initialization cells, + + * publication, + + * autotranslation, + + * the getCodeCells and runByTag APIs, + + * callbacks for table and plot actions, + + * UI customizations such as changing the fonts, allowing wide code + cells, and disabling autosave. + +* [kernel](kernel) The Java implementation of the kernels is here. + The main directory is [kernel/base](kernel/base) which has generic + code for all the languages. The base kernel has classes for + Jupyter's Comm protocol (a layer over ZMQ), magics, the classpath + (including loading from maven), and the kernl parts of the widget + APIs. + + There is also a subdirectory for each language which has the + evaluator for that language, plus scala has wrappers for the widgets + so they have native types. + +* [test](test) The e2e tests, which are made with wdio (selenium, + chromedriver, jasmine). + ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). @@ -146,3 +225,4 @@ database engine (http://www.h2database.com/), which is dual licensed and available under the MPL 2.0 (Mozilla Public License) or under the EPL 1.0 (Eclipse Public License). An original copy of the license agreement can be found at: http://www.h2database.com/html/license.html + diff --git a/RELEASE.md b/RELEASE.md index d8ae6c9be4..a8ad9ee959 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -64,12 +64,11 @@ git clone https://github.com/twosigma/beakerx-feedstock.git cd beakerx-feedstock git remote add upstream https://github.com/conda-forge/beakerx-feedstock.git git fetch upstream -git checkout master -git reset --hard upstream/master +git reset --hard upstream/master git push origin master --force ``` - Update the `version` and `sha256` variable values in `recipe/meta.yaml`. - Return build number to 0. + Return build number to 1. Then test it locally: @@ -95,11 +94,11 @@ conda install --use-local beakerx Publish on npmjs ---------------- -To update the embedded version of our widget library: - -- Do a full build. -- Run `(cd js/notebook; npm publish)` -- Run `(cd js/lab; npm publish)` +To update the embedded version of our widget library, and our Lab extension: +``` +(cd js/notebook; npm publish) +(cd js/lab; npm publish) +``` Release to Docker Hub --------------------- diff --git a/StartHere.ipynb b/StartHere.ipynb index 6e5449b53a..a1b28caf9e 100644 --- a/StartHere.ipynb +++ b/StartHere.ipynb @@ -16,10 +16,13 @@ "[Groovy](doc/groovy/Groovy.ipynb), [Java](doc/java/Java.ipynb), [Scala](doc/scala/Scala.ipynb), [Clojure](doc/clojure/Clojure.ipynb), [SQL](doc/sql/Sql.ipynb), [Kotlin](doc/kotlin/Kotlin.ipynb).\n", "\n", "### Magics\n", - "[Timing](doc/groovy/TimingMagicCommands.ipynb), [Classpath and Imports](doc/groovy/ClasspathMagicCommands.ipynb), [Properties, Heap Size and other JVM parameters](doc/groovy/JavaArgs.ipynb), [Defining New Magics](doc/groovy/LoadMagicCommand.ipynb).\n", + "[Timing](doc/groovy/TimingMagicCommands.ipynb), [Classpath and Imports](doc/groovy/ClasspathMagicCommands.ipynb), [Defining New Magics](doc/groovy/LoadMagicCommand.ipynb).\n", + "\n", + "### Options Panels\n", + "[Properties, Heap Size, and other JVM Options](doc/groovy/JavaArgs.ipynb), [UI Options](doc/groovy/UIOptions.ipynb).\n", "\n", "### Autotranslation\n", - "[Python](doc/python/AutoTranslation.ipynb), [Groovy](doc/groovy/AutoTranslation.ipynb)\n", + "[Python](doc/python/AutoTranslation.ipynb), [Groovy](doc/groovy/AutoTranslation.ipynb).\n", "\n", "### Groovy Plotting and Charting\n", "[Example and Interaction](doc/groovy/Charting.ipynb), [Time Series and General APIs and Features](doc/groovy/PlotFeatures.ipynb), [Category Plots and Bar Charts](doc/groovy/CategoryPlot.ipynb), [Levels of Detail](doc/groovy/LevelsOfDetails.ipynb), [Histograms](doc/groovy/Histogram.ipynb), [Heatmaps](doc/groovy/Heatmap.ipynb), [Treemaps](doc/groovy/Treemap.ipynb), [Plot Actions](doc/groovy/PlotActions.ipynb), [Plot Seamless Updates](doc/groovy/PlotsPythonStyle.ipynb), [Second Y Axis](doc/groovy/2ndYaxis.ipynb).\n", @@ -37,12 +40,12 @@ "### Scala\n", "[Tables](doc/scala/TableAPI.ipynb), [Plotting](doc/scala/Plot.ipynb), [EasyForm](doc/scala/EasyForm.ipynb).\n", "\n", - "### Media Outputs and Displayer Customization\n", + "### Rich Outputs and Displayer Customization\n", "\n", - "[Media and MIME Outputs](doc/groovy/Mime.ipynb), [Display of Null](doc/groovy/showNullExecutionResult.ipynb), [Custom Displayers and `jvm-repr`](doc/groovy/JvmRepr.ipynb).\n", + "[Media and MIME Outputs](doc/groovy/Mime.ipynb), [Display of Null](doc/groovy/showNullExecutionResult.ipynb), [Custom Displayers and `jvm-repr`](doc/groovy/JvmRepr.ipynb).\n", "\n", "### Forms, Widgets, and Interaction\n", - "[EasyForm](doc/groovy/EasyForm.ipynb), [Output Containers and Layout Managers](doc/groovy/OutputContainers.ipynb), [Groovy interface to Jupyter JS Widgets](doc/groovy/JavaWidgets.ipynb), [Interactive recomputation](doc/groovy/Interactive.ipynb).\n", + "[EasyForm](doc/groovy/EasyForm.ipynb), [Output Widget](doc/groovy/Output.ipynb), [Output Containers and Layout Managers](doc/groovy/OutputContainers.ipynb), [Groovy interface to Jupyter JS Widgets](doc/groovy/JavaWidgets.ipynb), [Interactive recomputation](doc/groovy/Interactive.ipynb).\n", "\n", "### Automation\n", "[Progress Reporting API](doc/groovy/ProgressUpdateReporting.ipynb), [Initialization Cells](doc/python/InitCells.ipynb), [Get Code](doc/groovy/CodeCell.ipynb).\n", @@ -53,8 +56,8 @@ "### Spark\n", "[Spark](doc/scala/Spark.ipynb) cluster computing based on Scala, and the [Flint](doc/scala/Flint.ipynb) time series library.\n", "\n", - "### Deeplearning4j and DataVec\n", - "[DataVec, including automatic display](doc/groovy/DataVec.ipynb).\n", + "### More Integrations\n", + "[DataVec](doc/groovy/DataVec.ipynb) (DeepLearning4j), [STIL](doc/groovy/STIL.ipynb) (Starlink Tables Infrastructure Library).\n", "\n", "## Learn More\n", "On the web at the homepage [BeakerX.com](http://beakerx.com), on [GitHub](https://github.com/twosigma/beakerx), and on [Two Sigma's Open Source site](http://opensource.twosigma.com/).\n", diff --git a/beakerx/.gitignore b/beakerx/.gitignore index 5bdbab1586..399282cca8 100644 --- a/beakerx/.gitignore +++ b/beakerx/.gitignore @@ -1,5 +1,3 @@ /build/ /.classpath /.project -!/beakerx/static/tree.js -!/beakerx/static/img/ diff --git a/beakerx/beakerx/__init__.py b/beakerx/beakerx/__init__.py index b09dedbea2..bc4fc71795 100644 --- a/beakerx/beakerx/__init__.py +++ b/beakerx/beakerx/__init__.py @@ -47,4 +47,4 @@ def run(): parse() except KeyboardInterrupt: return 130 - return 0 \ No newline at end of file + return 0 diff --git a/beakerx/beakerx/_version.py b/beakerx/beakerx/_version.py index 0c4dee7e2d..18c636a902 100644 --- a/beakerx/beakerx/_version.py +++ b/beakerx/beakerx/_version.py @@ -1,2 +1,2 @@ -version_info = (0, 12, 0) +version_info = (0, 13, 0) __version__ = '.'.join(map(str, version_info)) diff --git a/beakerx/beakerx/beakerx_widgets.py b/beakerx/beakerx/beakerx_widgets.py index 00f1d2884a..1bd0c73428 100644 --- a/beakerx/beakerx/beakerx_widgets.py +++ b/beakerx/beakerx/beakerx_widgets.py @@ -12,12 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from ipywidgets import Box, DOMWidget, CoreWidget, Text, Label, Textarea, \ +from ipywidgets import Box, DOMWidget, CoreWidget, \ + Text, Label, Textarea, Password, \ Button, Widget, \ SelectMultiple, Select, Dropdown, Checkbox, HBox, \ VBox, RadioButtons, register, Layout, widget_serialization, HTML from ipywidgets.widgets.trait_types import InstanceDict -from traitlets import Int, Unicode, Dict, Bool, Union, List +from traitlets import Int, Unicode, Dict, Bool, Union, List, Any, observe from IPython.display import display import types @@ -45,6 +46,19 @@ def fireChanged(self, x=None): for f in self.onChangeListeners: f(x) + def set_value(self, new_value): + self.value = new_value + + def add_interface_to(target): + target.onInitListeners = list() + target.onChangeListeners = list() + target.onInit = types.MethodType(EasyFormComponent.onInit, target) + target.onChange = types.MethodType(EasyFormComponent.onChange, target) + target.fireInit = types.MethodType(EasyFormComponent.fireInit, target) + target.fireChanged = types.MethodType(EasyFormComponent.fireChanged, target) + target.set_value = types.MethodType(EasyFormComponent.set_value, target) + + class BeakerxLayout(Layout): _view_module = Unicode('@jupyter-widgets/base').tag(sync=True) @@ -147,6 +161,24 @@ def __init__(self, **kwargs): style = None +class BeakerxPassword(Password, EasyFormComponent): + def on_value_change(self, change): + self.fireChanged(change['new']) + + def __init__(self, **kwargs): + super(BeakerxPassword, self).__init__(**kwargs) + self.observe(self.on_value_change, names='value') + + _view_module = Unicode('beakerx').tag(sync=True) + _model_module = Unicode('beakerx').tag(sync=True) + _model_module_version = Unicode('*').tag(sync=True) + _view_module_version = Unicode('*').tag(sync=True) + + size = Int(default_value=-1).tag(sync=True) + layout = InstanceDict(BeakerxLayout).tag(sync=True, **widget_serialization) + style = None + + class BeakerxHTML(HTML, EasyFormComponent): def __init__(self, *args, **kwargs): super(BeakerxHTML, self).__init__(**kwargs) @@ -205,18 +237,28 @@ def __init__(self, **kwargs): _model_module_version = Unicode('*').tag(sync=True) _view_module_version = Unicode('*').tag(sync=True) editable = Bool(default_value=False).tag(sync=True) + value = Any(None, allow_none=True).tag(sync=True) original_options = Union([List(), Dict()]) style = None + def _update_options_list(self, new_value): + if new_value not in self.options: + self.options = self.original_options[:] + self.options += (new_value,) + self._options_values = tuple(tuple(self.options)) + def _handle_msg(self, msg): if 'value' in msg['content']['data']['state']: value = msg['content']['data']['state']['value'] - if msg['content']['data']['state']['value'] not in self.options: - self.options = self.original_options[:] - self.options += (msg['content']['data']['state']['value'],) + self._update_options_list(value) self.value = value super(BeakerxComboBox, self)._handle_msg(msg) + def set_value(self, value): + if self.editable: + self._update_options_list(value) + self.value = value + class BeakerxCheckbox(Checkbox, EasyFormComponent): def __init__(self, **kwargs): diff --git a/beakerx/beakerx/commands.py b/beakerx/beakerx/commands.py index 1ecc11ff74..5705a2368c 100644 --- a/beakerx/beakerx/commands.py +++ b/beakerx/beakerx/commands.py @@ -20,7 +20,7 @@ def install_subparser(subparser): install_parser = subparser.add_parser('install', help='installs BeakerX extensions') - install_parser.set_defaults(func = install) + install_parser.set_defaults(func=install) install_parser.add_argument("--prefix", help="location of the environment to install into", default=sys.prefix) @@ -28,7 +28,10 @@ def install_subparser(subparser): def uninstall_subparser(subparser): uninstall_parser = subparser.add_parser('uninstall', help='uninstalls BeakerX extensions') - uninstall_parser.set_defaults(func=lambda args : uninstall()) + uninstall_parser.set_defaults(func=uninstall) + uninstall_parser.add_argument("--prefix", + help="location of the environment to uninstall from", + default=sys.prefix) return subparser def bkr2ipynb_subparser(subparser): diff --git a/beakerx/beakerx/easyform/easyform.py b/beakerx/beakerx/easyform/easyform.py index d0fe566df6..ba8b36d5cb 100644 --- a/beakerx/beakerx/easyform/easyform.py +++ b/beakerx/beakerx/easyform/easyform.py @@ -44,6 +44,13 @@ def addTextField(self, *args, **kwargs): self.components[text.description] = text return text + def addPasswordField(self, *args, **kwargs): + password = BeakerxPassword(description=self.getDescription(args, kwargs)) + password.size = getValue(kwargs, 'width', -1) + self.children += (password,) + self.components[password.description] = password + return password + def addTextArea(self, *args, **kwargs): textarea = BeakerxTextArea( description=self.getDescription(args, kwargs)) @@ -142,6 +149,12 @@ def addRadioButtons(self, *args, **kwargs): self.components[radio_buttons.description] = radio_buttons return radio_buttons + def addWidget(self, name, widget): + EasyFormComponent.add_interface_to(widget) + self.children += (widget,) + self.components[name] = widget + return widget + def __iter__(self): return iter(self.components) @@ -158,7 +171,7 @@ def get(self, key): return "" def put(self, key, value): - self.components[key].value = value + self.components[key].set_value(value) @staticmethod def getDescription(args, kwargs): diff --git a/beakerx/beakerx/environment.py b/beakerx/beakerx/environment.py index 62302f080d..ac72e77f96 100644 --- a/beakerx/beakerx/environment.py +++ b/beakerx/beakerx/environment.py @@ -25,6 +25,13 @@ "heap_GB": null, "other": [], "properties": {} + }, + "ui_options": { + "auto_close": true, + "improve_fonts": true, + "wide_cells": true, + "show_publication": true, + "auto_save": true } } } diff --git a/beakerx/beakerx/handlers.py b/beakerx/beakerx/handlers.py index 39a2195e33..abd7c9f882 100644 --- a/beakerx/beakerx/handlers.py +++ b/beakerx/beakerx/handlers.py @@ -70,7 +70,7 @@ def load_jupyter_server_extension(nbapp): host_pattern = '.*$' settings_route_pattern = url_path_join(web_app.settings['base_url'], '/beakerx', '/settings') version_route_pattern = url_path_join(web_app.settings['base_url'], '/beakerx', '/version') - javadoc_route_pattern = url_path_join(web_app.settings['base_url'], '/beakerx', '/javadoc/(.*)') + javadoc_route_pattern = url_path_join(web_app.settings['base_url'], '/static', '/javadoc/(.*)') web_app.add_handlers(host_pattern, [(settings_route_pattern, SettingsHandler)]) web_app.add_handlers(host_pattern, [(version_route_pattern, VersionHandler)]) web_app.add_handlers(host_pattern, [(javadoc_route_pattern, JavaDoc)]) diff --git a/beakerx/beakerx/install.py b/beakerx/beakerx/install.py index 3057da1715..87bcc0a385 100644 --- a/beakerx/beakerx/install.py +++ b/beakerx/beakerx/install.py @@ -50,7 +50,7 @@ def _classpath_for(kernel): def _uninstall_nbextension(): subprocess.check_call(["jupyter", "nbextension", "disable", "beakerx", "--py", "--sys-prefix"]) subprocess.check_call(["jupyter", "nbextension", "uninstall", "beakerx", "--py", "--sys-prefix"]) - + subprocess.check_call(["jupyter", "serverextension", "disable", "beakerx", "--py", "--sys-prefix"]) def _install_nbextension(): if sys.platform == 'win32': @@ -116,17 +116,19 @@ def _uninstall_kernels(): uninstall_cmd = [ 'jupyter', 'kernelspec', 'remove', kernel, '-y', '-f' ] - subprocess.check_call(uninstall_cmd) + try: + subprocess.check_call(uninstall_cmd) + except subprocess.CalledProcessError: + pass #uninstal_cmd prints the appropriate message def _install_magics(): log.info("installing groovy magic for python...") dir_path = os.path.join(sys.prefix, 'etc', 'ipython') pathlib.Path(dir_path).mkdir(parents=True, exist_ok=True) - file = open(os.path.join(dir_path, 'ipython_config.py'), 'w+') - file.write("c = get_config()\n") - file.write("c.InteractiveShellApp.extensions = ['beakerx.groovy_magic']") - file.close() + with open(os.path.join(dir_path, 'ipython_config.py'), 'w+') as ipython_config: + ipython_config.write("c = get_config()\n") + ipython_config.write("c.InteractiveShellApp.extensions = ['beakerx_magics.groovy_magic']\n") def _set_conf_privileges(): config_path = os.path.join(paths.jupyter_config_dir(), 'beakerx.json') @@ -154,7 +156,7 @@ def _install_kernelspec_manager(prefix, disable=False): nb_app = cfg.setdefault("KernelSpecManager", {}) if disable and nb_app.get(KSMC, None) == CKSM: nb_app.pop(KSMC) - else: + elif not disable: nb_app.update({KSMC: CKSM}) log.debug("Writing config in {}...".format(path)) @@ -181,9 +183,10 @@ def make_parser(): return parser -def _disable_beakerx(): +def _disable_beakerx(args): _uninstall_nbextension() _uninstall_kernels() + _install_kernelspec_manager(args.prefix, disable=True) def _install_beakerx(args): @@ -199,8 +202,8 @@ def _install_beakerx(args): def install(args): _install_beakerx(args) -def uninstall(): - _disable_beakerx() +def uninstall(args): + _disable_beakerx(args) if __name__ == "__main__": diff --git a/beakerx/beakerx/static/custom/custom.css b/beakerx/beakerx/static/custom/custom.css index 58f55ce1c6..098e375306 100644 --- a/beakerx/beakerx/static/custom/custom.css +++ b/beakerx/beakerx/static/custom/custom.css @@ -46,10 +46,10 @@ font-weight: bold; } -.CodeMirror pre, -.rendered_html pre, -.rendered_html code, -.output_area pre { +.improveFonts .CodeMirror pre, +.improveFonts .rendered_html pre, +.improveFonts .rendered_html code, +.improveFonts .output_area pre { font-family: "Roboto Mono", monospace, sans-serif; } @@ -57,13 +57,13 @@ div.output_text { line-height: 1.3em; } -.widget-html-content, -.rendered_html, -.cm-header-1, -.cm-header-2, -.cm-header-3, -.cm-header-4, -.cm-header-5, -.cm-header-6 { +.improveFonts .widget-html-content, +.improveFonts .rendered_html, +.improveFonts .cm-header-1, +.improveFonts .cm-header-2, +.improveFonts .cm-header-3, +.improveFonts .cm-header-4, +.improveFonts .cm-header-5, +.improveFonts .cm-header-6 { font-family: "Lato", Helvetica, sans-serif; } diff --git a/beakerx/beakerx/static/html/settings_tab.html b/beakerx/beakerx/static/html/settings_tab.html deleted file mode 100644 index dcbd024e18..0000000000 --- a/beakerx/beakerx/static/html/settings_tab.html +++ /dev/null @@ -1,105 +0,0 @@ - -