"""latex_envs Exporter class""" # ----------------------------------------------------------------------------- # Copyright (c) 2016-18, J.-F. Bercher # # Distributed under the terms of the Modified BSD License. # # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # Imports # ----------------------------------------------------------------------------- # Stdlib imports import os import re # IPython imports from IPython.display import HTML, display,JSON from nbconvert.exporters.exporter import Exporter from nbconvert.exporters.html import HTMLExporter from nbconvert.exporters.latex import LatexExporter from nbconvert.exporters.slides import SlidesExporter # from nbconvert.postprocessors.base import PostProcessorBase from nbconvert.filters.highlight import Highlight2HTML, Highlight2Latex from nbconvert.preprocessors import Preprocessor from traitlets import Bool, Dict from traitlets.config import Config # A small utilitary function def figcaption(text, label=" "): display(HTML("
Caption: %s
" % text.replace('\n', '
'))) text = text.replace('',r'\textbf{').replace('','}') #some replacement of HTML formatting text = text.replace('',r'\textit{').replace('','}') text = text.replace('',r'\texttt{').replace('','}') display(JSON({'caption': text, 'label':label}),include=["application/json"]) # ----------------------------------------------------------------------------- # Preprocessors, Exporters, PostProcessors # ----------------------------------------------------------------------------- class LenvsLatexPreprocessor(Preprocessor): environmentMap = ['thm', 'lem', 'cor', 'prop', 'defn', 'rem', 'prob', 'excs', 'examp', 'theorem', 'lemma', 'corollary', 'proposition', 'definition', 'remark', 'problem', 'exercise', 'example', 'proof', 'property', 'itemize', 'enumerate', 'theo', 'enum'] # this map should match the map defined in thmsInNb4.js # do not include figure def __call__(self, nb, resources): if self.enabled: self.log.debug("Applying preprocessor: %s", self.__class__.__name__) return self.preprocess(nb, resources) else: return nb, resources def preprocess(self, nb, resources): """ Preprocessing to apply on each notebook. Must return modified nb, resources. If you wish to apply your preprocessing to each cell, you might want to override preprocess_cell method instead. Parameters ---------- nb : NotebookNode Notebook being converted resources : dictionary Additional resources used in the conversion process. Allows preprocessors to pass variables into the Jinja engine. """ #process metadata for index, cell in enumerate(nb.cells): nb.cells[index], resources = self.preprocess_cell(cell, resources, index) return nb, resources def replacement(self, match): theenv = match.group(1) tobetranslated = match.group(3) opt_parameter = '' if match.group(2) is not None: opt_parameter = match.group(2).replace('[','!lb!').replace(']','!rb!') out = "!sl!begin!op!" + theenv + '!cl@' + opt_parameter + tobetranslated + "!sl!end!op!" + theenv + '!cl@' # noqa # out = out.replace('\n', '!nl!') #dont remember why I did that if theenv in self.environmentMap: return out else: return match.group(0).replace('\\begin', '/begin').replace('\\end', '/end')#out def inline_math_strip_space(self,match): return "$"+match.group(1).replace(' ','')+"$" def preprocess_cell(self, cell, resources, index): """ Preprocess cell Parameters ---------- cell : NotebookNode cell Notebook cell being processed resources : dictionary Additional resources used in the conversion process. Allows preprocessors to pass variables into the Jinja engine. cell_index : int Index of the cell being processed (see base.py) """ if cell.cell_type == "markdown": data = cell.source data = data.replace(r"$\LaTeX$", r"\LaTeX") data = data.replace(r"{enumerate}", r"{enum}") code = re.search(r'\\begin{(\w+)}([\s\S]*?)\\end{\1}', data) while (code is not None): data = re.sub(r'\\begin{(\w+)}(\[[\S\s]*?\])?([\s\S]*?)\\end{\1}', #data = re.sub(r'\\begin{(\w+)}([\s\S]*?)\\end{\1}', self.replacement, data) data = re.sub(r'\n\s*\\item', r'//item',data) data = data.replace(r'\item', r'/item') code = re.search(r'\\begin{(\w+)}([\s\S]*?)\\end{\1}', data) data = re.sub(r'\\\[([\s\S]*?)\\\]', r'$$\1$$', data) #$$.$$ is converted into \[.\] #noqa data = re.sub(r'\\\(([\s\S]*?)\\\)', self.inline_math_strip_space, data) #$.$ converted into \(.\) #noqa #data = data.replace('\n', '!nl!\n') data = data.replace('\\\\', '!sl!!sl!') data = re.sub(r'%([\S\s ]*?)\n', r'!cc!\1!nl!',data) #data = data.replace('%', '!cc!') data = data.replace("/begin", "\\begin") data = data.replace("/end", "\\end") cell.source = data elif cell.cell_type == "code" and "outputs" in cell: json_metadata = [] mime_types = ['image/svg+xml','image/png','image/jpeg','application/pdf'] # Below just an ad hoc personnal filter if "%run nbinit.ipy" in cell.source: cell.source = '' cell.cell_type = "raw" return cell, resources for output in cell.outputs: if "data" in output: if 'text/html' in output.data and 'img src' in output.data['text/html']: data = output.data['text/html'] data = re.sub(r'','',data) output.data['image/png'] = data # make png data from html data elif 'application/json' in output.data and 'caption' in output.data['application/json']: #found a json field with caption json_metadata.append(output.data['application/json']) if any(x in output.data for x in mime_types) and len(json_metadata)>0: output.metadata.update(json_metadata.pop()) # write caption to data field metadata return cell, resources class LenvsHTMLPreprocessor(Preprocessor): environmentMap = ['thm', 'lem', 'cor', 'prop', 'defn', 'rem', 'prob', 'excs', 'examp', 'theorem', 'lemma', 'corollary', 'proposition', 'definition', 'remark', 'problem', 'exercise', 'example', 'proof', 'property', 'itemize', 'enumerate', 'theo', 'enum'] # this map should match the map defined in thmsInNb4.js # do not include figure def replacement(self, match): return "\n" + match.group(0) def preprocess_cell(self, cell, resources, index): """ Preprocess cell Parameters ---------- cell : NotebookNode cell Notebook cell being processed resources : dictionary Additional resources used in the conversion process. Allows preprocessors to pass variables into the Jinja engine. cell_index : int Index of the cell being processed (see base.py) """ # Add a newline before each environment: this is a workaround # for a bug in mistune where # the environment contents will be converted from markdown # this has unwanted consequences for equations # ref: https://github.com/jupyter/nbconvert/issues/160 if cell.cell_type == "markdown": cell.source = re.sub(r'\\\[([\s\S]*?)\\\]', r'$$\1$$', cell.source) cell.source = re.sub(r'\\\(([\s\S]*?)\\\)', r'$\1$', cell.source) cell.source = re.sub(r'\\begin{equation\*}([\s\S]*?)\\end{equation\*}', r'$$\1$$', cell.source) cell.source = re.sub(r'\\begin{(\w+)}([\s\S]*?)\\end{\1}', self.replacement, cell.source) return cell, resources def include_latexdefs(name): '''This function is used to include latex user definitions in the html template, using the syntax {{ include_latexdefs('latexdefs.tex') }} This function is included in jinja2 environment''' text = '' try: with open(name) as f: for line in f: text += '$' + line[:-1] + '$\n' except: pass return text def include_userenvs_cfg(): '''This function is used to include the user environment configuration in the html template, using the syntax {{ include_userenvs_cfg() }} This function is included in jinja2 environment''' import jupyter_core, os datadir = jupyter_core.paths.jupyter_data_dir() user_envs_file = os.path.join(datadir, 'nbextensions', 'latex_envs', 'user_envs.json') text = '' try: f=open(user_envs_file,'rt') text=f.read(); except: pass return text class LenvsHTMLExporter(HTMLExporter): """ Exports to an html document, embedding latex_env extension (.html) """ def __init__(self, config=None, **kw): """ Public constructor Parameters ---------- config : :class:`~traitlets.config.Config` User configuration instance. `**kw` Additional keyword arguments passed to parent __init__ """ with_default_config = self.default_config if config: with_default_config.merge(config) super(HTMLExporter, self).__init__( config=with_default_config, **kw) self.register_preprocessor(LenvsHTMLPreprocessor(), enabled=True) self._init_preprocessors() def _file_extension_default(self): return '.html' def _template_file_default(self): return 'latex_envs' output_mimetype = 'text/html' def _raw_mimetypes_default(self): return ['text/markdown', 'text/html', ''] @property def default_config(self): # import jupyter_core.paths # import os c = Config({ 'NbConvertBase': { 'display_data_priority': ['application/javascript', 'text/html', 'text/markdown', 'image/svg+xml', 'text/latex', 'image/png', 'image/jpeg', 'text/plain' ] }, 'CSSHTMLHeaderPreprocessor': { 'enabled': True }, 'HighlightMagicsPreprocessor': { 'enabled': True }, 'ExtractOutputPreprocessor': {'enabled': False}, 'latex_envs.LenvsHTMLPreprocessor': {'enabled': True}} ) c.merge(super(LenvsHTMLExporter, self).default_config) if os.path.isdir(os.path.join(os.path.dirname(__file__), 'templates')): c.TemplateExporter.template_paths = ['.', os.path.join(os.path.dirname(__file__), 'templates')] else: from jupyter_contrib_nbextensions.nbconvert_support import ( templates_directory) c.TemplateExporter.template_paths = ['.', templates_directory()] return c def from_notebook_node(self, nb, resources=None, **kw): langinfo = nb.metadata.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', None)) self.register_filter('highlight_code', Highlight2HTML(pygments_lexer=lexer, parent=self)) self.environment.globals['include_latexdefs'] = include_latexdefs self.environment.globals['include_userenvs_cfg'] = include_userenvs_cfg lenvshtmlpreprocessor = LenvsHTMLPreprocessor() self.register_preprocessor(lenvshtmlpreprocessor, enabled=True) self._init_preprocessors() nb, resources = lenvshtmlpreprocessor(nb, resources) output, resources = super(LenvsHTMLExporter, self).from_notebook_node( nb, resources, **kw) # postout = postprocess(output) # print(postout[0:200]) #WORKS return output, resources ################### class LenvsSlidesExporter(SlidesExporter): """ Exports to a reveal-js/slides document, embedding latex_env extension (.html) """ @property def default_config(self): # import jupyter_core.paths # import os c = Config({ 'NbConvertBase': { 'display_data_priority': ['application/javascript', 'text/html', 'text/markdown', 'image/svg+xml', 'text/latex', 'image/png', 'image/jpeg', 'text/plain' ] }, 'CSSHTMLHeaderPreprocessor': { 'enabled': True }, 'HighlightMagicsPreprocessor': { 'enabled': True }, 'ExtractOutputPreprocessor': {'enabled': False}, 'latex_envs.LenvsHTMLPreprocessor': {'enabled': True}} ) c.merge(super(LenvsSlidesExporter, self).default_config) if os.path.isdir(os.path.join(os.path.dirname(__file__), 'templates')): c.TemplateExporter.template_paths = ['.', os.path.join(os.path.dirname(__file__), 'templates')] else: from jupyter_contrib_nbextensions.nbconvert_support import ( templates_directory) c.TemplateExporter.template_paths = ['.', templates_directory()] return c def _template_file_default(self): return 'slides_latex_envs.tpl' def from_notebook_node(self, nb, resources=None, **kw): langinfo = nb.metadata.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', None)) self.register_filter('highlight_code', Highlight2HTML(pygments_lexer=lexer, parent=self)) self.environment.globals['include_latexdefs'] = include_latexdefs self.environment.globals['include_userenvs_cfg'] = include_userenvs_cfg lenvshtmlpreprocessor = LenvsHTMLPreprocessor() self.register_preprocessor(lenvshtmlpreprocessor, enabled=True) self._init_preprocessors() nb, resources = lenvshtmlpreprocessor(nb, resources) output, resources = super(LenvsSlidesExporter, self).from_notebook_node( nb, resources, **kw) return output, resources ################### class LenvsTocHTMLExporter(LenvsHTMLExporter): """ Exports to a html document, embedding latex_env and toc extensions (.html) """ def _template_file_default(self): return 'latex_envs_toc' ################ class LenvsLatexExporter(LatexExporter): """ Exports to a LaTeX document """ removeHeaders = Bool( False, help="Remove headers and footers").tag(config=True, alias="rh") figcaptionProcess = Bool( True, help="Process figcaptions").tag(config=True, alias="fc") tocrefRemove = Bool( True, help="Remove tocs and ref sections, + some cleaning").tag( config=True, alias="trr") flags = Dict(dict(enable=({'Bar': {'enabled': True}}, "Enable Bar"))) def __init__(self, config=None, **kw): """ Public constructor Parameters ---------- config : :class:`~traitlets.config.Config` User configuration instance. `**kw` Additional keyword arguments passed to parent __init__ """ with_default_config = self.default_config if config: with_default_config.merge(config) super(Exporter, self).__init__(config=with_default_config, **kw) self.register_preprocessor(LenvsLatexPreprocessor(), enabled=True) self._init_preprocessors() def _file_extension_default(self): return '.tex' def _template_file_default(self): return 'thmsInNb_article' output_mimetype = 'text/tex' def _raw_mimetypes_default(self): return ['text/tex', 'text/txt', ''] @property def default_config(self): # import jupyter_core.paths # import os c = Config({ 'NbConvertBase': { 'display_data_priority': ['application/javascript', 'text/html', 'text/markdown', 'image/svg+xml', 'text/latex', 'image/png', 'image/jpeg', 'text/plain' ] }, 'CSSHTMLHeaderPreprocessor': { 'enabled': True}, 'HighlightMagicsPreprocessor': { 'enabled': True}, 'ExtractOutputPreprocessor': { 'enabled': True}, 'latex_envs.LenvsLatexPreprocessor': {'enabled': True} } ) c.merge(super(LenvsLatexExporter, self).default_config) if os.path.isdir(os.path.join(os.path.dirname(__file__), 'templates')): c.TemplateExporter.template_paths = ['.', os.path.join(os.path.dirname(__file__), 'templates')] else: from jupyter_contrib_nbextensions.nbconvert_support import ( templates_directory) c.TemplateExporter.template_paths = ['.', templates_directory()] return c def tocrefrm(self, text): # Remove Table of Contents section newtext = re.sub(r'(?:\\[sub]?section|\\chapter){Table of Contents}([\s\S]*?)(?=(?:\\[sub]?section|\\chapter))', '', text, flags=re.M) # noqa # Remove References section newtext = re.sub(r'\\section{References}[\S\s]*?(?=(?:\\[sub]*section|\\chapter|\\end{document}|\Z))', '', newtext, flags=re.M) # noqa # Cleaning newtext = re.sub('\\\\begin{verbatim}[\s]*?[\s]*?\\\\end{verbatim}', '', newtext, flags=re.M) # noqa newtext = re.sub('\\\\begin{verbatim}[\s]*?[\s]*?\\\\end{verbatim}', '', newtext, flags=re.M) # noqa # bottom page with links to Index/back/next (suppress this) # '----[\s]*?
[Index](toc.ipynb)[\S ]*?.ipynb\)
' newtext = re.sub('\\\\begin{center}\\\\rule{[\S\s]*?\\\\end{center}[\s]*?\S*\href{toc.ipynb}{Index}[\S\s ]*?.ipynb}{Next}', '', newtext, flags=re.M) # noqa return newtext def postprocess(self, nb_text): nb_text = nb_text.replace('!nl!', '\n') nb_text = nb_text.replace('!op!', '{') nb_text = nb_text.replace('!cl@', '}') nb_text = nb_text.replace('!cc!', '%') nb_text = nb_text.replace('!sl!', '\\') nb_text = nb_text.replace('!lb!', '[') nb_text = nb_text.replace('!rb!', ']') nb_text = nb_text.replace(r'//item', '\n\\item') nb_text = nb_text.replace('\\[', '\n\\[').replace('\\]', '\\]\n') nb_text = nb_text.replace(r'/item', r'\item') nb_text = nb_text.replace(r"{enum}", r"{enumerate}") if self.removeHeaders: tex_text = re.search('begin{document}([\s\S]*?)\\\\end{document}', nb_text, flags=re.M) # noqa newtext = tex_text.group(1) newtext = newtext.replace('\\maketitle', '') newtext = newtext.replace('\\tableofcontents', '') nb_text = newtext if self.tocrefRemove: nb_text = self.tocrefrm(nb_text) return nb_text def from_notebook_node(self, nb, resources=None, **kw): langinfo = nb.metadata.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', None)) self.register_filter('highlight_code', Highlight2Latex(pygments_lexer=lexer, parent=self)) lenvslatexpreprocessor = LenvsLatexPreprocessor() self.register_preprocessor(lenvslatexpreprocessor, enabled=True) self._init_preprocessors() nb, resources = lenvslatexpreprocessor(nb, resources) output, resources = super(LenvsLatexExporter, self).from_notebook_node(nb, resources, **kw) # noqa postout = self.postprocess(output) #print(postout[0:200]) #WORKS return postout, resources # jupyter nbconvert --to latex_envs.LenvsLatexExporter # --LenvsLatexExporter.removeHeaders=True # --LenvsLatexExporter.figcaptionProcess=True # --LenvsLatexExporter.tocrefRemove=True test_theo.ipynb # once entry point are installed # jupyter nbconvert --to latex_lenvs --figcaptionProcess=true # --removeHeaders=false test_theo # jupyter nbconvert --to latex_envs.LenvsHTMLExporter test_theo.ipynb