.*?)(?P=del)')
result = tex
for match in r.finditer(tex):
c = match.group("content")
result = result.replace(match.group(0), '\\verb{'+c +'}')
return result
diff --git a/texla/Parser/TreeExplorer.py b/texla/Parser/TreeExplorer.py
index f582588..2a829d2 100644
--- a/texla/Parser/TreeExplorer.py
+++ b/texla/Parser/TreeExplorer.py
@@ -1,110 +1,120 @@
import logging
class TreeExplorer:
"""
The TreeExplorer class is an utility to navigate
and extract information from the tree of parsed blocks.
For example it is useful to extract the tree of the
parents of a block for debugging reasons. It is useful
also in rendering to localize blocks inside the document.
"""
def __init__(self, root_block):
""" The constructor needs a root_block to
begin the tree"""
self.root_block = root_block
self.blocks = {'@': root_block}
+ self.block_names = {}
#registering blocks by id
self.register_blocks(root_block.ch_blocks)
@staticmethod
def create_tree_from_children(block):
#first of all we need the root_block
current = block
while True:
if current.parent_block is None:
root_block = current
break
current = current.parent_block
#now we can return a new TreeExplorer
#constructed from the found root.
return TreeExplorer(root_block)
def register_blocks(self, blocks):
"""This methods reads all the blocks tree
from the root_block and created a dictionary
with id:block"""
for block in blocks:
self.blocks[block.id] = block
if block.N_chblocks > 0:
self.register_blocks(block.ch_blocks)
def update_blocks_register(self):
"""This methods update the blocks' ids register
recalling register_blocks with the root_block"""
self.register_blocks(self.root_block.ch_blocks)
def get_parents_list(self, block):
"""This method returns the list of the parent
blocks of the requested block """
if isinstance(block, str):
block = self.blocks[block]
parents = []
current = block
while True:
if current == self.root_block:
break
parents.append(current.parent_block)
current = current.parent_block
parents.reverse()
return parents
def get_parents_list_ids(self, block):
parents = self.get_parents_list(block)
return [x.id for x in parents]
def get_block(self, blockid):
return self.blocks.get(blockid)
def print_tree(self, block, filter_list=None):
"""This methods prints a beautified tree starting
from block parameter and his children. If filter_list
is present only the block with the id in the list
are printed. It returns a list of output strings"""
output = []
if filter_list is None or block.id in filter_list:
lstr = ". "* (block.tree_depth+1)
output.append(lstr+ ". "+ " "+"_"*40 )
output.append(lstr+ "#"+"---"+ ">|ID : {}".format(block.id))
output.append(lstr+ ". "+ " |block_name : {}".
format(block.block_name))
output.append(lstr+ ". "+ " |attributes: ")
for at,attr in block.attributes.items():
output.append(lstr+ ". " + " | - "+ "{} : {}".
format(at, attr))
output.append(lstr+ ". ."+"\u203E"*40+"\n")
output = "\n".join(output)
#iterating on the block children
for bl in block.ch_blocks:
output += self.print_tree(bl, filter_list)
return output
def print_tree_to_blocks(self, blocks):
"""This methods print the tree of parents
of the list of blocks passed as parameter.
First of all it gets all the parents ids and
then prints the tree using the list as filter."""
fl = []
for bl in blocks:
fl+= self.get_parents_list_ids(bl)
if isinstance(bl, str):
fl.append(bl)
else:
fl.append(bl.id)
return self.print_tree(self.root_block, filter_list=fl)
def print_tree_to_block(self, block):
return self.print_tree_to_blocks([block])
def print_all_tree(self):
- return self.print_tree(self.root_block)
\ No newline at end of file
+ return self.print_tree(self.root_block)
+
+ def register_block_names(self):
+ """This function registers the block_names, creating
+ a dictionary with blocks groups by type"""
+ self.block_names.clear()
+ for bl in self.blocks.values():
+ if not bl in self.block_names:
+ self.block_names[bl.block_name] = []
+ self.block_names[bl.block_name].append(bl)
\ No newline at end of file
diff --git a/texla/Renderers/MediaWikiRenderer.py b/texla/Renderers/MediaWikiRenderer.py
index 24c3e90..78c219c 100644
--- a/texla/Renderers/MediaWikiRenderer.py
+++ b/texla/Renderers/MediaWikiRenderer.py
@@ -1,554 +1,579 @@
import logging
from .Renderer import Renderer
from ..PageTree.PageTree import *
class MediaWikiRenderer(Renderer):
- def __init__(self, configs):
- super().__init__()
+ def __init__(self, configs, reporter):
+ super().__init__(reporter)
self.configs = configs
self.doc_title = configs['doc_title']
#saving the hooks
self.render_hooks = {
#root
'root-block': self.r_document,
'default': self.default,
#text
'par': self.r_par,
'newpage': self.r_newpage,
'newline': self.r_newline,
'\\': self.r_newline,
'text': self.r_text,
'clearpage': self.r_newpage,
'cleardoublepage': self.r_newpage,
#formatting
'emph': self.r_textit,
'textbf': self.r_textbf,
'textit': self.r_textit,
'textsc': self.r_textsc,
'textsuperscript': self.r_superscript,
'textsubscript': self.r_subscript,
'underline': self.r_underline,
'uline': self.r_underline,
'%': self.r_special_character,
'&': self.r_special_character,
'$': self.r_special_character,
'{': self.r_special_character,
'}': self.r_special_character,
'#': self.r_special_character,
'_': self.r_special_character,
'dots': self.r_dots,
'ldots': self.r_dots,
'flushright': self.r_flushright,
'flushleft': self.r_flushleft,
'center': self.r_center,
'centerline': self.r_center,
'abstract': self.r_abstract,
'linebreak': self.r_break,
'pagebreak': self.r_break,
'nolinebreak': self.r_break,
'nopagebreak': self.r_break,
'verbatim': self.r_verbatim,
'verb': self.r_verb,
#spaces
'vspace': self.r_vspace,
'mandatory_space': self.r_mandatory_space,
#theorems
'theorem' : self.r_theorem,
'proof' : self.r_proof,
#sectioning
'part': self.sectioning,
'chapter': self.sectioning,
'section': self.sectioning,
'subsection': self.sectioning,
'subsubsection': self.sectioning,
'paragraph': self.sectioning,
'subparagraph': self.sectioning,
#math
'displaymath': self.r_display_math,
'inlinemath': self.r_inline_math,
'ensuremath': self.r_inline_math,
'equation': self.r_display_math,
'eqnarray': self.r_align,
'multline': self.r_align,
'align': self.r_align,
'alignat': self.r_align,
'gather': self.r_gather,
#lists
'itemize': self.r_itemize,
'enumerate': self.r_enumerate,
'description': self.r_description,
#quotes
'quotation': self.r_quotes,
'quote': self.r_quotes,
'verse': self.r_verse,
'footnote': self.r_footnote,
#labels
'label': self.r_label,
'ref': self.r_ref,
'vref': self.r_ref,
'pageref': self.r_ref,
'eqref': self.r_ref,
#accents
"accented_letter": self.r_accented_letter,
+ #figures
+ "figure": self.r_figure
}
#register plugins
self.register_plugins(configs["plugins"])
#tree object
self.tree = PageTree(configs)
#parameter for list formatting
self.list_level = ''
#parameters for theorem handling
self.in_theorem = False
self.theorem_number = 0
self.th_numbering = {}
########################################
#STARTING POINT
def start_rendering(self, root_block):
"""starting rendering from root-block"""
#start rendering of base class
super(MediaWikiRenderer, self).start_rendering(root_block)
self.render_block(root_block)
#after rendering
self.tree.after_render()
#end rendering of base class
super(MediaWikiRenderer, self).end_rendering()
####### ROOT BLOCK
def r_document(self, block):
#we trigger the rendering of content
text = self.render_children_blocks(block)
#text is the tex outside sections
self.tree.addText(text)
#returning the text to respect the interface
return text
########################################
#DEFAULT
def default(self, block):
#we don't print anything
return ''
#########################################
#TEXT
def r_text(self, block):
text = block.attributes['text']
# The following replace happens as ~ is the latex symbol
# for unbreakable space
return text.replace("~", " ")
def r_newline(self, block):
return '\n'
def r_newpage(self, block):
return '\n\n'
def r_par(self, block):
return '\n\n'
#########################################
#SECTIONING
def sectioning(self, block):
title = block.attributes['title']
section_name = block.attributes['section_name']
#remove the \n insiede title
title = re.sub('\\n*', '', title)
#creation of the new page
self.tree.createPage(title, section_name)
#content processing
text = self.render_children_blocks(block)
#adding text to current page
self.tree.addText(text)
#exiting the section
self.tree.exitPage()
return ''
#########################################
#MATH
def r_display_math(self, block):
s = block.attributes['content']
#rendering labels
self.render_blocks(block.labels)
return ''
def r_inline_math(self, block):
s = block.attributes['content']
#rendering labels
self.render_blocks(block.labels)
return ''
def r_align(self, block):
s = block.attributes['content']
#rendering labels
self.render_blocks(block.labels)
return ''
def r_gather(self, block):
s = block.attributes['content']
output = []
for eq in s.split("\\\\"):
eq = eq.replace("\n","").strip()
output.append('')
#rendering labels
self.render_blocks(block.labels)
return '\n'.join(output)
#########################################
#LABELS and refs
def r_label(self, block):
label = block.attributes['label']
self.tree.addLabel(label)
return ''
def r_ref(self, block):
ref = block.attributes['ref']
#saving ref in Babel of PageTree
self.tree.addReference(ref)
return "{{ref@"+ ref+ "}}"
+ #########################################
+ #FIGURE
+
+ def r_figure(self, block):
+ captions = block.get_children("caption")
+ includegraphics = block.get_children("includegraphics")
+ s = "[[File:"
+ if len(includegraphics):
+ inc = includegraphics[0]
+ s += inc.attributes["img_name"]
+ else:
+ return ""
+ if len(block.get_children("centering")):
+ s += "|" + self.configs["keywords"]["center"]
+
+ if len(captions):
+ cap = captions[0]
+ s += "|" + cap.attributes["caption"]
+ s += "]]"
+ return s;
+
+
+
#########################################
#FORMATTING
def r_special_character(self, block):
return block.attributes['character']
def r_dots(self, block):
return '...'
def r_textbf(self, block):
s = []
s.append("\'\'\'")
s.append(self.render_children_blocks(block))
s.append("\'\'\'")
return ''.join(s)
def r_textit(self, block):
s = []
s.append("\'\'")
s.append(self.render_children_blocks(block))
s.append("\'\'")
return ''.join(s)
def r_textsc(self, block):
return self.render_children_blocks(block).upper()
def r_superscript(self, block):
s = []
s.append('')
s.append(self.render_children_blocks(block))
s.append('')
return ''.join(s)
def r_subscript(self, block):
s = []
s.append('')
s.append(self.render_children_blocks(block))
s.append('')
return ''.join(s)
def r_underline(self, block):
s = []
s.append('{{Sottolineato|')
s.append(self.render_children_blocks(block))
s.append('}}')
return ''.join(s)
def r_abstract(self, block):
s = []
s.append('{{Abstract|')
s.append(self.render_children_blocks(block))
s.append('}}')
return ''.join(s)
def r_break(self, block):
return ''
def r_vspace(self,block):
return '\n\n'
def r_mandatory_space(self,block):
return ' '
def r_verbatim(self, block):
return '' + block.attributes['content'] +'
'
def r_verb(self, block):
return '' + block.attributes['content'] +''
#########################################
#ALIGNMENT
def r_center(self, block):
s = []
s.append('{{Center|')
s.append(self.render_children_blocks(block))
s.append('}}')
return ''.join(s)
def r_flushleft(self, block):
s = []
s.append('{{Flushleft|')
s.append(self.render_children_blocks(block))
s.append('}}')
return ''.join(s)
def r_flushright(self, block):
s = []
s.append('{{Flushright|')
s.append(self.render_children_blocks(block))
s.append('}}')
return ''.join(s)
#########################################
#LISTS
def r_itemize(self, block):
self.list_level += '*'
s = ['\n']
for item in block.ch_blocks:
s.append(self.list_level)
s.append(self.render_children_blocks(item).strip())
s.append("\n")
self.list_level = self.list_level[:-1]
return ''.join(s)
def r_enumerate(self, block):
self.list_level += '#'
s = ['\n']
for item in block.ch_blocks:
s.append(self.list_level)
s.append(self.render_children_blocks(item).strip())
s.append("\n")
self.list_level = self.list_level[:-1]
return ''.join(s)
def r_description(self, block):
s = ['\n']
for item in block.ch_blocks:
s.append(';')
s.append(item.attributes['word'])
s.append(':')
s.append(self.render_children_blocks(item))
s.append("\n")
return ''.join(s)
#########################################
#QUOTES
def r_quotes(self, block):
s = []
s.append('')
s.append(self.render_children_blocks(block))
s.append('
')
return ''.join(s)
def r_verse(self, block):
s = []
s.append('')
s.append('\n'.join(self.render_children_blocks(block).split('//')))
s.append('
')
return ''.join(s)
def r_footnote(self, block):
s = []
s.append("[")
s.append(self.render_children_blocks(block))
s.append("]")
return ''.join(s)
#########################################
#Theorems
def r_theorem(self, block):
#the label in theorems is not working for now
th_definition = block.attributes['definition']
th_title = ''
if block.attributes['title'] != None:
th_title +=" "+ block.attributes['title']
s = []
#adding the theorem to the tree
self.theorem_number += 1
self.tree.addTheorem(str(self.theorem_number), th_definition)
#checking if the Environment template is used
environ = False
if self.configs['lang'] =='it':
if th_definition.lower() == 'teorema':
#adding content to page through a template
s.append("\n{{InizioTeorema|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineTeorema}}\n")
elif th_definition.lower() == 'definizione':
s.append("\n{{InizioDefinizione|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineDefinizione}}\n")
elif th_definition.lower() == 'proposizione':
s.append("\n{{InizioProposizione|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineProposizione}}\n")
elif th_definition.lower() == 'lemma':
s.append("\n{{InizioLemma|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineLemma}}\n")
elif th_definition.lower() == 'corollario':
s.append("\n{{InizioCorollario|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineCorollario}}\n")
elif th_definition.lower()[:-2] == 'eserciz':
s.append("\n{{InizioEsercizio|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineEsercizio}}\n")
elif th_definition.lower()[:-1] == 'osservazion':
s.append("\n{{InizioOsservazione|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineOsservazione}}\n")
elif th_definition.lower()[:-2] == 'esemp':
s.append("\n{{InizioEsempio|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineEsempio}}\n")
elif th_definition.lower() == 'dimostrazione':
s.append("\n{{InizioDimostrazione|titolo=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{FineDimostrazione}}\n")
else:
s.append("\n{{Environment|name="+ th_definition + \
"|title=" + th_title +\
"|content=")
s.append(self.render_children_blocks(block))
s.append("}}\n")
elif self.configs['lang'] =='en':
if th_definition.lower() == 'theorem':
#adding content to page through a template
s.append("\n{{BeginTheorem|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndTheorem}}\n")
elif th_definition.lower() == 'definition':
s.append("\n{{BeginDefinition|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndDefinition}}\n")
elif th_definition.lower() == 'proposition':
s.append("\n{{BeginProposition|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndProposition}}\n")
elif th_definition.lower() == 'lemma':
s.append("\n{{BeginLemma|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndLemma}}\n")
elif th_definition.lower() == 'corollary':
s.append("\n{{BeginCorollary|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndCorollary}}\n")
elif th_definition.lower() == 'exercise':
s.append("\n{{BeginExercise|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndExercise}}\n")
elif th_definition.lower() == 'observation':
s.append("\n{{BeginObservation|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndObservation}}\n")
elif th_definition.lower() == 'remark':
s.append("\n{{BeginRemark|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndRemark}}\n")
elif th_definition.lower() == 'example':
s.append("\n{{BeginExample|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndExample}}\n")
elif th_definition.lower() == 'demonstration':
s.append("\n{{BeginDemonstration|title=" + \
th_title+"|number={{thnum@"+ str(self.theorem_number)+"}}"+\
"|anchor={{thanchor@"+ str(self.theorem_number) +"}}}}")
s.append(self.render_children_blocks(block))
s.append("{{EndDemonstration}}\n")
else:
s.append("\n{{Environment|name="+ th_definition + \
"|title=" + th_title +\
"|content=")
s.append(self.render_children_blocks(block))
s.append("}}\n")
#exit from theorem ambient
self.tree.exitTheorem()
return '\n'.join(s)
def r_proof(self, block):
s=[]
if self.configs['lang'] == 'it':
if block.title !=None:
s.append('\n{{InizioDimostrazione|titolo='+\
block.attributes['title']+ "}}")
s.append(self.render_children_blocks(block))
s.append("{{FineDimostrazione}}\n")
else:
s.append('\n{{InizioDimostrazione}}')
s.append(self.render_children_blocks(block))
s.append("{{FineDimostrazione}}\n")
elif self.configs['lang'] == 'en':
if block.title !=None:
s.append('\n{{BeginProof|title='+\
block.attributes['title']+"}}")
s.append(self.render_children_blocks(block))
s.append("{{EndProof}}\n")
else:
s.append('\n{{BeginProof}}')
s.append(self.render_children_blocks(block))
s.append("{{EndProof}}\n")
return '\n'.join(s)
#########################################
#ACCENTED letters
def r_accented_letter(self, block):
if block.attributes["accent_type"] == '"' \
and block.attributes["letter"] == "a":
return "รค"
if block.attributes["accent_type"] in ["'","`"]:
return block.attributes["letter"]+\
block.attributes["accent_type"]
else:
return block.attributes["letter"]
diff --git a/texla/Renderers/Renderer.py b/texla/Renderers/Renderer.py
index 1d56299..e127439 100644
--- a/texla/Renderers/Renderer.py
+++ b/texla/Renderers/Renderer.py
@@ -1,185 +1,178 @@
from ..Parser import Blocks
from ..Parser.TreeExplorer import TreeExplorer
import logging
import importlib
class Renderer():
- def __init__(self):
+ def __init__(self, reporter):
+ self.reporter = reporter
#hooks implemented directly by the Renderer class.
self.render_hooks = {}
#plugins hooks
self.pre_render_hooks = {}
self.post_render_hooks = {}
self.start_hooks = []
self.end_hooks = []
self.loaded_plugins = {}
- self.used_tags = {}
self.tree_explorer = None
def register_plugins(self, plugins):
for plugin in plugins:
module = importlib.import_module("..plugins"+'.'+ plugin, __name__)
if hasattr(module, "plugin_render_hooks"):
self.loaded_plugins[plugin] = module
self.register_render_plugin_hooks(module.plugin_render_hooks)
- logging.info("Renderer.register_plugins "\
+ logging.debug("Renderer.register_plugins "\
"@ Loaded plugin: {}".format(plugin))
logging.debug("Plugin {} render hooks: {}".format( plugin,
list(module.plugin_render_hooks.keys())))
if hasattr(module, "plugin_lifecycle_hooks"):
self.register_lifecyle_plugin_hooks(module.plugin_lifecycle_hooks)
- logging.info("Plugin {} lifecycle hooks: {}".format( plugin,
+ logging.debug("Plugin {} lifecycle hooks: {}".format( plugin,
list(module.plugin_lifecycle_hooks.keys())))
def register_render_plugin_hooks(self, hooks):
'''This function registers the hooks for renderer plugins.
The plugins can define hooks for pre and post render actions.
The pre hook receives the block before the rendering and can
only return the block itself, modified.
The post hook receive the block and the text from the renderer:
it has to return the final text only.
The keyword ALL creates a hooks for all the blocks.
Note that it is always called after all the other hooks.'''
for bl in hooks:
if "pre" in hooks[bl]:
self.register_pre_renderer_hook(bl, hooks[bl]["pre"])
if "post" in hooks[bl]:
self.register_post_renderer_hook(bl, hooks[bl]["post"])
#checking ALL keyword
if "ALL" in hooks:
if "pre" in hooks["ALL"]:
self.register_pre_renderer_hook(bl, hooks["ALL"]["pre"])
if "post" in hooks["ALL"]:
self.register_post_renderer_hook(bl, hooks["ALL"]["post"])
def register_lifecyle_plugin_hooks(self, hooks):
''' This function registers the hooks for the renderer lifecycle.
Plugins can register hooks for the start and end actions.
The start hook is called with the root_block of the chain.
The end hook is called without arguments. These hooks must be used
only to signal the actions to the plugins.'''
if "start" in hooks:
self.register_start_hook(hooks["start"])
if "end" in hooks:
self.register_end_hook(hooks["end"])
def register_pre_renderer_hook(self, block, hook):
if block not in self.pre_render_hooks:
self.pre_render_hooks[block] = []
self.pre_render_hooks[block].append(hook)
def register_post_renderer_hook(self, block, hook):
if block not in self.post_render_hooks:
self.post_render_hooks[block] = []
self.post_render_hooks[block].append(hook)
def register_start_hook(self, hook):
self.start_hooks.append(hook)
def register_end_hook(self, hook):
self.end_hooks.append(hook)
def start_rendering(self, root_block):
'''This function create a TreeExplorer instance
and passes it to the plugin that has the variable
needs_tree_explorer=True. Then it starts the plugins'''
self.tree_explorer = TreeExplorer(root_block)
#passing the tree_explorer
for pl in self.loaded_plugins.values():
if hasattr(pl, "needs_tree_explorer"):
if pl.needs_tree_explorer:
logging.debug("Renderer @ Inserting "\
"TreeExplorer into plugin {}".format(pl))
pl.tree_explorer = self.tree_explorer
#starting the plugins
for hook in self.start_hooks:
hook(root_block)
def end_rendering(self):
#ending plugins
for hook in self.end_hooks:
hook()
def render_children_blocks(self, block, collapse=True):
'''This is one of the most important funciont
of the rendering process.
This function takes all the children blocks of
a block and get they rendering output.
If collapsed=True it returns a unique string,
otherwise it returns a list of tuples with[(block_name, output)]
'''
output = []
for bl in block.ch_blocks:
#it's not necessary checking for renderer_hook
#because default hook is mandatory
output.append((bl.block_name, self.render_block(bl)))
- logging.debug('Render.ch_blocks @ %s', output)
if collapse:
return ''.join([x[1] for x in output])
else:
return output
def render_block(self, bl):
'''This function calls the right render_hook for
the block. If there isn't an hook it calld the default,
that is mandatory'''
output = ""
######### pre hooks ############
#hooks executed in the order of inserction
#They receive the block and they can only modify the block object
if bl.block_name in self.pre_render_hooks:
for prehook in self.pre_render_hooks[bl.block_name]:
#calling prehook with the block
prehook(bl)
#calling after the others the ALL hooks
if "ALL" in self.pre_render_hooks:
for prehook in self.pre_render_hooks["ALL"]:
#calling prehook with the block
prehook(bl)
######## rendering #############
if bl.block_name in self.render_hooks:
- self.used_tag('ok | ' + bl.block_name)
logging.debug('Render @ block: ' + bl.block_name)
output = self.render_hooks[bl.block_name](bl)
else:
#default hook is mandatory
- self.used_tag('default | ' + bl.block_name)
logging.debug('Render @ block: default@' + bl.block_name)
+ #reporting to the Reporter
+ if bl.block_name != "default":
+ self.reporter.add_not_rendered_block(bl)
output = self.render_hooks['default'](bl)
######## post hooks ###########
#hooks executed in the order of inserction.
#They receive the block and text. They have to return the
#output text, that is passed to the next posthook
if bl.block_name in self.post_render_hooks:
for posthook in self.post_render_hooks[bl.block_name]:
#calling posthook with the block and output
output = posthook(bl, output)
#calling ALL hooks after the others
if "ALL" in self.post_render_hooks:
for posthook in self.post_render_hooks["ALL"]:
#calling posthook with the block and output
output = posthook(bl, output)
#final output
return output
def render_blocks(self, bls, collapse=False):
'''This function renderes a list of blocks.
It's the same as render_children_blocks but
with a generic list'''
output = []
for bl in bls:
output.append((bl.block_name,self.render_block(bl)))
if collapse:
return ''.join([x[1] for x in output])
else:
return output
-
- #Utils for debug
- def used_tag(self, tag):
- if tag in self.used_tags:
- self.used_tags[tag] += 1
- else:
- self.used_tags[tag] = 1
diff --git a/texla/Renderers/plugins/math_check_online.py b/texla/Renderers/plugins/math_check_online.py
index 3e3777a..b75cfbd 100644
--- a/texla/Renderers/plugins/math_check_online.py
+++ b/texla/Renderers/plugins/math_check_online.py
@@ -1,110 +1,110 @@
import requests
import logging
from multiprocessing import Process, Pool, Queue
from os import path
def request_formula(tex):
url_check = 'http://restbase.wikitolearn.org/pool.wikitolearn.org/v1/media/math/check/tex'
# url_check = 'http://restbase.tuttorotto.biz/pool.tuttorotto.biz/v1/media/math/check/tex'
header = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
payload = {'q': tex}
r = requests.post(url_check, data=payload, headers=header)
if r.status_code == 200:
return True
else:
return False
formulas = []
bad_formulas = Queue()
def save_math(block):
tex = block.attributes["content"]
#saving the formula only if it's longer than 10
- if len(tex) > 10:
+ if len(tex) > 5:
logging.debug("Plugin math_check_online @ saving formula {}".format(
tex))
formulas.append((tex, block.id))
def save_math_align(block):
tex = "\\begin{align}" + block.attributes["content"] + "\\end{align}"
#saving the formula only if it's longer than 10
if len(tex) > 50:
logging.debug("Plugin math_check_online @ saving formula {}".format(
tex))
formulas.append((tex, block.id))
def check_math(formula):
ok = request_formula(formula[0])
if ok:
logging.info("Plugin math_check_online @ formula {}, block_id: {}".
format("OK", formula[1]))
else:
logging.error("Plugin math_check_online @ formula {}, block_id: {}".
format("BAD", formula[1]))
bad_formulas.put(formula)
def start_pool():
pool = Pool(processes=6)
logging.info("Plugin math_check_online @ total formulas to check: {}".
format(len(formulas)))
pool.map(check_math, formulas)
#saving results
logging.info("GOOD FORMULAS: {} --- BAD FORMULAS: {}".format(
len(formulas)-bad_formulas.qsize(), bad_formulas.qsize()))
log_matherrors_file_path = path.relpath("sandbox/math_errors.txt")
with open(log_matherrors_file_path, "w") as f:
f.write("Math Errors Tree Log: \n")
f.write("---------------------\n")
ids = []
while not bad_formulas.empty():
form = bad_formulas.get()
ids.append(form[1])
output = tree_explorer.print_tree_to_blocks(ids)
f.write(output + "\n\n")
def start_check():
p = Process(target=start_pool)
p.start()
plugin_render_hooks = {
'displaymath': {
"pre": save_math
},
'inlinemath': {
"pre": save_math
},
'ensuremath': {
"pre": save_math
},
'equation': {
"pre": save_math
},
'eqnarray': {
"pre": save_math_align
},
'multline': {
"pre": save_math_align
},
'align': {
"pre": save_math_align
},
'alignat': {
"pre": save_math_align
}
}
plugin_lifecycle_hooks = {"end": start_check}
needs_tree_explorer = True
tree_explorer = None
diff --git a/texla/Renderers/plugins/spaces_check.py b/texla/Renderers/plugins/spaces_check.py
index bd1cf39..01dbf34 100644
--- a/texla/Renderers/plugins/spaces_check.py
+++ b/texla/Renderers/plugins/spaces_check.py
@@ -1,16 +1,16 @@
import logging
import re
def check_space(block, text):
- logging.debug("Plugin spaces_check @ checking output of block {}".
- format(block.id))
+ #logging.debug("Plugin spaces_check @ checking output of block {}".
+ # format(block.id))
r = re.compile(r'\n[ ]*')
return r.sub("\n", text)
plugin_render_hooks = {
'ALL' : {
'post': check_space
}
}
diff --git a/texla/Reporter.py b/texla/Reporter.py
new file mode 100644
index 0000000..58ac3a0
--- /dev/null
+++ b/texla/Reporter.py
@@ -0,0 +1,40 @@
+from .Parser.TreeExplorer import TreeExplorer
+import logging
+
+class Reporter:
+
+ def __init__(self, tree):
+ self.tree_explorer = tree
+ #registering the block_names
+ self.tree_explorer.register_block_names()
+ self.not_parsed_blocks = self.tree_explorer.block_names["default"]
+ self.not_rendered_blocks = []
+ self.not_parsed_types = {}
+ self.not_rendered_types = {}
+ for bl in self.not_parsed_blocks:
+ if bl.type not in self.not_parsed_types:
+ self.not_parsed_types[bl.type] = []
+ self.not_parsed_types[bl.type].append(bl)
+
+
+ def add_not_rendered_block(self, block):
+ """This method saves a block that is not rendered by the Renderer."""
+ self.not_rendered_blocks.append(block)
+ if not block.block_name in self.not_rendered_types:
+ self.not_rendered_types[block.block_name] = []
+ self.not_rendered_types[block.block_name].append(block)
+
+ def print_report(self, console=True):
+ logging.info('\033[0;34m############### TEXLA REPORT ###############\033[0m')
+ s = []
+ s.append("\n- NOT PARSED blocks:")
+ for bl, v in self.not_parsed_types.items():
+ s.append("\t- {} : {}".format(bl, len(v)))
+ s.append("\n- NOT RENDERED blocks:")
+ for bl, v in self.not_rendered_types.items():
+ s.append("\t- {} : {}".format(bl, len(v)))
+ text= "\n".join(s)
+ if console:
+ logging.info(text)
+ with open("sandbox/texla_report.txt",'w') as file:
+ file.write(text)