diff --git a/IPython/core/display.py b/IPython/core/display.py index 624f587..6528e04 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -169,6 +169,24 @@ def display_html(*objs, **kwargs): _display_mimetype('text/html', objs, **kwargs) +def display_markdown(*objs, **kwargs): + """Displays the Markdown representation of an object. + + Parameters + ---------- + objs : tuple of objects + The Python objects to display, or if raw=True raw markdown data to + display. + raw : bool + Are the data objects raw data or Python objects that need to be + formatted before display? [default: False] + metadata : dict (optional) + Metadata to be associated with the specific mimetype output. + """ + + _display_mimetype('text/markdown', objs, **kwargs) + + def display_svg(*objs, **kwargs): """Display the SVG representation of an object. @@ -392,6 +410,12 @@ class HTML(TextDisplayObject): return self._repr_html_() +class Markdown(TextDisplayObject): + + def _repr_markdown_(self): + return self.data + + class Math(TextDisplayObject): def _repr_latex_(self): diff --git a/IPython/core/displaypub.py b/IPython/core/displaypub.py index 8052140..dedd9e9 100644 --- a/IPython/core/displaypub.py +++ b/IPython/core/displaypub.py @@ -77,6 +77,7 @@ class DisplayPublisher(Configurable): * text/plain * text/html + * text/markdown * text/latex * application/json * application/javascript @@ -141,6 +142,7 @@ def publish_display_data(source, data, metadata=None): * text/plain * text/html + * text/markdown * text/latex * application/json * application/javascript diff --git a/IPython/core/formatters.py b/IPython/core/formatters.py index 33bdc17..d6f6dfe 100644 --- a/IPython/core/formatters.py +++ b/IPython/core/formatters.py @@ -129,6 +129,7 @@ class DisplayFormatter(Configurable): formatter_classes = [ PlainTextFormatter, HTMLFormatter, + MarkdownFormatter, SVGFormatter, PNGFormatter, PDFFormatter, @@ -152,6 +153,7 @@ class DisplayFormatter(Configurable): * text/plain * text/html + * text/markdown * text/latex * application/json * application/javascript @@ -706,6 +708,20 @@ class HTMLFormatter(BaseFormatter): print_method = ObjectName('_repr_html_') +class MarkdownFormatter(BaseFormatter): + """A Markdown formatter. + + To define the callables that compute the Markdown representation of your + objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type` + or :meth:`for_type_by_name` methods to register functions that handle + this. + + The return value of this formatter should be a valid Markdown. + """ + format_type = Unicode('text/markdown') + + print_method = ObjectName('_repr_markdown_') + class SVGFormatter(BaseFormatter): """An SVG formatter. @@ -826,6 +842,7 @@ class PDFFormatter(BaseFormatter): FormatterABC.register(BaseFormatter) FormatterABC.register(PlainTextFormatter) FormatterABC.register(HTMLFormatter) +FormatterABC.register(MarkdownFormatter) FormatterABC.register(SVGFormatter) FormatterABC.register(PNGFormatter) FormatterABC.register(PDFFormatter) @@ -844,6 +861,7 @@ def format_display_data(obj, include=None, exclude=None): * text/plain * text/html + * text/markdown * text/latex * application/json * application/javascript diff --git a/IPython/html/static/notebook/js/outputarea.js b/IPython/html/static/notebook/js/outputarea.js index 7bdcb52..2fe1c4c 100644 --- a/IPython/html/static/notebook/js/outputarea.js +++ b/IPython/html/static/notebook/js/outputarea.js @@ -248,6 +248,7 @@ var IPython = (function (IPython) { OutputArea.output_types = [ 'application/javascript', 'text/html', + 'text/markdown', 'text/latex', 'image/svg+xml', 'image/png', @@ -417,7 +418,9 @@ var IPython = (function (IPython) { } this._safe_append(toinsert); // If we just output latex, typeset it. - if ((json['text/latex'] !== undefined) || (json['text/html'] !== undefined)) { + if ((json['text/latex'] !== undefined) || + (json['text/html'] !== undefined) || + (json['text/markdown'] !== undefined)) { this.typeset(); } }; @@ -488,7 +491,9 @@ var IPython = (function (IPython) { if (this.append_mime_type(json, toinsert, handle_inserted)) { this._safe_append(toinsert); // If we just output latex, typeset it. - if ((json['text/latex'] !== undefined) || (json['text/html'] !== undefined)) { + if ((json['text/latex'] !== undefined) || + (json['text/html'] !== undefined) || + (json['text/markdown'] !== undefined)) { this.typeset(); } } @@ -545,6 +550,20 @@ var IPython = (function (IPython) { }; + var append_markdown = function(markdown, md, element) { + var type = 'text/markdown'; + var toinsert = this.create_output_subarea(md, "output_markdown", type); + var text_and_math = IPython.mathjaxutils.remove_math(markdown); + var text = text_and_math[0]; + var math = text_and_math[1]; + var html = marked.parser(marked.lexer(text)); + html = IPython.mathjaxutils.replace_math(html, math); + toinsert.append(html); + element.append(toinsert); + return toinsert; + }; + + var append_javascript = function (js, md, element) { // We just eval the JS code, element appears in the local scope. var type = 'application/javascript'; @@ -882,6 +901,7 @@ var IPython = (function (IPython) { OutputArea.display_order = [ 'application/javascript', 'text/html', + 'text/markdown', 'text/latex', 'image/svg+xml', 'image/png', @@ -893,6 +913,7 @@ var IPython = (function (IPython) { OutputArea.append_map = { "text/plain" : append_text, "text/html" : append_html, + "text/markdown": append_markdown, "image/svg+xml" : append_svg, "image/png" : append_png, "image/jpeg" : append_jpeg,