diff --git a/texla/PageTree/PageTree.py b/texla/PageTree/PageTree.py index a7f00bd..8cbd2df 100644 --- a/texla/PageTree/PageTree.py +++ b/texla/PageTree/PageTree.py @@ -1,257 +1,259 @@ from .Page import Page import re, os, json class PageTree(): def __init__(self, configs): self.configs = configs 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 = {} #labels : id self.labels = {} #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_id = self.root_id self.current_anchor = self.root_id 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_id].addSubpage(p) #updates current self.pageid_stack.append(p.id) self.current_id = p.id self.current_anchor = p.id def exitPage(self): '''Return to the parent page enviroment''' self.current_id = self.pageid_stack[-2] self.pageid_stack.pop() self.current_anchor = self.current_id def addText(self, text): self.pages[self.current_id].addText(text) def addLabel(self, label): self.labels[label] = self.current_anchor def getRef(self, label): return self.urls[self.labels[label]] @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('\\', '') title = title.replace('\\mathcal','') title = title.replace('\\mathbf','') title = title.replace('\\mathbb','') title = title.replace('\\ensuremath','') + title = title.replace(';', ' ') + title = title.replace('&', 'e') + 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 collapse_tree(self, content_level, max_page_level): '''This funcion contains all the tree collapsing procedures in the order: subpages content collapsing, subpages level collapsing, url collapsing, fixReferences.''' self.collapse_content_level(content_level) self.collapse_page_level(max_page_level) self.collapse_urls() self.fix_references() def collapse_content_level(self, max_level): '''This functions collapse 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.collapseSubpages() 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 = '' #we don't need to fix labels for now #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 fix_references(self): '''This function fix the references inside the text with the right urls instead of urls''' for page in self.pages.values(): page.fixReferences(self.labels,self.pages) def create_indexes(self): '''This function create sections index and book total index''' self.create_sections_index() self.create_book_index() 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 ) page.text = '\n'.join(index) def create_book_index(self): '''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(' ','_') base_page.text+= '{{libro|Project:Libri/'+ book_url+\ '|'+ self.doc_title + '}}\n' #creating root index index = [] 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.pages.values(): + for page in self.root_page.subpages: if page.level == 0: index.append('{{Section\n|sectionTitle=') index.append(page.title + '\n') index.append('|sectionText=\n') #transcluding index for section index.append('{{:'+ page.url+ '}}') #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') base_page.text += '\n'.join(index) #creating book export page book_title = 'Project:Libri_' + book_url book_export_page = Page(book_title, 'root', -1,None) book_export_page.url = self.configs['base_path']+ \ 'Project:Libri/' + 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['Project:Libri/' + self.doc_title] = book_export_page diff --git a/texla/Renderers/MediaWikiRenderer.py b/texla/Renderers/MediaWikiRenderer.py index 204339c..f63f2e6 100644 --- a/texla/Renderers/MediaWikiRenderer.py +++ b/texla/Renderers/MediaWikiRenderer.py @@ -1,482 +1,482 @@ import logging from .Renderer import Renderer from ..PageTree.PageTree import * from . import MathCheck class MediaWikiRenderer(Renderer): def __init__(self, configs): super().__init__() self.configs = configs self.doc_title = configs['doc_title'] #registering the hooks self.register_render_hooks(self.get_render_hooks()) #tree object self.tree = PageTree(configs) #parameter for list formatting self.list_level = '' #parameters for theorem handling self.in_theorem = False self.th_numbering = {} ######################################## #STARTING POINT def start_rendering(self, root_block): '''starting rendering from root-block''' self.render_block(root_block) #after rendering self.tree.after_render() ####### 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) ######################################## #DEFAULT def default(self, block): #we don't print anything return '' ######################################### #TEXT def r_text(self, block): text = block.attributes['text'] return text 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'] #check math content s = MathCheck.math_check(s) #rendering labels self.render_blocks(block.labels) - return '' + s + '' + return '' + s + '' def r_inline_math(self, block): s = block.attributes['content'] #check math content s = MathCheck.math_check(s) #rendering labels self.render_blocks(block.labels) return '' + s + '' def r_align(self, block): s = block.attributes['content'] s = s.replace('alignat', 'align') s = s.replace('eqnarray', 'align') s = s.replace('multline', 'align') s = s.replace('align*', 'align') s = s.replace('alignat*', 'align') s = s.replace('eqnarray*', 'align') s = s.replace('multline*', 'align') #check math content s = MathCheck.math_check(s) #rendering labels self.render_blocks(block.labels) return '\\begin{align}' +\ s + '\end{align}' ######################################### #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'] return '\\ref{' + ref + '}' ######################################### #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)) 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)) 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 not block.attributes['star']: counter = block.attributes['counter'] if counter==None: counter = block.th_type if counter in self.th_numbering: num = self.th_numbering[counter] +1 else: num = 1 th_title += str(num) self.th_numbering[counter] = num if block.attributes['title'] != None: th_title +=" "+ block.attributes['title'] s = [] if self.configs['lang'] =='it': if th_definition.lower() == 'teorema': #adding content to page through a template s.append("\n{{Teorema|titolo=" + \ th_title+"|") elif th_definition.lower() == 'definizione': s.append("\n{{Definizione|titolo=" + \ th_title+"|") elif th_definition.lower() == 'proposizione': s.append("\n{{Proposizione|titolo=" + \ th_title+"|") elif th_definition.lower() == 'lemma': s.append("\n{{Lemma|title=" + \ th_title+"|") elif th_definition.lower() == 'corollario': s.append("\n{{Corollario|titolo=" + \ th_title+"|") elif th_definition.lower()[:-2] == 'eserciz': s.append("\n{{Esercizio|titolo=" + \ th_title+"|") elif th_definition.lower()[:-1] == 'osservazion': s.append("\n{{Osservazione|titolo=" + \ th_title+"|") elif th_definition.lower()[:-2] == 'esemp': s.append("\n{{Esempio|titolo=" + \ th_title+"|") elif th_definition.lower() == 'dimostrazione': s.append("\n{{Dimostrazione|titolo=" + \ th_title+"|") else: s.append("\n{{Environment|name="+ th_definition + \ "|title=" + th_title +\ "|content=") elif self.configs['lang'] =='en': if th_definition.lower() == 'theorem': #adding content to page through a template s.append("\n{{Theorem|title=" + \ th_title+"|") elif th_definition.lower() == 'definition': s.append("\n{{Definition|title=" + \ th_title+"|") elif th_definition.lower() == 'proposition': s.append("\n{{Proposition|title=" + \ th_title+"|") elif th_definition.lower() == 'lemma': s.append("\n{{Lemma|title=" + \ th_title+"|") elif th_definition.lower() == 'corollarium': s.append("\n{{Corollarium|title=" + \ th_title+"|") elif th_definition.lower() == 'exercise': s.append("\n{{Exercise|title=" + \ th_title+"|") elif th_definition.lower() == 'observation': s.append("\n{{Observation|title=" + \ th_title+"|") elif th_definition.lower() == 'remark': s.append("\n{{Remark|title=" + \ th_title+"|") elif th_definition.lower() == 'example': s.append("\n{{Example|title=" + \ th_title+"|") elif th_definition.lower() == 'demonstration': s.append("\n{{Demonstration|title=" + \ th_title+"|") else: s.append("\n{{Environment|name="+ th_definition + \ "|title=" + th_title +\ "|content=") #insertig theorem content s.append(self.render_children_blocks(block)) s.append('}}\n') return '\n'.join(s) def r_proof(self, block): s=[] if self.configs['lang'] == 'it': if block.title !=None: s.append('\n{{Dimostrazione|titolo='+\ block.attributes['title']) else: s.append('\n{{Dimostrazione|') elif self.configs['lang'] == 'en': if block.title !=None: s.append('\n{{Proof|title='+\ block.attributes['title']) else: s.append('\n{{Proof|') s.append(self.render_children_blocks(block)) s.append('}}\n') return '\n'.join(s) ######################################### #ACCENTED letters def r_accented_letter(self, block): if block.attributes["accent_type"] in ['"',"'","`"]: return block.attributes["letter"]+\ block.attributes["accent_type"] else: return block.attributes["letter"] def get_render_hooks(self): '''Render hooks''' 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, #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, } return render_hooks