diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js
index 6d42141..4e60a96 100644
--- a/IPython/html/static/base/js/utils.js
+++ b/IPython/html/static/base/js/utils.js
@@ -5,6 +5,8 @@ define([
'base/js/namespace',
'jquery',
'codemirror/lib/codemirror',
+ // silently upgrades CodeMirror
+ 'codemirror/mode/meta',
], function(IPython, $, CodeMirror){
"use strict";
@@ -603,20 +605,40 @@ define([
msg += ajax_error_msg(jqXHR);
console.log(msg);
};
-
+
var requireCodeMirrorMode = function (mode, callback, errback) {
- /**
- * load a mode with requirejs
+ /**
+ * find a predefined mode or detect from CM metadata then
+ * require and callback with the resolveable mode string: mime or
+ * custom name
*/
- if (typeof mode != "string") mode = mode.name;
- if (CodeMirror.modes.hasOwnProperty(mode)) {
- callback(CodeMirror.modes.mode);
+
+ var modename = (typeof mode == "string") ? mode :
+ mode.mode || mode.name;
+
+ // simplest, cheapest check by mode name: mode may also have config
+ if (CodeMirror.modes.hasOwnProperty(modename)) {
+ // return the full mode object, if it has a name
+ callback(mode.name ? mode : modename);
return;
}
+
+ // *somehow* get back a CM.modeInfo-like object that has .mode and
+ // .mime
+ var info = (mode && mode.mode && mode.mime && mode) ||
+ CodeMirror.findModeByName(modename) ||
+ CodeMirror.findModeByExtension(modename.split(".").slice(-1)) ||
+ CodeMirror.findModeByMIME(modename) ||
+ {mode: modename, mime: modename};
+
require([
// might want to use CodeMirror.modeURL here
- ['codemirror/mode', mode, mode].join('/'),
- ], callback, errback
+ ['codemirror/mode', info.mode, info.mode].join('/'),
+ ], function() {
+ // return the original mode, as from a kernelspec on first load
+ // or the mimetype, as for most highlighting
+ callback(mode.name ? mode : info.mime);
+ }, errback
);
};
diff --git a/IPython/html/static/edit/js/editor.js b/IPython/html/static/edit/js/editor.js
index f2db0c8..53320b6 100644
--- a/IPython/html/static/edit/js/editor.js
+++ b/IPython/html/static/edit/js/editor.js
@@ -41,12 +41,10 @@ function($,
cm.clearHistory();
// Find and load the highlighting mode
- var modeinfo = CodeMirror.findModeByMIME(model.mimetype);
- if (modeinfo) {
- utils.requireCodeMirrorMode(modeinfo.mode, function() {
- cm.setOption('mode', modeinfo.mode);
- });
- }
+ utils.requireCodeMirrorMode(model.mimetype, function(spec) {
+ var mode = CodeMirror.getMode({}, spec);
+ cm.setOption('mode', mode);
+ });
that.save_enabled = true;
},
function(error) {
diff --git a/IPython/html/static/notebook/js/cell.js b/IPython/html/static/notebook/js/cell.js
index 9c1daa8..77ca5a5 100644
--- a/IPython/html/static/notebook/js/cell.js
+++ b/IPython/html/static/notebook/js/cell.js
@@ -558,8 +558,8 @@ define([
return;
}
if (mode.search('magic_') !== 0) {
- utils.requireCodeMirrorMode(mode, function () {
- that.code_mirror.setOption('mode', mode);
+ utils.requireCodeMirrorMode(mode, function (spec) {
+ that.code_mirror.setOption('mode', spec);
});
return;
}
@@ -570,7 +570,7 @@ define([
if(current_mode == magic_mode){
return;
}
- utils.requireCodeMirrorMode(mode, function () {
+ utils.requireCodeMirrorMode(mode, function (spec) {
// create on the fly a mode that switch between
// plain/text and something else, otherwise `%%` is
// source of some highlight issues.
@@ -579,7 +579,7 @@ define([
CodeMirror.getMode(config, 'text/plain'),
// always set something on close
{open: open, close: close,
- mode: CodeMirror.getMode(config, mode),
+ mode: CodeMirror.getMode(config, spec),
delimStyle: "delimit"
}
);
diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js
index 966f71e..3fedb9a 100644
--- a/IPython/html/static/notebook/js/notebook.js
+++ b/IPython/html/static/notebook/js/notebook.js
@@ -102,16 +102,16 @@ define([
return code;
}
}
- utils.requireCodeMirrorMode(lang, function () {
+ utils.requireCodeMirrorMode(lang, function (spec) {
var el = document.createElement("div");
- var mode = CodeMirror.getMode({}, lang);
+ var mode = CodeMirror.getMode({}, spec);
if (!mode) {
console.log("No CodeMirror mode: " + lang);
callback(null, code);
return;
}
try {
- CodeMirror.runMode(code, mode, el);
+ CodeMirror.runMode(code, spec, el);
callback(null, el.innerHTML);
} catch (err) {
console.log("Failed to highlight " + lang + " code", err);
@@ -1585,17 +1585,16 @@ define([
}
this.codemirror_mode = newmode;
codecell.CodeCell.options_default.cm_config.mode = newmode;
- var modename = newmode.mode || newmode.name || newmode;
var that = this;
- utils.requireCodeMirrorMode(modename, function () {
+ utils.requireCodeMirrorMode(newmode, function (spec) {
that.get_cells().map(function(cell, i) {
if (cell.cell_type === 'code'){
- cell.code_mirror.setOption('mode', newmode);
+ cell.code_mirror.setOption('mode', spec);
// This is currently redundant, because cm_config ends up as
// codemirror's own .options object, but I don't want to
// rely on that.
- cell.cm_config.mode = newmode;
+ cell.cm_config.mode = spec;
}
});
});
diff --git a/IPython/html/static/notebook/less/highlight-refs.less b/IPython/html/static/notebook/less/highlight-refs.less
new file mode 100644
index 0000000..a2c0ab6
--- /dev/null
+++ b/IPython/html/static/notebook/less/highlight-refs.less
@@ -0,0 +1,5 @@
+/* load the codemirror defaults as LESS so that highlight.less
+ can load default theme declarations by reference without pulling in the
+ nasty positioning
+*/
+@import (less) "../../components/codemirror/lib/codemirror.css";
diff --git a/IPython/html/static/notebook/less/highlight.less b/IPython/html/static/notebook/less/highlight.less
index 15a878c..d0b2bf2 100644
--- a/IPython/html/static/notebook/less/highlight.less
+++ b/IPython/html/static/notebook/less/highlight.less
@@ -5,160 +5,108 @@ Adapted from GitHub theme
*/
-pre code {
- display: block;
- padding: 0.5em;
+@import (reference) "highlight-refs.less";
+
+@highlight-base: #000;
+
+.highlight-base{
+ color: @highlight-base;
+}
+
+.highlight-variable{
+ .highlight-base();
+}
+
+.highlight-variable-2{
+ color: lighten(@highlight-base, 10%);
}
-.highlight-base,
-pre code,
-pre .subst,
-pre .tag .title,
-pre .lisp .title,
-pre .clojure .built_in,
-pre .nginx .title {
- color: black;
+.highlight-variable-3{
+ color: lighten(@highlight-base, 20%);
}
-.highlight-string,
-pre .string,
-pre .constant,
-pre .parent,
-pre .tag .value,
-pre .rules .value,
-pre .rules .value .number,
-pre .preprocessor,
-pre .ruby .symbol,
-pre .ruby .symbol .string,
-pre .aggregate,
-pre .template_tag,
-pre .django .variable,
-pre .smalltalk .class,
-pre .addition,
-pre .flow,
-pre .stream,
-pre .bash .variable,
-pre .apache .tag,
-pre .apache .cbracket,
-pre .tex .command,
-pre .tex .special,
-pre .erlang_repl .function_or_atom,
-pre .markdown .header {
+.highlight-string{
color: #BA2121;
}
-.highlight-comment,
-pre .comment,
-pre .annotation,
-pre .template_comment,
-pre .diff .header,
-pre .chunk,
-pre .markdown .blockquote {
+.highlight-comment{
color: #408080;
font-style: italic;
}
-.highlight-number,
-pre .number,
-pre .date,
-pre .regexp,
-pre .literal,
-pre .smalltalk .symbol,
-pre .smalltalk .char,
-pre .go .constant,
-pre .change,
-pre .markdown .bullet,
-pre .markdown .link_url {
+.highlight-number{
color: #080;
}
-pre .label,
-pre .javadoc,
-pre .ruby .string,
-pre .decorator,
-pre .filter .argument,
-pre .localvars,
-pre .array,
-pre .attr_selector,
-pre .important,
-pre .pseudo,
-pre .pi,
-pre .doctype,
-pre .deletion,
-pre .envvar,
-pre .shebang,
-pre .apache .sqbracket,
-pre .nginx .built_in,
-pre .tex .formula,
-pre .erlang_repl .reserved,
-pre .prompt,
-pre .markdown .link_label,
-pre .vhdl .attribute,
-pre .clojure .attribute,
-pre .coffeescript .property {
- color: #88F
+.highlight-atom{
+ color: #88F;
}
-.highlight-keyword,
-pre .keyword,
-pre .id,
-pre .phpdoc,
-pre .aggregate,
-pre .css .tag,
-pre .javadoctag,
-pre .phpdoc,
-pre .yardoctag,
-pre .smalltalk .class,
-pre .winutils,
-pre .bash .variable,
-pre .apache .tag,
-pre .go .typename,
-pre .tex .command,
-pre .markdown .strong,
-pre .request,
-pre .status {
+.highlight-keyword{
color: #008000;
font-weight: bold;
}
-.highlight-builtin,
-pre .built_in {
+.highlight-builtin{
color: #008000;
}
-pre .markdown .emphasis {
- font-style: italic;
+.highlight-error{
+ color: #f00;
}
-pre .nginx .built_in {
- font-weight: normal;
+.highlight-operator{
+ color: #AA22FF;
+ font-weight: bold;
}
-pre .coffeescript .javascript,
-pre .javascript .xml,
-pre .tex .formula,
-pre .xml .javascript,
-pre .xml .vbscript,
-pre .xml .css,
-pre .xml .cdata {
- opacity: 0.5;
+.highlight-meta{
+ color: #AA22FF;
}
+/* previously not defined, copying from default codemirror */
+.highlight-def{ .cm-s-default.cm-def() }
+.highlight-punctuation{ .cm-s-default.cm-punctuation() }
+.highlight-property{ .cm-s-default.cm-property() }
+.highlight-string-2{ .cm-s-default.cm-string-2() }
+.highlight-qualifier{ .cm-s-default.cm-qualifier() }
+.highlight-bracket{ .cm-s-default.cm-bracket() }
+.highlight-tag{ .cm-s-default.cm-tag() }
+.highlight-attribute{ .cm-s-default.cm-attribute() }
+.highlight-header{ .cm-s-default.cm-header() }
+.highlight-quote{ .cm-s-default.cm-quote() }
+.highlight-link{ .cm-s-default.cm-link() }
+
+
/* apply the same style to codemirror */
-.cm-s-ipython {
- span.cm-variable { .highlight-base()}
- span.cm-keyword { .highlight-keyword() }
- span.cm-number { .highlight-number() }
- span.cm-comment { .highlight-comment() }
- span.cm-string { .highlight-string()}
- span.cm-builtin { .highlight-builtin() }
- span.cm-error { color: #f00; }
- span.cm-operator {color: #AA22FF; font-weight: bold;}
- span.cm-meta {color: #AA22FF;}
-
- span.cm-tab {
- background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
- background-position: right;
- background-repeat: no-repeat;
- }
+.cm-s-ipython span {
+ &.cm-keyword { .highlight-keyword() }
+ &.cm-atom { .highlight-atom() }
+ &.cm-number { .highlight-number() }
+ &.cm-def { .highlight-def() }
+ &.cm-variable { .highlight-variable() }
+ &.cm-punctuation { .highlight-punctuation() }
+ &.cm-property { .highlight-property() }
+ &.cm-operator { .highlight-operator() }
+ &.cm-variable-2 { .highlight-variable-2() }
+ &.cm-variable-3 { .highlight-variable-3() }
+ &.cm-comment { .highlight-comment() }
+ &.cm-string { .highlight-string() }
+ &.cm-string-2 { .highlight-string-2() }
+ &.cm-meta { .highlight-meta() }
+ &.cm-qualifier { .highlight-qualifier() }
+ &.cm-builtin { .highlight-builtin() }
+ &.cm-bracket { .highlight-bracket() }
+ &.cm-tag { .highlight-tag() }
+ &.cm-attribute { .highlight-attribute() }
+ &.cm-header { .highlight-header() }
+ &.cm-quote { .highlight-quote() }
+ &.cm-link { .highlight-link() }
+ &.cm-error { .highlight-error() }
+
+ &.cm-tab {
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
+ background-position: right;
+ background-repeat: no-repeat;
+ }
}
diff --git a/IPython/html/static/style/ipython.min.css b/IPython/html/static/style/ipython.min.css
index 913feb0..84654de 100644
--- a/IPython/html/static/style/ipython.min.css
+++ b/IPython/html/static/style/ipython.min.css
@@ -563,145 +563,103 @@ Original style from softwaremaniacs.org (c) Ivan Sagalaev