Show More
@@ -38,6 +38,7 b' import string' | |||
|
38 | 38 | import hashlib |
|
39 | 39 | import pygments |
|
40 | 40 | import itertools |
|
41 | import fnmatch | |
|
41 | 42 | |
|
42 | 43 | from datetime import datetime |
|
43 | 44 | from functools import partial |
@@ -1811,27 +1812,15 b' def urlify_commit_message(commit_text, r' | |||
|
1811 | 1812 | return literal(newtext) |
|
1812 | 1813 | |
|
1813 | 1814 | |
|
1814 | def rst(source, mentions=False): | |
|
1815 | return literal('<div class="rst-block">%s</div>' % | |
|
1816 | MarkupRenderer.rst(source, mentions=mentions)) | |
|
1817 | ||
|
1818 | ||
|
1819 | def markdown(source, mentions=False): | |
|
1820 | return literal('<div class="markdown-block">%s</div>' % | |
|
1821 | MarkupRenderer.markdown(source, flavored=True, | |
|
1822 | mentions=mentions)) | |
|
1823 | ||
|
1824 | ||
|
1825 | 1815 | def renderer_from_filename(filename, exclude=None): |
|
1826 | 1816 | """ |
|
1827 | 1817 | choose a renderer based on filename |
|
1828 | 1818 | """ |
|
1829 | 1819 | |
|
1830 | # images | |
|
1831 | ||
|
1832 | 1820 | # ipython |
|
1833 | if filename.endswith('.ipynb'): | |
|
1834 | return 'ipython' | |
|
1821 | for ext in ['*.ipynb']: | |
|
1822 | if fnmatch.fnmatch(filename, pat=ext): | |
|
1823 | return 'jupyter' | |
|
1835 | 1824 | |
|
1836 | 1825 | is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude) |
|
1837 | 1826 | if is_markup: |
@@ -1841,26 +1830,18 b' def renderer_from_filename(filename, exc' | |||
|
1841 | 1830 | |
|
1842 | 1831 | def render(source, renderer='rst', mentions=False): |
|
1843 | 1832 | if renderer == 'rst': |
|
1844 | return rst(source, mentions=mentions) | |
|
1833 | return literal( | |
|
1834 | '<div class="rst-block">%s</div>' % | |
|
1835 | MarkupRenderer.rst(source, mentions=mentions)) | |
|
1845 | 1836 | elif renderer == 'markdown': |
|
1846 | return markdown(source, mentions=mentions) | |
|
1847 | elif renderer == 'ipython': | |
|
1848 | def ipython_renderer(source): | |
|
1849 | import nbformat | |
|
1850 | from nbconvert import HTMLExporter | |
|
1851 | notebook = nbformat.reads(source, as_version=4) | |
|
1837 | return literal( | |
|
1838 | '<div class="markdown-block">%s</div>' % | |
|
1839 | MarkupRenderer.markdown(source, flavored=True, mentions=mentions)) | |
|
1840 | elif renderer == 'jupyter': | |
|
1841 | return literal( | |
|
1842 | '<div class="ipynb">%s</div>' % | |
|
1843 | MarkupRenderer.jupyter(source)) | |
|
1852 | 1844 | |
|
1853 | # 2. Instantiate the exporter. We use the `basic` template for now; we'll get into more details | |
|
1854 | # later about how to customize the exporter further. | |
|
1855 | html_exporter = HTMLExporter() | |
|
1856 | html_exporter.template_file = 'basic' | |
|
1857 | ||
|
1858 | # 3. Process the notebook we loaded earlier | |
|
1859 | (body, resources) = html_exporter.from_notebook_node(notebook) | |
|
1860 | ||
|
1861 | return body | |
|
1862 | ||
|
1863 | return ipython_renderer(source) | |
|
1864 | 1845 | # None means just show the file-source |
|
1865 | 1846 | return None |
|
1866 | 1847 |
@@ -29,6 +29,7 b' import logging' | |||
|
29 | 29 | import itertools |
|
30 | 30 | |
|
31 | 31 | from mako.lookup import TemplateLookup |
|
32 | from mako.template import Template as MakoTemplate | |
|
32 | 33 | |
|
33 | 34 | from docutils.core import publish_parts |
|
34 | 35 | from docutils.parsers.rst import directives |
@@ -49,6 +50,7 b' class MarkupRenderer(object):' | |||
|
49 | 50 | |
|
50 | 51 | MARKDOWN_PAT = re.compile(r'\.(md|mkdn?|mdown|markdown)$', re.IGNORECASE) |
|
51 | 52 | RST_PAT = re.compile(r'\.re?st$', re.IGNORECASE) |
|
53 | JUPYTER_PAT = re.compile(r'\.(ipynb)$', re.IGNORECASE) | |
|
52 | 54 | PLAIN_PAT = re.compile(r'^readme$', re.IGNORECASE) |
|
53 | 55 | |
|
54 | 56 | extensions = ['codehilite', 'extra', 'def_list', 'sane_lists'] |
@@ -95,6 +97,8 b' class MarkupRenderer(object):' | |||
|
95 | 97 | detected_renderer = 'markdown' |
|
96 | 98 | elif MarkupRenderer.RST_PAT.findall(filename): |
|
97 | 99 | detected_renderer = 'rst' |
|
100 | elif MarkupRenderer.JUPYTER_PAT.findall(filename): | |
|
101 | detected_renderer = 'jupyter' | |
|
98 | 102 | elif MarkupRenderer.PLAIN_PAT.findall(filename): |
|
99 | 103 | detected_renderer = 'plain' |
|
100 | 104 | else: |
@@ -263,6 +267,78 b' class MarkupRenderer(object):' | |||
|
263 | 267 | else: |
|
264 | 268 | raise |
|
265 | 269 | |
|
270 | @classmethod | |
|
271 | def jupyter(cls, source): | |
|
272 | from rhodecode.lib import helpers | |
|
273 | import nbformat | |
|
274 | from nbconvert import HTMLExporter | |
|
275 | from traitlets.config import Config | |
|
276 | ||
|
277 | class CustomHTMLExporter(HTMLExporter): | |
|
278 | def _template_file_default(self): | |
|
279 | return 'basic' | |
|
280 | ||
|
281 | def _sanitize_resources(resources): | |
|
282 | """ | |
|
283 | Skip/sanitize some of the CSS generated and included in jupyter | |
|
284 | so it doesn't messes up UI so much | |
|
285 | """ | |
|
286 | ||
|
287 | # TODO(marcink): probably we should replace this with whole custom | |
|
288 | # CSS set that doesn't screw up, but jupyter generated html has some | |
|
289 | # special markers, so it requires Custom HTML exporter template with | |
|
290 | # _default_template_path_default, to achieve that | |
|
291 | ||
|
292 | # strip the reset CSS | |
|
293 | resources[0] = resources[0][resources[0].find('/*! Source'):] | |
|
294 | return resources | |
|
295 | ||
|
296 | def as_html(notebook): | |
|
297 | conf = Config() | |
|
298 | html_exporter = CustomHTMLExporter(config=conf) | |
|
299 | ||
|
300 | (body, resources) = html_exporter.from_notebook_node(notebook) | |
|
301 | header = '<!-- ## IPYTHON NOTEBOOK RENDERING ## -->' | |
|
302 | js = MakoTemplate(r''' | |
|
303 | <!-- Load mathjax --> | |
|
304 | <!-- MathJax configuration --> | |
|
305 | <script type="text/x-mathjax-config"> | |
|
306 | MathJax.Hub.Config({ | |
|
307 | jax: ["input/TeX","output/HTML-CSS", "output/PreviewHTML"], | |
|
308 | extensions: ["tex2jax.js","MathMenu.js","MathZoom.js", "fast-preview.js", "AssistiveMML.js", "[Contrib]/a11y/accessibility-menu.js"], | |
|
309 | TeX: { | |
|
310 | extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"] | |
|
311 | }, | |
|
312 | tex2jax: { | |
|
313 | inlineMath: [ ['$','$'], ["\\(","\\)"] ], | |
|
314 | displayMath: [ ['$$','$$'], ["\\[","\\]"] ], | |
|
315 | processEscapes: true, | |
|
316 | processEnvironments: true | |
|
317 | }, | |
|
318 | // Center justify equations in code and markdown cells. Elsewhere | |
|
319 | // we use CSS to left justify single line equations in code cells. | |
|
320 | displayAlign: 'center', | |
|
321 | "HTML-CSS": { | |
|
322 | styles: {'.MathJax_Display': {"margin": 0}}, | |
|
323 | linebreaks: { automatic: true } | |
|
324 | }, | |
|
325 | showMathMenu: false | |
|
326 | }); | |
|
327 | </script> | |
|
328 | <!-- End of mathjax configuration --> | |
|
329 | <script src="${h.asset('js/src/math_jax/MathJax.js')}"></script> | |
|
330 | ''').render(h=helpers) | |
|
331 | ||
|
332 | css = '<style>{}</style>'.format( | |
|
333 | ''.join(_sanitize_resources(resources['inlining']['css']))) | |
|
334 | ||
|
335 | body = '\n'.join([header, css, js, body]) | |
|
336 | return body, resources | |
|
337 | ||
|
338 | notebook = nbformat.reads(source, as_version=4) | |
|
339 | (body, resources) = as_html(notebook) | |
|
340 | return body | |
|
341 | ||
|
266 | 342 | |
|
267 | 343 | class RstTemplateRenderer(object): |
|
268 | 344 |
General Comments 0
You need to be logged in to leave comments.
Login now