from docstructure import SITE_STRUCTURE, HREF_MAP, BASENAME_MAP from lxml.etree import (parse, fromstring, ElementTree, Element, SubElement, XPath, XML) import os import re import sys import copy import shutil import subprocess RST2HTML_OPTIONS = " ".join([ '--no-toc-backlinks', '--strip-comments', '--language en', '--date', ]) XHTML_NS = 'http://www.w3.org/1999/xhtml' htmlnsmap = {"h" : XHTML_NS} find_title = XPath("/h:html/h:head/h:title/text()", namespaces=htmlnsmap) find_title_tag = XPath("/h:html/h:head/h:title", namespaces=htmlnsmap) find_headings = XPath("//h:h1[not(@class)]//text()", namespaces=htmlnsmap) find_heading_tag = XPath("//h:h1[@class = 'title'][1]", namespaces=htmlnsmap) find_menu = XPath("//h:ul[@id=$name]", namespaces=htmlnsmap) find_page_end = XPath("/h:html/h:body/h:div[last()]", namespaces=htmlnsmap) find_words = re.compile('(\w+)').findall replace_invalid = re.compile(r'[-_/.\s\\]').sub def make_menu_section_head(section, menuroot): section_id = section + '-section' section_head = menuroot.xpath("//ul[@id=$section]/li", section=section_id) if not section_head: ul = SubElement(menuroot, "ul", id=section_id) section_head = SubElement(ul, "li") title = SubElement(section_head, "span", {"class":"section title"}) title.text = section else: section_head = section_head[0] return section_head def build_menu(tree, basename, section_head): page_title = find_title(tree) if page_title: page_title = page_title[0] else: page_title = replace_invalid('', basename.capitalize()) build_menu_entry(page_title, basename+".html", section_head, headings=find_headings(tree)) def build_menu_entry(page_title, url, section_head, headings=None): page_id = replace_invalid(' ', os.path.splitext(url)[0]) + '-menu' ul = SubElement(section_head, "ul", {"class":"menu foreign", "id":page_id}) title = SubElement(ul, "li", {"class":"menu title"}) a = SubElement(title, "a", href=url) a.text = page_title if headings: subul = SubElement(title, "ul", {"class":"submenu"}) for heading in headings: li = SubElement(subul, "li", {"class":"menu item"}) try: ref = heading.getparent().getparent().get('id') except AttributeError: ref = None if ref is None: ref = '-'.join(find_words(replace_invalid(' ', heading.lower()))) a = SubElement(li, "a", href=url+'#'+ref) a.text = heading def merge_menu(tree, menu, name): menu_root = copy.deepcopy(menu) tree.getroot()[1][0].insert(0, menu_root) # html->body->div[class=document] for el in menu_root.iter(): tag = el.tag if tag[0] != '{': el.tag = "{http://www.w3.org/1999/xhtml}" + tag current_menu = find_menu( menu_root, name=replace_invalid(' ', name) + '-menu') if not current_menu: current_menu = find_menu( menu_root, name=replace_invalid('-', name) + '-menu') if current_menu: for submenu in current_menu: submenu.set("class", submenu.get("class", ""). replace("foreign", "current")) return tree def inject_flatter_button(tree): head = tree.xpath('h:head[1]', namespaces=htmlnsmap)[0] script = SubElement(head, '{%s}script' % XHTML_NS, type='text/javascript') script.text = """ (function() { var s = document.createElement('script'); var t = document.getElementsByTagName('script')[0]; s.type = 'text/javascript'; s.async = true; s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto'; t.parentNode.insertBefore(s, t); })(); """ script.tail = '\n' intro_div = tree.xpath('h:body//h:div[@id = "introduction"][1]', namespaces=htmlnsmap)[0] intro_div.insert(-1, XML( '
Like working with lxml? '
'Happy about the time that it just saved you?
'
'Show your appreciation with Flattr.
'
' '
'