diff --git a/IPython/html/static/notebook/js/textcell.js b/IPython/html/static/notebook/js/textcell.js
index 848d92e..c9ed7c3 100644
--- a/IPython/html/static/notebook/js/textcell.js
+++ b/IPython/html/static/notebook/js/textcell.js
@@ -27,7 +27,7 @@ var IPython = (function (IPython) {
*
* @class TextCell
* @constructor TextCell
- * @extend Ipython.Cell
+ * @extend IPython.Cell
* @param {object|undefined} [options]
* @param [options.cm_config] {object} config to pass to CodeMirror, will extend/overwrite default config
* @param [options.placeholder] {string} default string to use when souce in empty for rendering (only use in some TextCell subclass)
@@ -285,7 +285,7 @@ var IPython = (function (IPython) {
/**
* @class MarkdownCell
* @constructor MarkdownCell
- * @extends Ipython.HtmlCell
+ * @extends IPython.HTMLCell
*/
var MarkdownCell = function (options) {
var options = options || {};
@@ -342,7 +342,7 @@ var IPython = (function (IPython) {
/**
* @class RawCell
* @constructor RawCell
- * @extends Ipython.TextCell
+ * @extends IPython.TextCell
*/
var RawCell = function (options) {
@@ -437,12 +437,12 @@ var IPython = (function (IPython) {
/**
* @class HeadingCell
- * @extends Ipython.TextCell
+ * @extends IPython.TextCell
*/
/**
* @constructor HeadingCell
- * @extends Ipython.TextCell
+ * @extends IPython.TextCell
*/
var HeadingCell = function (options) {
@@ -501,24 +501,8 @@ var IPython = (function (IPython) {
};
- HeadingCell.prototype.set_rendered = function (text) {
- var r = this.element.find("div.text_cell_render");
- r.empty();
- var link = text.replace(/ /g, '_');
- r.append(
- $('')
- .append(
- $('')
- .addClass('heading-anchor')
- .attr('id', link)
- .html(text)
- ).append(
- $('')
- .addClass('anchor-link')
- .attr('href', '#' + link)
- .text('¶')
- )
- );
+ HeadingCell.prototype.set_rendered = function (html) {
+ this.element.find("div.text_cell_render").html(html);
};
@@ -531,8 +515,24 @@ var IPython = (function (IPython) {
HeadingCell.prototype.render = function () {
if (this.rendered === false) {
var text = this.get_text();
+ // Markdown headings must be a single line
+ text = text.replace(/\n/g, ' ');
if (text === "") { text = this.placeholder; }
- this.set_rendered(text);
+ text = Array(this.level + 1).join("#") + " " + text;
+ text = IPython.mathjaxutils.remove_math(text);
+ var html = marked.parser(marked.lexer(text));
+ var h = $(IPython.mathjaxutils.replace_math(html));
+ // add id and linkback anchor
+ var hash = h.text().replace(/ /g, '-');
+ h.attr('id', hash);
+ h.append(
+ $('')
+ .addClass('anchor-link')
+ .attr('href', '#' + hash)
+ .text('¶')
+ );
+
+ this.set_rendered(h);
this.typeset();
this.element.find('div.text_cell_input').hide();
this.element.find("div.text_cell_render").show();
diff --git a/IPython/html/static/notebook/less/textcell.less b/IPython/html/static/notebook/less/textcell.less
index e104e9c..67382b4 100644
--- a/IPython/html/static/notebook/less/textcell.less
+++ b/IPython/html/static/notebook/less/textcell.less
@@ -19,11 +19,6 @@ div.text_cell_render {
color: @textColor;
}
-a.heading-anchor {
- text-decoration: none;
- color: inherit;
-}
-
a.anchor-link:link {
text-decoration: none;
padding: 0px 20px;
diff --git a/IPython/html/static/style/style.min.css b/IPython/html/static/style/style.min.css
index 08581b0..ed96732 100644
--- a/IPython/html/static/style/style.min.css
+++ b/IPython/html/static/style/style.min.css
@@ -1559,7 +1559,6 @@ span#checkpoint_status,span#autosave_status{font-size:small;}
@media (max-width:767px){span#save_widget{font-size:small;} span#checkpoint_status,span#autosave_status{font-size:x-small;}}@media (max-width:767px){span#checkpoint_status,span#autosave_status{display:none;}}@media (min-width:768px) and (max-width:979px){span#checkpoint_status{display:none;} span#autosave_status{font-size:x-small;}}div.text_cell{padding:5px 5px 5px 5px;}
div.text_cell_input{color:#000000;border:1px solid #cfcfcf;border-radius:4px;background:#f7f7f7;}
div.text_cell_render{outline:none;resize:none;width:inherit;border-style:none;padding:5px;color:#000000;}
-a.heading-anchor{text-decoration:none;color:inherit;}
a.anchor-link:link{text-decoration:none;padding:0px 20px;visibility:hidden;}
h1:hover .anchor-link,h2:hover .anchor-link,h3:hover .anchor-link,h4:hover .anchor-link,h5:hover .anchor-link,h6:hover .anchor-link{visibility:visible;}
.toolbar{padding:0px 10px;margin-top:-5px;}.toolbar select,.toolbar label{width:auto;height:26px;vertical-align:middle;margin-right:2px;margin-bottom:0px;display:inline;font-size:92%;margin-left:0.3em;margin-right:0.3em;padding:0px;padding-top:3px;}
diff --git a/IPython/nbconvert/exporters/exporter.py b/IPython/nbconvert/exporters/exporter.py
index cc19ee5..6c9475b 100755
--- a/IPython/nbconvert/exporters/exporter.py
+++ b/IPython/nbconvert/exporters/exporter.py
@@ -57,6 +57,8 @@ default_filters = {
'rm_ansi': filters.remove_ansi,
'rm_dollars': filters.strip_dollars,
'rm_fake': filters.rm_fake,
+ 'html_text' : filters.html_text,
+ 'add_anchor': filters.add_anchor,
'ansi2latex': filters.ansi2latex,
'rm_math_space': filters.rm_math_space,
'wrap': filters.wrap
diff --git a/IPython/nbconvert/filters/markdown.py b/IPython/nbconvert/filters/markdown.py
index eb842bd..cd4b5a2 100755
--- a/IPython/nbconvert/filters/markdown.py
+++ b/IPython/nbconvert/filters/markdown.py
@@ -52,7 +52,7 @@ def markdown2latex(source):
def markdown2html(source):
"""Convert a markdown string to HTML via pandoc"""
- return pandoc(source, 'markdown', 'html')
+ return pandoc(source, 'markdown', 'html', extra_args=['--mathjax'])
def markdown2rst(source):
"""Convert a markdown string to LaTeX via pandoc.
diff --git a/IPython/nbconvert/filters/strings.py b/IPython/nbconvert/filters/strings.py
index 5464e7d..c886804 100755
--- a/IPython/nbconvert/filters/strings.py
+++ b/IPython/nbconvert/filters/strings.py
@@ -1,3 +1,4 @@
+# coding: utf-8
"""String filters.
Contains a collection of useful string manipulation filters for use in Jinja
@@ -17,6 +18,9 @@ templates.
import re
import textwrap
+from xml.etree import ElementTree
+
+from IPython.utils import py3compat
#-----------------------------------------------------------------------------
# Functions
@@ -24,6 +28,8 @@ import textwrap
__all__ = [
'wrap',
+ 'html_text',
+ 'add_anchor',
'strip_dollars',
'rm_fake',
'python_comment',
@@ -50,6 +56,35 @@ def wrap(text, width=100):
return '\n'.join(wrpd)
+def html_text(element):
+ """extract inner text from html
+
+ Analog of jQuery's $(element).text()
+ """
+ if not isinstance(element, (ElementTree.ElementTree, ElementTree.Element)):
+ element = ElementTree.fromstring(element)
+
+ text = element.text or ""
+ for child in element:
+ text += html_text(child)
+ text += (element.tail or "")
+ return text
+
+
+def add_anchor(html):
+ """Add an anchor-link to an html header tag
+
+ For use in heading cells
+ """
+ h = ElementTree.fromstring(py3compat.cast_bytes_py2(html))
+ link = html_text(h).replace(' ', '-')
+ h.set('id', link)
+ a = ElementTree.Element("a", {"class" : "anchor-link", "href" : "#" + link})
+ a.text = u'¶'
+ h.append(a)
+ return ElementTree.tostring(h)
+
+
def strip_dollars(text):
"""
Remove all dollar symbols from text
diff --git a/IPython/nbconvert/templates/basichtml.tpl b/IPython/nbconvert/templates/basichtml.tpl
index 1785cd4..2fd6f0e 100644
--- a/IPython/nbconvert/templates/basichtml.tpl
+++ b/IPython/nbconvert/templates/basichtml.tpl
@@ -59,12 +59,7 @@ Out[{{cell.prompt_number}}]:
{% block headingcell scoped %}
-
-{% set source = cell.source | replace(' ','_') %}
-
- {{cell.source | markdown| rm_fake}}
-
-
+ {{("#" * cell.level + cell.source) | replace('\n', ' ') | markdown | rm_fake | add_anchor }}
{% endblock headingcell %}
diff --git a/IPython/nbconvert/templates/latex/base.tplx b/IPython/nbconvert/templates/latex/base.tplx
index 4b6cae0..a7223d7 100644
--- a/IPython/nbconvert/templates/latex/base.tplx
+++ b/IPython/nbconvert/templates/latex/base.tplx
@@ -87,22 +87,7 @@ it introduces a new line
((* endblock markdowncell *))
((* block headingcell scoped -*))
- \
- ((*- if cell.level == 1 -*))
- ((* block h1 -*))section((* endblock h1 -*))
- ((*- elif cell.level == 2 -*))
- ((* block h2 -*))subsection((* endblock h2 -*))
- ((*- elif cell.level == 3 -*))
- ((* block h3 -*))subsubsection((* endblock h3 -*))
- ((*- elif cell.level == 4 -*))
- ((* block h4 -*))paragraph((* endblock h4 -*))
- ((*- elif cell.level == 5 -*))
- ((* block h5 -*))subparagraph((* endblock h5 -*))
- ((*- elif cell.level == 6 -*))
- ((* block h6 -*))subparagraph((* endblock h6 -*))
- ((= 6th level not available in standard latex =))
-
- ((*- endif -*)){((( cell.source | markdown2latex )))}
+ ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | markdown2latex )))
((* endblock headingcell *))
((* block rawcell scoped *))
diff --git a/IPython/nbconvert/templates/markdown.tpl b/IPython/nbconvert/templates/markdown.tpl
index 732192a..9c12c4e 100644
--- a/IPython/nbconvert/templates/markdown.tpl
+++ b/IPython/nbconvert/templates/markdown.tpl
@@ -61,7 +61,7 @@ $$
{% block headingcell scoped %}
-{{ '#' * cell.level }} {{ cell.source }}
+{{ '#' * cell.level }} {{ cell.source | replace('\n', ' ') }}
{% endblock headingcell %}
diff --git a/IPython/nbconvert/templates/python.tpl b/IPython/nbconvert/templates/python.tpl
index 49eaa43..484a64d 100644
--- a/IPython/nbconvert/templates/python.tpl
+++ b/IPython/nbconvert/templates/python.tpl
@@ -44,7 +44,7 @@ it introduces a new line
{% endblock markdowncell %}
{% block headingcell scoped %}
-{{ '#' * cell.level }}{{ cell.source | pycomment}}
+{{ '#' * cell.level }}{{ cell.source | replace('\n', ' ') | pycomment}}
{% endblock headingcell %}
{% block rawcell scoped %}
diff --git a/IPython/nbconvert/templates/rst.tpl b/IPython/nbconvert/templates/rst.tpl
index 7bc1150..d791cfb 100644
--- a/IPython/nbconvert/templates/rst.tpl
+++ b/IPython/nbconvert/templates/rst.tpl
@@ -63,21 +63,7 @@ Out[{{cell.prompt_number}}]:{% endif %}{% endblock output_prompt %}
{% endblock markdowncell %}
{% block headingcell scoped %}
-{%- set len = cell.source|length -%}
-{{ cell.source | markdown2rst }}
-{% if cell.level == 1 %}
-{{- '=' * len }}
-{%- elif cell.level == 2 %}
-{{- '-' * len }}
-{%- elif cell.level == 3 %}
-{{- '~' * len }}
-{%- elif cell.level == 4 %}
-{{- '.' * len }}
-{%- elif cell.level == 5 %}
-{{- '\\' * len }}
-{%- elif cell.level == 6 %}
-{{- '`' * len }}
-{% endif %}
+{{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2rst }}
{% endblock headingcell %}
diff --git a/IPython/nbconvert/utils/pandoc.py b/IPython/nbconvert/utils/pandoc.py
index c914cee..3823d80 100644
--- a/IPython/nbconvert/utils/pandoc.py
+++ b/IPython/nbconvert/utils/pandoc.py
@@ -24,7 +24,7 @@ from IPython.utils.py3compat import cast_bytes
# Classes and functions
#-----------------------------------------------------------------------------
-def pandoc(source, fmt, to, encoding='utf-8'):
+def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
"""Convert an input string in format `from` to format `to` via pandoc.
This function will raise an error if pandoc is not installed.
@@ -44,7 +44,10 @@ def pandoc(source, fmt, to, encoding='utf-8'):
out : unicode
Output as returned by pandoc.
"""
- p = subprocess.Popen(['pandoc', '-f', fmt, '-t', to],
+ command = ['pandoc', '-f', fmt, '-t', to]
+ if extra_args:
+ command.extend(extra_args)
+ p = subprocess.Popen(command,
stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
out, _ = p.communicate(cast_bytes(source, encoding))