Merge pull request #273 from juhasch/feature/reorg
[WIP] Restructure repository
@@ -1,2 +1,16 @@
|
||||
custom.js
|
||||
custom.css
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
.idea
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
IPython-contrib is licensed under the terms of the Modified BSD License (also
|
||||
known as New or Revised or 3-Clause BSD), as follows:
|
||||
|
||||
- Copyright (c) 2013-2014, IPython-contrib Developers
|
||||
- Copyright (c) 2013-2015, IPython-contrib Developers
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
Jupyter notebook extensions master branch
|
||||
Jupyter notebook extensions
|
||||
===========================
|
||||
This repository contains a collection of extensions that add functionality to the Jupyter notebook.
|
||||
These extensions are mostly written in Javascript and will be loaded locally in your Browser.
|
||||
|
||||
The IPython-contrib repository is maintained independently by a group of users and developers and not officially related to the IPython development team.
|
||||
The IPython-contrib repository is maintained independently by a group of users and developers and not officially related
|
||||
to the IPython development team.
|
||||
|
||||
The maturity of the provided extensions may vary, please create an issue if you encounter any problems.
|
||||
|
||||
@@ -20,19 +21,20 @@ IPython/Jupyter version support
|
||||
There are different branches of the notebook extensions in this repository.
|
||||
Please make sure you use the branch corresponding to your IPython/Jupyter version.
|
||||
|
||||
Overview
|
||||
===========================
|
||||
The repository is organized in different categories:
|
||||
|
||||
| Name | Description |
|
||||
|------------|-------------|
|
||||
| [usability](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#usability) | Additional functionality for the notebook |
|
||||
| [publishing](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#publishing) | Getting your notebooks out in the wild |
|
||||
| [styling](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#styling) | Styling schemes for different looks of the notebook |
|
||||
| [slidemode](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#slidemode) | Slideshow creation |
|
||||
| [testing](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki#testing) | Extensions in a early stage |
|
||||
|
||||
Documentation
|
||||
=============
|
||||
The extensions are documented in the Wiki. Please take a look [here](https://github.com/ipython-contrib/IPython-notebook-extensions/wiki)
|
||||
Some extensions are not documented. We encourage you to add documentation for them.
|
||||
|
||||
All extensions that are maintained and active have a markdown readme file for documentation and a yaml file to
|
||||
allow them being configured using the 'nbextensions' server extension.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
The simple case: You want to install the extensions as local user. Then, simply run `setup.py install` or install
|
||||
the conda package. The conda package can also be built by running `conda build IPython-notebook-extensions`,
|
||||
and then doing a `conda install nbextensions`.
|
||||
|
||||
For more complex installation scenarios, please look up the documentation for installing notebook extensions,
|
||||
server extensions, pre/postprocessors, and templates at the Jupyter homepage http://www.jupyter.org
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Configuration file for ipython-notebook.
|
||||
|
||||
from IPython.utils.path import get_ipython_dir
|
||||
import os
|
||||
import sys
|
||||
|
||||
ipythondir = get_ipython_dir()
|
||||
extensions = os.path.join(ipythondir,'extensions')
|
||||
sys.path.append( extensions )
|
||||
|
||||
c = get_config()
|
||||
c.NotebookApp.open_browser = False
|
||||
#c.IPKernelApp.ip = '127.0.0.1'
|
||||
#c.FileNotebookManager.notebook_dir = 'i:\\notebook'
|
||||
|
||||
c.NotebookApp.server_extensions = [ 'nbextensions' ]
|
||||
c.NotebookApp.extra_template_paths = [os.path.join(ipythondir,'templates') ]
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
// Example for custom.js
|
||||
|
||||
// we want strict javascript that fails on ambiguous syntax
|
||||
"use strict";
|
||||
|
||||
// activate extensions only after Notebook is initialized
|
||||
require(["base/js/events"], function (events) {
|
||||
events.on("app_initialized.NotebookApp", function () {
|
||||
/*
|
||||
* all exentensions from IPython-notebook-extensions, uncomment to activate
|
||||
*/
|
||||
|
||||
// PUBLISHING
|
||||
// IPython.load_extensions('publishing/nbviewer_theme/main')
|
||||
// IPython.load_extensions('publishing/gist_it')
|
||||
// IPython.load_extensions('publishing/nbconvert_button')
|
||||
// IPython.load_extensions('publishing/printview/main')
|
||||
// IPython.load_extensions('publishing/printviewmenu_button')
|
||||
|
||||
// SLIDEMODE
|
||||
// IPython.load_extensions('slidemode/main')
|
||||
|
||||
|
||||
// STYLING
|
||||
// IPython.load_extensions('styling/css_selector/main')
|
||||
|
||||
// TESTING
|
||||
// IPython.load_extensions('testing/hierarchical_collapse/main')
|
||||
|
||||
// USABILITY
|
||||
// IPython.load_extensions('usability/aspell/ipy-aspell')
|
||||
// IPython.load_extensions('usability/codefolding/main')
|
||||
// IPython.load_extensions('usability/dragdrop/drag-and-drop')
|
||||
// IPython.load_extensions('usability/runtools/main')
|
||||
// IPython.load_extensions('usability/chrome_clipboard/main')
|
||||
// IPython.load_extensions('usability/navigation-hotkeys/main')
|
||||
// IPython.load_extensions('usability/toggle_all_line_number')
|
||||
// IPython.load_extensions('usability/help_panel/help_panel')
|
||||
// IPython.load_extensions('usability/hide_input/main')
|
||||
// IPython.load_extensions('usability/split-combine')
|
||||
// IPython.load_extensions('usability/read-only')
|
||||
// IPython.load_extensions('usability/init_cell/main')
|
||||
// IPython.load_extensions('usability/limit_output/main')
|
||||
// IPython.load_extensions('usability/autosavetime')
|
||||
// IPython.load_extensions('usability/autoscroll')
|
||||
// IPython.load_extensions('usability/breakpoints')
|
||||
// IPython.load_extensions('usability/clean_start')
|
||||
// IPython.load_extensions('usability/comment-uncomment')
|
||||
// IPython.load_extensions('usability/linenumbers')
|
||||
// IPython.load_extensions('usability/no_exec_dunder')
|
||||
// IPython.load_extensions('usability/noscroll')
|
||||
// IPython.load_extensions('usability/hide_io_selected')
|
||||
// IPython.load_extensions('usability/execute_time/ExecuteTime')
|
||||
// IPython.load_extensions('usability/python-markdown/main')
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ import json
|
||||
|
||||
jupyterdir = jupyter_data_dir()
|
||||
nbextension_dirs = (get_nbext_dir(), os.path.join(jupyterdir, 'nbextensions'))
|
||||
exclude = [ 'mathjax' ]
|
||||
exclude = ['mathjax']
|
||||
|
||||
|
||||
class NBExtensionHandler(IPythonHandler):
|
||||
@@ -83,8 +83,8 @@ class NBExtensionHandler(IPythonHandler):
|
||||
extension_list_json = json.dumps(extension_list)
|
||||
self.write(self.render_template(
|
||||
'nbextensions.html',
|
||||
base_url = self.base_url,
|
||||
extension_list = extension_list_json,
|
||||
base_url=self.base_url,
|
||||
extension_list=extension_list_json,
|
||||
page_title="Notebook Extension Configuration"
|
||||
))
|
||||
|
||||
@@ -94,9 +94,9 @@ class RenderExtensionHandler(IPythonHandler):
|
||||
@web.authenticated
|
||||
def get(self, path):
|
||||
self.write(self.render_template('rendermd.html',
|
||||
base_url = self.base_url,
|
||||
render_url = path,
|
||||
page_title = path,
|
||||
base_url=self.base_url,
|
||||
render_url=path,
|
||||
page_title=path,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""PostProcessor for embedding markdown images in HTML files."""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
import requests
|
||||
|
||||
from traitlets import Bool, Unicode, Int
|
||||
from nbconvert.postprocessors.base import PostProcessorBase
|
||||
|
||||
|
||||
class EmbedPostProcessor(PostProcessorBase):
|
||||
""" Post processor designed to embed images in markdown cells as base64 encoded blob in HTML file """
|
||||
|
||||
def replfunc(self, match):
|
||||
""" replace source url or file link with base64 encoded blob """
|
||||
url = match.group(1)
|
||||
imgformat = url.split('.')[-1]
|
||||
if url.startswith('http'):
|
||||
data = request.get(url)
|
||||
elif url.startswith('data'):
|
||||
img = '<img src="' + url + '" '+ match.group(2) + ' />'
|
||||
return img
|
||||
else:
|
||||
with open(url, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
self.log.info("embedding url: %s, format: %s" % (url, imgformat))
|
||||
b64_data=base64.b64encode(data).decode("utf-8")
|
||||
if imgformat == "svg":
|
||||
img = '<img src="data:image/svg+xml;base64,' + b64_data + '" ' + match.group(2) + '/>'
|
||||
elif imgformat == "pdf":
|
||||
img = '<img src="data:application/pdf;base64,' + b64_data + '" ' + match.group(2) + '/>'
|
||||
else:
|
||||
img = '<img src="data:image/'+imgformat+';base64,' + b64_data + '" '+ match.group(2) + ' />'
|
||||
return img
|
||||
|
||||
def postprocess(self, input):
|
||||
if self.config.export_format == "html":
|
||||
regex = re.compile('<img\s+src="(\S+)"\s*(\S*)\s*/>')
|
||||
ext = input.split('.')[-1]
|
||||
output=input[0:-(len(ext)+1)] + '-embedded.' + ext
|
||||
with open(input) as fin, open(output,'w') as fout:
|
||||
for line in fin:
|
||||
fout.write(regex.sub(self.replfunc,line))
|
||||
fin.close()
|
||||
fout.close()
|
||||
@@ -0,0 +1,9 @@
|
||||
from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.join(jupyter_data_dir(), 'extensions'))
|
||||
|
||||
c = get_config()
|
||||
c.Exporter.template_path = [os.path.join(jupyter_data_dir(), 'templates') ]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.join(jupyter_data_dir(), 'extensions'))
|
||||
|
||||
c = get_config()
|
||||
c.NotebookApp.extra_template_paths = [os.path.join(jupyter_data_dir(),'templates') ]
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package:
|
||||
name: nbextensions
|
||||
version: "master"
|
||||
|
||||
source:
|
||||
git_url: https://github.com/ipython-contrib/IPython-notebook-extensions
|
||||
git_tag: master
|
||||
|
||||
build:
|
||||
script: python setup.py install
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- ipython >=4
|
||||
- jupyter_client
|
||||
- jupyter_core
|
||||
- notebook
|
||||
- nbconvert
|
||||
- nbformat
|
||||
- python
|
||||
- traitlets
|
||||
|
||||
run:
|
||||
- ipython >=4
|
||||
- jupyter_client
|
||||
- jupyter_core
|
||||
- notebook
|
||||
- nbconvert
|
||||
- nbformat
|
||||
- python
|
||||
- traitlets
|
||||
- yaml
|
||||
|
||||
about:
|
||||
home: https://github.com/ipython-contrib/IPython-notebook-extensions
|
||||
license: Modified BSD License
|
||||
summary: 'Notebook extensions for the Jupyter/IPython notebook'
|
||||
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
@@ -388,9 +388,11 @@ require([
|
||||
// Activate/Deactivate buttons
|
||||
build_activate_buttons(ext_id).appendTo(col_left);
|
||||
var ext_url = get_ext_url(extension);
|
||||
var active = false;
|
||||
if (config.data.hasOwnProperty('load_extensions')) active = config.data.load_extensions[ext_url] === true
|
||||
set_buttons_active(
|
||||
ext_id,
|
||||
config.data.load_extensions[ext_url] === true
|
||||
active
|
||||
);
|
||||
|
||||
if (!extension.hasOwnProperty('Parameters')) continue;
|
||||
@@ -7,6 +7,38 @@ Activating an extension means it is loaded automatically when working with a not
|
||||
|
||||
If you encounter problems with this page, please create an issue at the [ipython-contrib](https://github.com/ipython-contrib/IPython-notebook-extensions) repository.
|
||||
|
||||
The documentation below is something you probably don't need to know, if you installed the conda package.
|
||||
If not, good luck!
|
||||
|
||||
## Now where in the world did everything go ?
|
||||
Jupyter/IPython 4.x works differently than IPython 3.x.
|
||||
|
||||
In short
|
||||
----
|
||||
* The notebook was split from IPython. You need to install both to run the notebook with IPython now. The easiest way is to use Anaconda and do a `conda install jupyter`
|
||||
* There are no profiles anymore. You can specify environment variables to change the default, see [Jupyter ML](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/jupyter/7q02jjksvFU)].
|
||||
* The configuration has moved to a new place. To find out where, see below.
|
||||
* There is a kind of automatic upgrade of the configuration files from IPython 3.x to Jupyter.
|
||||
|
||||
## So where can I find things now?
|
||||
To find where the configuration files are, start IPython
|
||||
```Python
|
||||
from __future__ import print_function
|
||||
from jupyter_core.paths import jupyter_config_dir, jupyter_config_path
|
||||
print(jupyter_config_dir())
|
||||
print(jupyter_config_path())
|
||||
```
|
||||
`jupyter_config_dir()` shows you where your *local* configuration files are, `jupyter_config_path` shows you where Jupyter will look for configuration files. For the notebook, there are two files that will be used:
|
||||
`jupyter_notebook_config.py` and `jupyter_notebook_config.json`.
|
||||
|
||||
The `nbextension` directory has moved to a different location and can be found in one of these directories:
|
||||
```Python
|
||||
from __future__ import print_function
|
||||
from jupyter_core.paths import jupyter_data_dir, jupyter_path
|
||||
print(jupyter_data_dir())
|
||||
print(jupyter_path())
|
||||
```
|
||||
|
||||
## Checking/loading notebook extension manually from IPython
|
||||
You can check if the directory or a file (or list of files) exists:
|
||||
```Python
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 424 KiB After Width: | Height: | Size: 424 KiB |
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 185 KiB |
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 252 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 210 KiB |
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
# Copyright (C) 2013
|
||||
|
||||
# Distributed under the terms of the BSD License. The full license is in
|
||||
# the file COPYING, distributed as part of this software.
|
||||
|
||||
@author: juhasch
|
||||
"""
|
||||
|
||||
"""
|
||||
Tornado web server to
|
||||
push value received from Pyzmq pull messages
|
||||
to web browser using a webscocket connection
|
||||
"""
|
||||
|
||||
import time
|
||||
import os.path
|
||||
|
||||
import tornado.web
|
||||
import tornado.websocket
|
||||
import tornado.ioloop
|
||||
|
||||
import random
|
||||
import json
|
||||
import aspell
|
||||
|
||||
from zmq.eventloop import ioloop, zmqstream
|
||||
|
||||
webport = 8989 # port address for web client
|
||||
|
||||
s = aspell.Speller('lang', 'en')
|
||||
|
||||
GLOBALS={
|
||||
'sockets': []
|
||||
}
|
||||
|
||||
class WebSocketHandler(tornado.websocket.WebSocketHandler):
|
||||
def open(self):
|
||||
print "open socket"
|
||||
GLOBALS['sockets'].append(self)
|
||||
|
||||
def on_close(self):
|
||||
print "on_close"
|
||||
GLOBALS['sockets'].remove(self)
|
||||
|
||||
def on_message(self, message):
|
||||
x=json.loads(message)
|
||||
text = x['text']
|
||||
reply = s.check(text)
|
||||
# reply to request:
|
||||
# check 1 for OK, 0 for not a valid word
|
||||
# id cell_id
|
||||
# line codemirror line number
|
||||
# start codemirror start position of word
|
||||
# stop codemirror end position of word
|
||||
reply = {"check": reply, "id" : x['id'], "line": x['line'],
|
||||
"start" : x['start'], "end": x['end'] }
|
||||
self.write_message(reply)
|
||||
|
||||
application = tornado.web.Application([
|
||||
(r"/websocket", WebSocketHandler),
|
||||
])
|
||||
|
||||
if __name__ == "__main__":
|
||||
ioloop.install()
|
||||
|
||||
application.listen(webport)
|
||||
main_loop = tornado.ioloop.IOLoop.instance()
|
||||
main_loop.start()
|
||||
print "Running"
|
||||
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -14,20 +14,31 @@ define([
|
||||
'jquery',
|
||||
'require',
|
||||
'base/js/events',
|
||||
'services/config',
|
||||
'base/js/utils',
|
||||
'codemirror/lib/codemirror',
|
||||
'codemirror/addon/fold/foldgutter',
|
||||
'codemirror/addon/fold/foldcode',
|
||||
'codemirror/addon/fold/brace-fold',
|
||||
'codemirror/addon/fold/indent-fold'
|
||||
], function(IPython, $, require, events, codemirror) {
|
||||
], function(IPython, $, require, events, configmod, utils, codemirror) {
|
||||
"use strict";
|
||||
if (IPython.version[0] < 3) {
|
||||
console.log("This extension requires IPython 3.x");
|
||||
return
|
||||
}
|
||||
|
||||
var foldingKey = { "Alt-F" : toggleFolding };
|
||||
|
||||
var HOTKEY = 'Alt-F';
|
||||
var foldingKey = { HOTKEY : toggleFolding };
|
||||
|
||||
var base_url = utils.get_body_data("baseUrl");
|
||||
var config = new configmod.ConfigSection('notebook', {base_url: base_url});
|
||||
config.load();
|
||||
|
||||
config.loaded.then(function() {
|
||||
if (config.data.hasOwnProperty('codefolding_hotkey') ){
|
||||
HOTKEY = config.data.codefolding_hotkey;
|
||||
foldingKey = {};
|
||||
foldingKey[HOTKEY] = toggleFolding;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Toggle folding on/off at current line
|
||||
*
|
||||
@@ -77,7 +88,8 @@ define([
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
if (cell.code_mirror != cm) {
|
||||
var cells = IPython.notebook.get_cells();
|
||||
for(var k in cells){
|
||||
var ncells = IPython.notebook.ncells();
|
||||
for(var k=0; k < ncells; k++){
|
||||
var _cell = cells[k];
|
||||
if (_cell.code_mirror == cm ) { break; }
|
||||
}
|
||||
@@ -93,13 +105,13 @@ define([
|
||||
function cellFolding(cell) {
|
||||
if (CodeMirror.fold != undefined) {
|
||||
var keys = cell.code_mirror.getOption('extraKeys');
|
||||
cell.code_mirror.setOption('extraKeys', collect(keys, foldingKey ));
|
||||
cell.code_mirror.setOption('extraKeys', collect(keys, foldingKey ));
|
||||
var mode = cell.code_mirror.getOption('mode');
|
||||
/* use indent folding in Python */
|
||||
if (mode.name == 'ipython' ) {
|
||||
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.magic, CodeMirror.fold.indent) });
|
||||
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.indent) });
|
||||
} else {
|
||||
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.magic, CodeMirror.fold.brace) });
|
||||
cell.code_mirror.setOption('foldGutter',{rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.firstline, CodeMirror.fold.brace) });
|
||||
}
|
||||
var gutters = cell.code_mirror.getOption('gutters');
|
||||
var found = jQuery.inArray("CodeMirror-foldgutter", gutters);
|
||||
@@ -131,16 +143,18 @@ define([
|
||||
*/
|
||||
var initGutter = function() {
|
||||
var cells = IPython.notebook.get_cells();
|
||||
for(var i in cells){
|
||||
var ncells = IPython.notebook.ncells();
|
||||
for (var i=0; i<ncells; i++) {
|
||||
var cell = cells[i];
|
||||
if ((cell instanceof IPython.CodeCell)) {
|
||||
cellFolding(cell);
|
||||
/* restore folding state if previously saved */
|
||||
if ( cell.metadata.code_folding != undefined) {
|
||||
for (var idx in cell.metadata.code_folding) {
|
||||
for (var idx=0; idx++; idx < cell.metadata.code_folding.length) {
|
||||
var line = cell.metadata.code_folding[idx];
|
||||
var opts = cell.code_mirror.state.foldGutter.options;
|
||||
cell.code_mirror.foldCode(CodeMirror.Pos(line, 0), opts.rangeFinder);
|
||||
cell.code_mirror.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +165,7 @@ define([
|
||||
/**
|
||||
* Load my own CSS file
|
||||
*
|
||||
* @param name add CSS file
|
||||
* @param name off CSS file
|
||||
*
|
||||
*/
|
||||
var load_css = function (name) {
|
||||
@@ -163,7 +177,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* Called after extension was loaded
|
||||
* Initialize extension
|
||||
*
|
||||
*/
|
||||
var load_extension = function() {
|
||||
@@ -171,12 +185,12 @@ define([
|
||||
/* change default gutter width */
|
||||
load_css( './foldgutter.css');
|
||||
/* additional custom codefolding mode */
|
||||
require(['./firstline-fold', './magic-fold'], initGutter)
|
||||
require(['./firstline-fold'], initGutter)
|
||||
};
|
||||
|
||||
var codefolding = {
|
||||
load_ipython_extension : load_extension,
|
||||
var extension = {
|
||||
load_ipython_extension : load_extension
|
||||
};
|
||||
|
||||
return codefolding
|
||||
return extension
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
This extension adds codefolding functionality from CodeMirror to a codecell.
|
||||
|
||||
After clicking on the gutter (left margin of codecell) or typing `Alt+F`, the code gets folded. See the examples below.
|
||||
The folding status is saved in the cell metadata of the notebook, so reloading of a notebook will restore the folding view.
|
||||
After clicking on the gutter (left margin of codecell) or typing `Alt+F`, the code gets folded. See the examples below. The folding status is saved in the cell metadata of the notebook, so reloading of a notebook will restore the folding view.
|
||||
|
||||
## Supported modes:
|
||||
Three different folding modes are supported:
|
||||
@@ -22,8 +21,7 @@ or this:
|
||||
Other languages like Javascript use brackets to designate code blocks. Codefolding is supported for Javascript in using the `%%javascript` magic in a codecell.
|
||||
|
||||
### Firstline Comment Folding
|
||||
Allows collapsing of Python code cells to a single comment line. This is useful for long codecells. The algorithm simply
|
||||
looks for a comment in the first line and allows folding in the rest of the cell.
|
||||
Allows collapsing of Python code cells to a single comment line. This is useful for long codecells. The algorithm simply looks for a comment in the first line and allows folding in the rest of the cell.
|
||||
|
||||

|
||||
|
||||
@@ -31,8 +29,6 @@ The code above can be folded like this:
|
||||
|
||||

|
||||
|
||||
### Magic Folding
|
||||
Cell magics in the first line of a cell will also allow cellwide code folding
|
||||
|
||||
Installation
|
||||
============
|
||||
@@ -42,7 +38,7 @@ Install the master version of the IPython-notebook-extensions repository as expl
|
||||
Then load the extension from within the IPyton notebook:
|
||||
```javascript
|
||||
%%javascript
|
||||
IPython.load_extensions('nbextensions/usability/codefolding/codefolding');
|
||||
IPython.load_extensions('IPython-notebook-extensions-master/usability/codefolding/codefolding');
|
||||
```
|
||||
|
||||
## Internals
|
||||
@@ -54,3 +50,4 @@ cell.metadata.code_folding = [ 3, 20, 33 ]
|
||||
```
|
||||
When reloading the IPython notebook, the folding status is restored.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,170 @@
|
||||
// Copyright (c) IPython-Contrib Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
// Allow drag&drop of images into a notebook
|
||||
// Tested with Firefox and Chrome
|
||||
|
||||
define([
|
||||
'base/js/namespace',
|
||||
'jquery',
|
||||
"base/js/events"
|
||||
], function(IPython, $, events) {
|
||||
"use strict";
|
||||
|
||||
/* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */
|
||||
function uniqueid(){
|
||||
// always start with a letter (for DOM friendlyness)
|
||||
var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
|
||||
do {
|
||||
// between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
|
||||
var ascicode=Math.floor((Math.random()*42)+48);
|
||||
if (ascicode<58 || ascicode>64){
|
||||
// exclude all chars between : (58) and @ (64)
|
||||
idstr+=String.fromCharCode(ascicode);
|
||||
}
|
||||
} while (idstr.length<32);
|
||||
|
||||
return (idstr);
|
||||
}
|
||||
|
||||
var send_to_server = function(name,path,msg) {
|
||||
if (name == '') {
|
||||
name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1];
|
||||
}
|
||||
path = path.substring(0, path.lastIndexOf('/')) + '/';
|
||||
if (path === '/') path = '';
|
||||
var url = '//' + location.host + '/api/contents/' + path + name;
|
||||
var img = msg.replace(/(^\S+,)/, ''); // strip header
|
||||
//console.log("send_to_server:", url, img);
|
||||
var data = {'name': name, 'format':'base64', 'content': img, 'type': 'file'};
|
||||
var settings = {
|
||||
processData : false,
|
||||
cache : false,
|
||||
type : "PUT",
|
||||
dataType : "json",
|
||||
data : JSON.stringify(data),
|
||||
headers : {'Content-Type': 'text/plain'},
|
||||
async : false,
|
||||
success : function (data, status, xhr) {
|
||||
var new_cell = IPython.notebook.insert_cell_below('markdown');
|
||||
var str = '<img src="' + name + '"/>';
|
||||
new_cell.set_text(str);
|
||||
new_cell.execute();
|
||||
},
|
||||
error : function() {console.log('Data transfer for drag-and-drop failed.'); }
|
||||
};
|
||||
$.ajax(url, settings);
|
||||
};
|
||||
|
||||
/* the dragover event needs to be canceled to allow firing the drop event */
|
||||
window.addEventListener('dragover', function(event){
|
||||
if (event.preventDefault) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
/* allow dropping an image in notebook */
|
||||
window.addEventListener('drop', function(event){
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
event.preventDefault();
|
||||
if(event.stopPropagation) {event.stopPropagation();}
|
||||
if (event.dataTransfer.items != undefined) {
|
||||
/* Chrome here */
|
||||
var items = event.dataTransfer.items;
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
/* data coming from local file system, must be an image to allow dropping*/
|
||||
if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) {
|
||||
|
||||
var blob = items[i].getAsFile();
|
||||
var filename = blob.name;
|
||||
var reader = new FileReader();
|
||||
reader.onload = ( function(evt) {
|
||||
send_to_server(filename, IPython.notebook.notebook_path, evt.target.result);
|
||||
if(event.stopPropagation) {event.stopPropagation();}
|
||||
} );
|
||||
reader.readAsDataURL(blob);
|
||||
} else {
|
||||
console.log("Unsupported type:", items[i].kind);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Firefox here */
|
||||
var files = event.dataTransfer.files;
|
||||
if (files.length == 0) {
|
||||
var filename = event.dataTransfer.getData('application/x-moz-file-promise-dest-filename');
|
||||
var data = event.dataTransfer.getData('text/plain');
|
||||
if (filename.length == 0) {
|
||||
url = "";
|
||||
filename = '';
|
||||
} else {
|
||||
url = data;
|
||||
data = "";
|
||||
}
|
||||
/* data coming from browser:
|
||||
* url - image is given as an url
|
||||
* data - image is a base64 blob
|
||||
*/
|
||||
//console.log("type:",url," name:", filename," path:", IPython.notebook.notebook_path," url:", url);
|
||||
send_to_server(filename, IPython.notebook.notebook_path, data);
|
||||
return;
|
||||
}
|
||||
/* data coming from local file system, must be an image to allow dropping*/
|
||||
for (var i=0; i < files.length; i++) {
|
||||
var blob = event.dataTransfer.files[0];
|
||||
if (blob.type.indexOf('image/') !== -1) {
|
||||
var filename = blob.name;
|
||||
var url = event.view.location.origin;
|
||||
var reader = new FileReader();
|
||||
reader.onload = ( function(evt) {
|
||||
//console.log("file"," name:", filename," path:", IPython.notebook.notebook_path," url:", url);
|
||||
send_to_server(filename, IPython.notebook.notebook_path, evt.target.result);
|
||||
event.preventDefault();
|
||||
} );
|
||||
reader.readAsDataURL(blob);
|
||||
} else {
|
||||
console.log("Unsupported type:", blob.type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* make sure we do not drop images into a codemirror text field
|
||||
*/
|
||||
var checktype = function(cm,event) {
|
||||
if (event.dataTransfer.items != undefined)
|
||||
{
|
||||
event.codemirrorIgnore = true;
|
||||
}
|
||||
var blob = event.dataTransfer.files[0];
|
||||
|
||||
if (event.dataTransfer.files.length > 0 && blob.type.indexOf('image/') !== -1) {
|
||||
event.codemirrorIgnore = true;
|
||||
}
|
||||
};
|
||||
|
||||
var create_cell = function (event,nbcell,nbindex) {
|
||||
var cell = nbcell.cell;
|
||||
if ((cell instanceof IPython.CodeCell)) {
|
||||
cell.code_mirror.on('drop', checktype);
|
||||
}
|
||||
};
|
||||
|
||||
var cells = IPython.notebook.get_cells();
|
||||
for(var i in cells){
|
||||
var cell = cells[i];
|
||||
if ((cell instanceof IPython.CodeCell)) {
|
||||
cell.code_mirror.on('drop', checktype);
|
||||
}
|
||||
}
|
||||
|
||||
var load_ipython_extension = function() {
|
||||
events.on('create.Cell', create_cell);
|
||||
};
|
||||
var extension = {
|
||||
load_ipython_extension : load_ipython_extension
|
||||
};
|
||||
return extension;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
This IPython notebook extension allows dragging&dropping images from the desktop or other programs into a notebook. A new markdown cell is created below the currently selected cell and the image is embedded.
|
||||
The notebook has been tested with Firefox and Chrome.
|
||||
|
||||
A demo video showing drag&drop of images is here:
|
||||
http://youtu.be/buAL1bTZ73c
|
||||
|
||||
## Installation
|
||||
From IPython simply call
|
||||
```python
|
||||
import IPython
|
||||
IPython.html.nbextensions.install_nbextension('https://raw.githubusercontent.com/ipython-contrib/IPython-notebook-extensions/master/usability/dragdrop/main.js')
|
||||
```
|
||||
|
||||
Then load the extension from within the IPyton notebook:
|
||||
```javascript
|
||||
%%javascript
|
||||
IPython.load_extensions('drag-and-drop');
|
||||
```
|
||||
Alternatively, you can add the load command to your `custom.js`.
|
||||
|
||||
## Internals
|
||||
The image will be uploaded to the server into the directory where your notebook resides. This means, the image is not copied into the notebook itself, it will only be linked to. The markdown cell in the notebook will contain this tag:
|
||||
`<img src="http://127.0.0.1:8888/notebooks/myimage.png"/>`
|
||||
|
||||
If you run `nbconvert` to generate a HTML file, this image will remain outside of the html file. You can embedd all images by calling `nbconvert` with the option `--post=embed.EmbedPostProcessor`. The file `embed.py`, located in the same directory of this extension needs to be in `PYTHONPATH` to be found.
|
||||
@@ -18,7 +18,7 @@ define(["require", "jquery", "base/js/namespace", "base/js/events"], function (r
|
||||
|
||||
var patchCodecellExecute = function() {
|
||||
console.log('patching codecell to trigger ExecuteCell.ExecuteTime');
|
||||
IPython.CodeCell.prototype.old_execute = IPython.CodeCell.prototype.execute
|
||||
IPython.CodeCell.prototype.old_execute = IPython.CodeCell.prototype.execute;
|
||||
|
||||
IPython.CodeCell.prototype.execute = function () {
|
||||
this.old_execute(arguments);
|
||||
@@ -165,14 +165,18 @@ define(["require", "jquery", "base/js/namespace", "base/js/events"], function (r
|
||||
}
|
||||
};
|
||||
|
||||
var load_ipython_extension = function() {
|
||||
patchCodecellExecute();
|
||||
|
||||
patchCodecellExecute();
|
||||
events.on('ExecuteCell.ExecuteTime', executionStartTime);
|
||||
events.on('kernel_idle.Kernel', executionEndTime);
|
||||
|
||||
events.on('ExecuteCell.ExecuteTime',executionStartTime);
|
||||
events.on('kernel_idle.Kernel', executionEndTime);
|
||||
$("head").append($("<link rel='stylesheet' href='" + require.toUrl("./ExecuteTime.css") + "' type='text/css' />"));
|
||||
create_menu();
|
||||
};
|
||||
|
||||
$("head").append($("<link rel='stylesheet' href='" + require.toUrl("./ExecuteTime.css") + "' type='text/css' />"));
|
||||
create_menu();
|
||||
|
||||
console.log('Execute Timings loaded');
|
||||
var extension = {
|
||||
load_ipython_extension : load_ipython_extension
|
||||
};
|
||||
return extension;
|
||||
});
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -2,21 +2,18 @@ This extension displays when the last execution of a cell occurred and how long
|
||||
|
||||
## Display
|
||||
|
||||
Every executed cell is extended with a new area, attached at the bottom of the input area, that displays when the user
|
||||
started the last execution of this cell. When the kernel finishes to execute a cell, this area is update with the duration.
|
||||
Every executed cell is extended with a new area, attached at the bottom of the input area, that displays when the user started the last execution of this cell. When the kernel finishes to execute a cell, this area is update with the duration.
|
||||
|
||||

|
||||
|
||||
## Toggling
|
||||
|
||||
The timings area can be hide by double clicking on it or using the option in the cell menu. The menu toggle
|
||||
timings->All hides (resp. shows) all the possible timings area if the first cell is displayed (resp. hidden).
|
||||
The timings area can be hide by double clicking on it or using the option in the cell menu. The menu toggle timings->All hides (resp. shows) all the possible timings area if the first cell is displayed (resp. hidden).
|
||||
|
||||

|
||||
|
||||
## Internals
|
||||
To be sure that the kernel is run intentionally by executing a codecell, codecell.prototype.execute() is overloaded
|
||||
and a new event 'ExecuteCell.ExecuteTime' is fired, that this extension catches to display the start time. We use the event 'status_idle.Kernel' to know when the kernel finished the execution of the cell.
|
||||
To be sure that the kernel is run intentionally by executing a codecell, codecell.prototype.execute() is overloaded and a new event 'ExecuteCell.ExecuteTime' is fired, that this extension catches to display the start time. We use the event 'status_idle.Kernel' to know when the kernel finished the execution of the cell.
|
||||
|
||||
## Installation
|
||||
Copy `ExecuteTime.{js,css}`, and add `require(['/static/custom/ExecuteTime.js'])` to `custom.js` in your profile's `/static/custom` directory, so it looks like this:
|
||||
@@ -28,5 +25,4 @@ $([IPython.events]).on('app_initialized.NotebookApp', function(){
|
||||
```
|
||||
|
||||
## TODO
|
||||
The timings information could be stored into the notebook and displayed when it is loaded. Where these information s
|
||||
hould be stored is still to be decided (maybe in the metadata).
|
||||
The timings information could be stored into the notebook and displayed when it is loaded. Where these information should be stored is still to be decided (maybe in the metadata).
|
||||
@@ -1,7 +1,7 @@
|
||||
Type: IPython Notebook Extension
|
||||
Name: Search-Replace
|
||||
Description: Search and replace
|
||||
Link: https://github.com/ipython-contrib/IPython-notebook-extensions/wiki
|
||||
Name: Exercise
|
||||
Description: Exercise TEST
|
||||
Link: https://github.com/ipython-contrib/IPython-notebook-extensions/wiki/
|
||||
Icon: icon.png
|
||||
Main: main.js
|
||||
Compatibility: 3.x
|
||||
|
After Width: | Height: | Size: 15 KiB |
@@ -1,14 +1,15 @@
|
||||
// Hide or diplay solutions in a notebook
|
||||
// Copyright (c) IPython-Contrib Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
// To define a solution, select all cells of a solution using shift button and mouse
|
||||
// All cells will be hidden, except the first one
|
||||
// A hide/unhide symbol will be displayed. Click on it and the solution will be displayed/hidden
|
||||
// Hide or diplay solutions in a notebook
|
||||
|
||||
define([
|
||||
'base/js/namespace',
|
||||
'jquery',
|
||||
"base/js/events",
|
||||
], function(IPython, $, events) {
|
||||
'require',
|
||||
'base/js/events',
|
||||
'nbextensions/usability/rubberband/main'
|
||||
], function(IPython, $, require, events, rubberband) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
@@ -18,21 +19,21 @@ define([
|
||||
* @param ev {Event} jquery event
|
||||
*/
|
||||
function click_solution_lock(ev) {
|
||||
var cell=IPython.notebook.get_selected_cell()
|
||||
var is_locked = cell.element.find('#lock').hasClass('fa-plus-square-o')
|
||||
var cell=IPython.notebook.get_selected_cell();
|
||||
var is_locked = cell.element.find('#lock').hasClass('fa-plus-square-o');
|
||||
if (is_locked == true) {
|
||||
cell.element.find('#lock').removeClass('fa-plus-square-o')
|
||||
cell.element.find('#lock').addClass('fa-minus-square-o')
|
||||
cell.element.find('#lock').removeClass('fa-plus-square-o');
|
||||
cell.element.find('#lock').addClass('fa-minus-square-o');
|
||||
while (cell.metadata.solution == true) {
|
||||
IPython.notebook.select_next();
|
||||
cell.element.show();
|
||||
cell = IPython.notebook.get_selected_cell()
|
||||
}
|
||||
} else {
|
||||
cell.element.find('#lock').removeClass('fa-minus-square-o')
|
||||
cell.element.find('#lock').addClass('fa-plus-square-o')
|
||||
cell.element.find('#lock').removeClass('fa-minus-square-o');
|
||||
cell.element.find('#lock').addClass('fa-plus-square-o');
|
||||
IPython.notebook.select_next();
|
||||
cell = IPython.notebook.get_selected_cell()
|
||||
cell = IPython.notebook.get_selected_cell();
|
||||
while (cell.metadata.solution == true) {
|
||||
cell.element.hide();
|
||||
IPython.notebook.select_next();
|
||||
@@ -49,48 +50,48 @@ define([
|
||||
*/
|
||||
function hide_solutions() {
|
||||
// first check if lock symbol is already present in selected cell, if yes, remove it
|
||||
var cell=IPython.notebook.get_selected_cell()
|
||||
var has_lock = cell.element.find('#lock').is('div')
|
||||
var cell=IPython.notebook.get_selected_cell();
|
||||
var has_lock = cell.element.find('#lock').is('div');
|
||||
if (has_lock === true) {
|
||||
cell.element.find('#lock').remove()
|
||||
cell.element.find('#lock').remove();
|
||||
while (cell.metadata.solution == true) {
|
||||
delete cell.metadata.solution
|
||||
cell.element.show()
|
||||
IPython.notebook.select_next()
|
||||
delete cell.metadata.solution;
|
||||
cell.element.show();
|
||||
IPython.notebook.select_next();
|
||||
cell = IPython.notebook.get_selected_cell()
|
||||
}
|
||||
} else {
|
||||
// find first cell with solution
|
||||
var start_cell_i // = undefined
|
||||
var cells = IPython.notebook.get_cells()
|
||||
var start_cell_i; // = undefined
|
||||
var cells = IPython.notebook.get_cells();
|
||||
for(var i in cells){
|
||||
var cell = cells[i]
|
||||
var cell = cells[i];
|
||||
if (typeof cell.metadata.selected != undefined && cell.metadata.selected === true) {
|
||||
start_cell_i = i
|
||||
console.log("selected start cell:",i)
|
||||
start_cell_i = i;
|
||||
console.log("selected start cell:", i);
|
||||
break
|
||||
}
|
||||
}
|
||||
IPython.notebook.select(start_cell_i)
|
||||
IPython.notebook.select(start_cell_i);
|
||||
if (cell.metadata.selected == true) {
|
||||
var el = $('<div id="lock" class="fa fa-plus-square-o">')
|
||||
cell.element.prepend(el)
|
||||
cell.metadata.solution = true
|
||||
var el = $('<div id="lock" class="fa fa-plus-square-o">');
|
||||
cell.element.prepend(el);
|
||||
cell.metadata.solution = true;
|
||||
cell.element.css({"background-color": "#ffffff"});
|
||||
delete cell.metadata.selected
|
||||
delete cell.metadata.selected;
|
||||
|
||||
el.click(click_solution_lock)
|
||||
el.click(click_solution_lock);
|
||||
|
||||
IPython.notebook.select_next();
|
||||
cell = IPython.notebook.get_selected_cell()
|
||||
console.log("new cell:", IPython.notebook.get_selected_index())
|
||||
cell = IPython.notebook.get_selected_cell();
|
||||
console.log("new cell:", IPython.notebook.get_selected_index());
|
||||
while (cell.metadata.selected == true) {
|
||||
cell.element.css({"background-color": "#ffffff"});
|
||||
delete cell.metadata.selected
|
||||
delete cell.metadata.selected;
|
||||
cell.element.hide();
|
||||
cell.metadata.solution = true
|
||||
cell.metadata.solution = true;
|
||||
IPython.notebook.select_next();
|
||||
cell = IPython.notebook.get_selected_cell()
|
||||
cell = IPython.notebook.get_selected_cell();
|
||||
console.log("new cell(i):",IPython.notebook.get_selected_index())
|
||||
}
|
||||
}
|
||||
@@ -105,7 +106,7 @@ define([
|
||||
callback : function () {
|
||||
hide_solutions();
|
||||
}
|
||||
},
|
||||
}
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -120,22 +121,21 @@ define([
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.href = require.toUrl(name);
|
||||
console.log(link);
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
};
|
||||
|
||||
load_css('/nbextensions/testing/exercise/main.css');
|
||||
var exercise_wrapper = $('<div id="dragmask" class="highlight-drag"></div>')
|
||||
$("#header").append(exercise_wrapper)
|
||||
load_css('./main.css');
|
||||
var exercise_wrapper = $('<div id="dragmask" class="highlight-drag"></div>');
|
||||
$("#header").append(exercise_wrapper);
|
||||
|
||||
/**
|
||||
* Display existing solutions at startup
|
||||
*
|
||||
*/
|
||||
var cells = IPython.notebook.get_cells()
|
||||
var found_solution = false
|
||||
var cells = IPython.notebook.get_cells();
|
||||
var found_solution = false;
|
||||
for(var i in cells){
|
||||
var cell = cells[i]
|
||||
var cell = cells[i];
|
||||
if (found_solution == true && typeof cell.metadata.solution != undefined && cell.metadata.solution === true) {
|
||||
cell.element.hide()
|
||||
} else {
|
||||
@@ -143,10 +143,11 @@ define([
|
||||
}
|
||||
if (found_solution == false && typeof cell.metadata.solution != undefined && cell.metadata.solution === true) {
|
||||
// hide solution
|
||||
var el = $('<div id="lock" class="fa fa-plus-square-o">')
|
||||
cell.element.prepend(el)
|
||||
el.click( click_solution_lock)
|
||||
var el = $('<div id="lock" class="fa fa-plus-square-o">');
|
||||
cell.element.prepend(el);
|
||||
el.click( click_solution_lock);
|
||||
found_solution = true
|
||||
}
|
||||
rubberband.load_ipython_extension()
|
||||
}
|
||||
})
|
||||
});
|
||||