diff --git a/sandbox/.placeholder b/sandbox/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/texla/PageTree/Babel.py b/texla/PageTree/Babel.py index de3c558..4ece293 100644 --- a/texla/PageTree/Babel.py +++ b/texla/PageTree/Babel.py @@ -1,80 +1,87 @@ import logging class Babel: #Label babel - def __init__(self): + def __init__(self, reporter): self.refs = {} self.anchors = {} + self.reporter = reporter def add_label(self, label, anchor): ''' This method adds a label and its anchor to the babel. The label is unique but can be overwritten. ''' if label in self.anchors: logging.warning("Babel @ label: {} already present".format(label)) #saving the anchor that has to be unique self.anchors[label] = anchor logging.debug("Babel @ Adding label: \"{}\" to anchor: {}". format(label, anchor)) def add_reference(self, label, ref): ''' This method adds a reference to the label. A reference is a page or in general an object with .text properties. The babel will fix the reference of the registered objects. ''' #we don't check if label exist because #the process is asynchronous" if label not in self.refs: self.refs[label] = [] self.refs[label].append(ref) logging.debug("Babel @ Adding ref: {}, to label: \"{}\"". format(ref, label)) def move_anchor(self, oldanc, newanc): '''This function replace the references to oldanc with newanc, both as anchor and ref. It is used mainly when a page is moved''' new_anchors = {} for label, anc in self.anchors.items(): if anc == oldanc: new_anchors[label] = newanc self.anchors.update(new_anchors) new_refs = {} for label, ref in self.refs.items(): if ref == oldanc: new_refs[label] = newanc self.refs.update(new_refs) def fix_references(self): ''' This method will fix the reference in the objects saved under self.refs. The text {{ref:label}} in the objects' .text properties will be replaces by a url made of [url|title]. The url and the title MUST be properties of the anchor saved. + Finally this method will send to the reporter the references having a + label without anchor. ''' #iterating over anchor to fix only the right labels #and ignoring the missing ones for label in self.anchors: obj = self.anchors[label] title = obj.title url = obj.url if url is None and title is None: continue elif url is None and title is not None: replace_string = title elif url is not None and title is None: replace_string = "[["+ url + "]]" else: replace_string = "[[{}|{}]]".format(url,title) #checking if the babel has refs if label not in self.refs: continue #iterating over all refs for ref in self.refs[label]: logging.debug("Babel @ Fixing ref to label: \"{}\", from page {} to page: {}". format(label,ref, obj)) ref.text = ref.text.replace("{{ref@"+ label +"}}", replace_string) + #checking references without anchors + for label in self.refs: + if label not in self.anchors: + self.reporter.add_missing_anchor(label, self.refs[label]) diff --git a/texla/PageTree/Page.py b/texla/PageTree/Page.py index d2aa2a4..8d5e625 100644 --- a/texla/PageTree/Page.py +++ b/texla/PageTree/Page.py @@ -1,218 +1,218 @@ # -*- coding: utf-8 -*- import re import logging from ..Parser.Blocks.Utilities import * class Page(): """ Class that manages the pages content. Data members of Page -self.id = randon id of the page -self.title is the title normalized for urls -self.subpages contains the list of the subpages objects -self.level memorize the level of the page.(root=-1)) -self.url contains the unique internal url of the page -self.type is 'root',part,chapter,section,subsection,subsubection,paragraph. -self.keywords is a dictionary with localized keywords for output""" def __init__(self,title, page_type, level, keywords ): self.id = utility.get_random_string(8) self.title = title self.type = page_type self.keywords = keywords #contains the page text self.text = '' self.collapsed = False #list of subpages objects self.subpages = [] self.parent = None self.level = level def addText(self,text): self.text = text.strip() def addSubpage(self, page, after=None): """This methods add a subpage refreshing the levels of ALL subpages. It sets also the parent of the subpage""" if after: i = self.subpages.index(after) self.subpages.insert(i+1, page) else: self.subpages.append(page) #setting level page.refresh_level(self.level+1) #setting parent page.parent = self def addSubpages(self, pages, after=None): """This function add a list of subpages, setting levels and parent page.""" if after: i = self.subpages.index(after) +1 self.subpages = self.subpages[:i] + pages +\ self.subpages[i:] else: self.subpages += pages #setting level and parent of subpages for p in pages: p.refresh_level(self.level+1) p.parent = self def addSubpage_top(self, page): """This function add a subpage before all the others.""" self.subpages.insert(0,page) page.parent = self def removeSubpage(self, page): """This function removes the subpage recursively looking also at subpages""" if page in self.subpages: self.subpages.remove(page) page.parent = None else: for p in self.subpages: p.removeSubpage(page) def isSubpage(self,page): return page in self.subpages def get_subpages(self): """This function returns a list with all the subpages of the current page walking the subtree KEEPING THE ORDER (REALLY IMPORTANT): -subpage: --subsub1 --subsub2: ---subsubsub -subpage2... => [subpage, subsub1, subsub2, subsubsub, subpage2, ...]""" subpag = [] for p in self.subpages: subpag.append(p) subpag += p.get_subpages() return subpag def refresh_level(self, new_level): """This function change the level of this page refreshing recursively all the subpages""" self.level = new_level for p in self.subpages: p.refresh_level(self.level+1) def after_render(self): """This function does some fixes after rendering""" #first of all the text is fixed self.fix_text_characters() #check math inside titles self.math_inside_title = self.is_math_inside_title() def collapseSubpagesText(self, level=0): """ This method insert the text of subpages in this page and returns the complete text.""" for subpage in self.subpages: t = subpage.collapseSubpagesText(level+1) #add text self.text+= '\n'+t if level == 0: if '' in self.text: #added refs tags to show footnotes self.text+='\n{{Notes}}' else: #Creation of current page title tit = '\n'+'='+'='*(level)+self.title+ \ '='*(level)+'=' self.text = tit+ "\n"+ self.text #return the text return self.text def collapseURL(self, base_url): """This functions creates the url of the page checking if it is collapsed. Then it continues with the subpages""" if self.collapsed: self.url = base_url + '#' + self.title for p in self.subpages: p.collapseURL(base_url) else: if base_url != '': self.url = base_url + '/' + self.title else: self.url = self.title for p in self.subpages: p.collapseURL(self.url) def create_pagenumbers(self, parent, current): """This function creates the pagenumber string appending to the parent number its position in the pages of the same level. Then the process continues with subpages""" if parent != None: self.pagenumber = parent+ ".{}".format(current) else: self.pagenumber = str(current) i = 1 for page in self.subpages: page.create_pagenumbers(self.pagenumber, i) i += 1 def fix_text_characters(self): """Utility function to fix apostrophes and other characters inside the text of the page""" #fix for double apostrophes quotes s = re.findall(u'(\`\`)\s?(.*?)\s?(\'\')', self.text, re.DOTALL) for item in s: self.text = self.text.replace(item[0],'"') self.text = self.text.replace(item[2],'"') s2 = re.findall(u'(\‘\‘)\s?(.*?)\s?(\’\’)', self.text, re.DOTALL) for item2 in s2: self.text = self.text.replace(item2[0],'"') self.text = self.text.replace(item2[2],'"') #apostrophe fixed self.text = self.text.replace(u'’',u"'") self.text = self.text.replace(u'`',u"'") def is_math_inside_title(self): """This function checkes if there is math inside titles""" mre = re.search(r'(?2: s['is_page'] = False else: s['is_page'] = True s['text'] = self.text[:100] s['children'] = [] for page in self.subpages: s['children'].append(page.get_json_dictionary(pages)) return s def get_str(self): a = ' [C]' if self.collapsed else '' return '('+ str(self.level)+')'+'---'*self.level +\ '> '+ self.title + a def __str__(self): s =[] - s.append('title='+self.title) + s.append('title="'+self.title+'"') if hasattr(self, "url"): - s.append('url='+self.url) - s.append('subpages='+str(self.subpages)) + s.append('url="'+self.url + '"') + s.append('subpages='+str(len(self.subpages))) s.append('level='+str(self.level)) s.append('collapsed='+ str(self.collapsed)) return ' '.join(s) diff --git a/texla/PageTree/PageTree.py b/texla/PageTree/PageTree.py index 1152620..fe077a8 100644 --- a/texla/PageTree/PageTree.py +++ b/texla/PageTree/PageTree.py @@ -1,326 +1,327 @@ from .Page import Page from .Babel import Babel from .TheoremsManager import * import re, os, json class PageTree(): - def __init__(self, configs): + def __init__(self, configs, reporter): self.configs = configs + self.reporter = reporter self.doc_title = configs['doc_title'] self.keywords = configs['keywords'] self.output_path = configs['output_path'] #pages Data {id: page} self.pages = {} #id : titles self.titles = {} #label manager - self.babel = Babel() + self.babel = Babel(reporter) #theorems manager self.theorems_manager = TheoremsManager(self.pages) #urls (they are created after collapsing). #it's a dictionary id:url self.urls = {} #ROOT PAGE ro = Page(self.doc_title, 'root', -1, self.keywords) self.root_id = ro.id self.root_page = ro self.pages[self.root_id] = ro self.titles[self.root_id] = ro.title #indexes self.pageid_stack = [ro.id] self.current_page_id = self.root_id #the anchor is the object to be referentiated by labels self.current_anchor = ro def createPage(self, title, page_type): """This method creates a new page and enters in his enviroment setting current variables""" title = self.get_normalized_title(title) #finding level level = len(self.pageid_stack) - 1 #create new page p = Page(title, page_type, level, self.keywords) #add page to pages index self.pages[p.id] = p self.titles[p.id] = p.title #adding the page as subpage of the current page self.pages[self.current_page_id].addSubpage(p) #updates current self.pageid_stack.append(p.id) self.current_page_id = p.id self.current_anchor = p def exitPage(self): """Return to the parent page enviroment""" self.current_page_id = self.pageid_stack[-2] self.pageid_stack.pop() self.current_anchor = self.pages[self.current_page_id] def addText(self, text): self.pages[self.current_page_id].addText(text) def addLabel(self, label): """adding label to the babel with the current page as the anchor""" self.babel.add_label(label, self.current_anchor) def addReference(self, label): """adding the current_anchor as a reference for the requesting label""" self.babel.add_reference(label, self.current_anchor) def addTheorem(self, id, th_type): """Adding a theorem also as anchor""" th = Theorem(id,self.current_anchor, th_type) self.theorems_manager.addTheorem(th) #setting current anchor on the theorem self.current_anchor = th def exitTheorem(self): """Removing the anchor from the theorem and setting it to the last used page""" self.current_anchor = self.pages[self.current_page_id] @staticmethod def get_normalized_title(title): """Function that removes bad symbols from title""" title = title.replace('$', '') title = title.replace('{','') title = title.replace('}','') title = title.replace('\\mathcal','') title = title.replace('\\mathbf','') title = title.replace('\\mathbb','') title = title.replace('\\ensuremath','') title = title.replace('&', 'e') title = title.replace('\\', '') title = title.replace('/', '_') title = title.replace('>', 'gt') title = title.replace('<', 'lt') title = title.replace(':',' ') title = title.replace('.',' ') title = title.replace(',',' ') title = title.replace(';',' ') return title def get_tree_json(self): """This function return the json tree""" return self.root_page.get_json_dictionary(self.pages) def get_tree_debug(self): """This function prints the tree for debug""" s = [] for p in self.root_page.get_subpages(): s.append(p.get_str()) return('\n'.join(s)) def after_render(self): """This function does some fixes after rendering""" for page in self.pages.values(): page.after_render() def change_title(self, page_id, title): self.pages[page_id].title = title def remove_page_from_tree(self, page, parent=None): """This function remove a page from the tree, but doesn't delete it. The page remains in the self.pages dictionary but not in the subpages of the pages in the tree. If a parent page is passed the research for the removal starts from that page with performance improvements""" if parent: parent.removeSubpage(page) else: self.root_page.removeSubpage(page) def move_page_references(self, oldpage, newpage): """This function fixes the reference in TheoremsManager and Babel when a page is moved""" #we need to fix anchors in Babel self.babel.move_anchor(oldpage, newpage) #we need also to fix the theorems page self.theorems_manager.move_theorems_page(oldpage, newpage) def collapse_tree(self, content_level, max_page_level): """This function contains all the tree collapsing procedures in the order: 1) Mark the pages for the content collapsing without actually move the text 2) Fix the tree order with collapsing of page level (N.B.: it needs the collasped status of pages) 3) Fix the urls now that the level if fixed. 4) Create the pagenumber of every page, after the movement in the tree. 5) The theorems are fixed adding the right numbering. 6) Fix references to labels: the Babel will change pages content so this has to be done after the url fixing but before the actual text collapsing. 7) Finally collapse the pages text to the right content level""" self.collapse_content_level(content_level) self.collapse_page_level(max_page_level) self.collapse_urls() self.create_pagenumbers() self.theorems_manager.fix_theorems() #ask the babel to fix the refs to labels in all the pages self.babel.fix_references() #collapse the text in the right pages self.collapse_content_level_text(content_level) def collapse_content_level(self, max_level): """This function marks pages with level higher than choosen level to be collapsed. It DOESN'T move the text.""" for p in self.pages.values(): if p.level > max_level: p.collapsed = True def collapse_content_level_text(self, max_level): """This function collapses the content of the pages at the choosen level. The content of the pages with level higher than max_level is moved up to the tree to the page with the max_level, creating titles in the page text. The pages touched are marked as collapsed=True.""" for p in self.pages.values(): if p.level == max_level: p.collapseSubpagesText() def collapse_page_level(self, max_level): """This function fixes the level of the pages in the index according to a max_level. Pages with a level higher than the max_level are moved up in the tree till the max_level. The order related to parent pages is mantained. The PageTree is rewrited, hierarchy and levels are fixed. Moreover the level=0 is a special level and it's content is moved to an intro page, because level=0 pages must contain the index of their subpages. """ #PAGES LEVEL = 0 #If they contain text we have to create a new page #called introduction (localized) for p in [x for x in self.pages.values() if x.level==0]: if len(p.text)>0: #creating new page for text inside text page. p_intro = Page(self.keywords['intro'], 'section',1, self.keywords) p_intro.text = p.text #saving the intro page self.pages[p_intro.id] = p_intro self.titles[p_intro.id] = p_intro.title p.addSubpage_top(p_intro) #erasing text from section page p.text = '' #fixing page references self.move_page_references(p, p_intro) #Now we move pages according to the max_level. #pages not collapsed and with higher level then #the max_level are moved as subpages of the #nearest max_level page. for p in [x for x in self.pages.values() if x.level==max_level]: parent_page = p.parent #list of subpages to move at the right level subpages_to_add = [] #now we are cycling on the pages with level>max_level for sp in p.get_subpages(): if not sp.collapsed: #removing page from the tree acting #directly on the parent page sp.parent.removeSubpage(sp) #saving the page for the movement subpages_to_add.append(sp) #adding the list of moved subpages to the parent_page #so getting the right level. parent_page.addSubpages(subpages_to_add, p) ###NB: remember that the subpages level #is AUTOMATICALLY refreshed for all pages added. def collapse_urls(self): """This function creates the urls of the pages, checking is they are collapsed or not. If they are collapsed the url is parent_page#title. Then the references are resolved to urls throught labes""" self.root_page.collapseURL(self.configs['base_path']) def create_pagenumbers(self): """Every page will have a pagenumber like 1.2.1""" self.root_page.pagenumber = "0" i = 1 for pages in self.root_page.subpages: pages.create_pagenumbers(None, i ) i += 1 def create_indexes(self, export_book_page=False): """This function create sections index and book total index""" self.create_sections_index() self.create_book_index(export_book_page=False) def create_sections_index(self): """This function create the index for the sections (level=0) pages""" for page in self.pages.values(): if page.level == 0: index = [] for p in page.get_subpages(): if not p.collapsed: if len(p.text) >0: index.append('*'*p.level+ \ '[[' + p.url + '|' + p.title + ']]') else: index.append('*'*p.level+ p.title ) #adding section category index.append("[[Category:CourseLevelTwo]]") page.text = '\n'.join(index) def create_book_index(self, export_book_page=False): """This function create the book total index and the book export page index""" base_page = self.root_page #book export: link book_url = self.doc_title.replace(' ','_') #creating root index index = ["{{CourseRoot|"] if export_book_page: book_export_index = ['{{libro_salvato | setting-papersize = a4\ | setting-toc = auto | setting-columns = 1}}'] #book export: setting title book_export_index.append('==' + self.doc_title + '==') for page in self.root_page.subpages: if page.level == 0: index.append('{{CourseLevelTwo|'+page.title +'}}') if export_book_page: #book export index for chapters book_export_index.append(';' + page.title) #creating index for book for p in page.get_subpages(): if not p.collapsed: if len(p.text) > 0: book_export_index.append( ':[[' + p.url + '|' + p.title + ']]') #closing section index.append('\n{{ForceBreak}}\n') #adding course categories index.append("}}\n") index.append("[["+ self.configs["keywords"]["category"] +":Structure]]") index.append("[[Category:CourseRoot]]") base_page.text += '\n'.join(index) #creating book export page if export_book_page: #adding category to book page book_export_index.append("[["+self.configs["keywords"]["book_category"]+ "|"+self.doc_title +"]]") book_template = self.configs["keywords"]["book_template"] book_title = book_template + '_' + book_url book_export_page = Page(book_title, 'root', -1,None) book_export_page.url = self.configs['base_path']+ \ book_template + '/' + self.doc_title #inserting index text book_export_page.addText(u'\n'.join(book_export_index)) #the export book page is inserted in the pages dict and index self.pages[book_template + '/' + self.doc_title] = book_export_page diff --git a/texla/Renderers/MediaWikiRenderer.py b/texla/Renderers/MediaWikiRenderer.py index 53edb97..b5881c3 100644 --- a/texla/Renderers/MediaWikiRenderer.py +++ b/texla/Renderers/MediaWikiRenderer.py @@ -1,577 +1,577 @@ import logging from .Renderer import Renderer from ..PageTree.PageTree import * class MediaWikiRenderer(Renderer): def __init__(self, configs, reporter): super().__init__(configs, 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 } #tree object - self.tree = PageTree(configs) + self.tree = PageTree(configs, reporter) #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 '' + s + '' def r_inline_math(self, block): s = block.attributes['content'] #rendering labels self.render_blocks(block.labels) return '' + s + '' def r_align(self, block): s = block.attributes['content'] #rendering labels self.render_blocks(block.labels) return '\\begin{align}' +\ s + '\end{align}' def r_gather(self, block): s = block.attributes['content'] output = [] for eq in s.split("\\\\"): eq = eq.replace("\n","").strip() output.append('' +\ eq + '') #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/Reporter.py b/texla/Reporter.py index 188c8d8..9b3be4f 100644 --- a/texla/Reporter.py +++ b/texla/Reporter.py @@ -1,52 +1,69 @@ 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 = {} + #collecting not parsed block 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) + #references to labels not defined + self.missing_anchors = {} 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 add_missing_anchor(self, label, refs): + """This methods saves the references list to a missing label""" + if label not in self.missing_anchors: + self.missing_anchors[label] = [] + self.missing_anchors[label] += refs + 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))) + s.append("\n- Missing labels:") + for lb in self.missing_anchors: + s.append("\t- {}".format(lb)) text= "\n".join(s) if console: logging.info(text) #saving to file also the block trees with open("debug/texla_report.txt",'w') as file: t = ["############### TEXLA REPORT ###############"] t.append("\n- NOT PARSED blocks:") for bl, v in self.not_parsed_types.items(): t.append("\t- {} : {}".format(bl, len(v))) t.append("\n- NOT PARSED blocks details:") t.append(self.tree_explorer.print_tree_to_blocks(self.not_parsed_blocks)) t.append("\n- NOT RENDERED blocks:") for bl, v in self.not_rendered_types.items(): t.append("\t- {} : {}".format(bl, len(v))) t.append("\n- NOT RENDERED blocks details:") t.append(self.tree_explorer.print_tree_to_blocks(self.not_rendered_blocks)) + t.append("\n- Missing labels details:") + for lb, refs in self.missing_anchors.items(): + t.append("\t- {}".format(lb)) + for ref in refs: + t.append("\t\t- {}".format(ref)) file.write("\n".join(t))