def formulaeToImages(document, dir): # gather all macros macros = '' for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexmacros'): macros += domhelpers.getNodeText(node) node.parentNode.removeChild(node) i = 0 for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexformula'): latexText='''\\documentclass[12pt]{amsart}%s \\begin{document}\[%s\] \\end{document}''' % (macros, domhelpers.getNodeText(node)) file = tempfile.mktemp() open(file+'.tex', 'w').write(latexText) os.system('latex %s.tex' % file) os.system('dvips %s.dvi -o %s.ps' % (os.path.basename(file), file)) baseimgname = 'latexformula%d.png' % i imgname = os.path.join(dir, baseimgname) i += 1 os.system('pstoimg -type png -crop a -trans -interlace -out ' '%s %s.ps' % (imgname, file)) newNode = microdom.parseString('<span><br /><img src="%s" /><br /></span>' % baseimgname) node.parentNode.replaceChild(newNode, node)
def formulaeToImages(document, dir, _system=os.system): # gather all macros macros = '' for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexmacros'): macros += domhelpers.getNodeText(node) node.parentNode.removeChild(node) i = 0 for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexformula'): latexText='''\\documentclass[12pt]{amsart}%s \\begin{document}\[%s\] \\end{document}''' % (macros, domhelpers.getNodeText(node)) # This file really should be cleaned up by this function, or placed # somewhere such that the calling code can find it and clean it up. file = tempfile.mktemp() f = open(file+'.tex', 'w') f.write(latexText) f.close() _system('latex %s.tex' % file) _system('dvips %s.dvi -o %s.ps' % (os.path.basename(file), file)) baseimgname = 'latexformula%d.png' % i imgname = os.path.join(dir, baseimgname) i += 1 _system('pstoimg -type png -crop a -trans -interlace -out ' '%s %s.ps' % (imgname, file)) newNode = dom.parseString( '<span><br /><img src="%s" /><br /></span>' % ( baseimgname,)).documentElement node.parentNode.replaceChild(newNode, node)
def templateMutate(self, document, parentCount=0): if self.metaTemplate: newDoc = self.metaTemplate.cloneNode(1) if parentCount: dotdot = parentCount * '../' for ddname in 'href', 'src', 'action': for node in domhelpers.findElementsWithAttribute( newDoc, ddname): node.setAttribute(ddname, dotdot + node.getAttribute(ddname)) ttl = domhelpers.findNodesNamed(newDoc, "title")[0] ttl2 = domhelpers.findNodesNamed(document, "title")[0] ttl.childNodes[:] = [] for n in ttl2.childNodes: ttl.appendChild(n) body = domhelpers.findElementsWithAttribute( newDoc, "class", "__BODY__")[0] body2 = domhelpers.findNodesNamed(document, "body")[0] ndx = body.parentNode.childNodes.index(body) body.parentNode.childNodes[ndx:ndx + 1] = body2.childNodes for n in body2.childNodes: n.parentNode = body.parentNode f = open("garbage.html", "wb") f.write(newDoc.toprettyxml()) return newDoc return document
def formulaeToImages(document, dir, _system=os.system): # gather all macros macros = '' for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexmacros'): macros += domhelpers.getNodeText(node) node.parentNode.removeChild(node) i = 0 for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexformula'): latexText = '''\\documentclass[12pt]{amsart}%s \\begin{document}\[%s\] \\end{document}''' % (macros, domhelpers.getNodeText(node)) # This file really should be cleaned up by this function, or placed # somewhere such that the calling code can find it and clean it up. file = tempfile.mktemp() f = open(file + '.tex', 'w') f.write(latexText) f.close() _system('latex %s.tex' % file) _system('dvips %s.dvi -o %s.ps' % (os.path.basename(file), file)) baseimgname = 'latexformula%d.png' % i imgname = os.path.join(dir, baseimgname) i += 1 _system('pstoimg -type png -crop a -trans -interlace -out ' '%s %s.ps' % (imgname, file)) newNode = dom.parseString('<span><br /><img src="%s" /><br /></span>' % (baseimgname, )).documentElement node.parentNode.replaceChild(newNode, node)
def formulaeToImages(document, dir): # gather all macros macros = '' for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexmacros'): macros += domhelpers.getNodeText(node) node.parentNode.removeChild(node) i = 0 for node in domhelpers.findElementsWithAttribute(document, 'class', 'latexformula'): latexText = '''\\documentclass[12pt]{amsart}%s \\begin{document}\[%s\] \\end{document}''' % (macros, domhelpers.getNodeText(node)) file = tempfile.mktemp() f = open(file + '.tex', 'w') f.write(latexText) f.close() os.system('latex %s.tex' % file) os.system('dvips %s.dvi -o %s.ps' % (os.path.basename(file), file)) baseimgname = 'latexformula%d.png' % i imgname = os.path.join(dir, baseimgname) i += 1 os.system('pstoimg -type png -crop a -trans -interlace -out ' '%s %s.ps' % (imgname, file)) newNode = microdom.parseString( '<span><br /><img src="%s" /><br /></span>' % baseimgname) node.parentNode.replaceChild(newNode, node)
def test_findElementsWithAttribute(self): doc1 = self.dom.parseString('<a foo="1"><b foo="2"/><c foo="1"/><d/></a>') node_list = domhelpers.findElementsWithAttribute(doc1, 'foo') actual = ''.join([node.tagName for node in node_list]) self.assertEqual(actual, 'abc') node_list = domhelpers.findElementsWithAttribute(doc1, 'foo', '1') actual = ''.join([node.tagName for node in node_list]) self.assertEqual(actual, 'ac')
def test_findElementsWithAttribute(self): doc1 = self.dom.parseString('<a foo="1"><b foo="2"/><c foo="1"/><d/></a>') node_list = domhelpers.findElementsWithAttribute(doc1, "foo") actual = "".join([node.tagName for node in node_list]) self.assertEqual(actual, "abc") node_list = domhelpers.findElementsWithAttribute(doc1, "foo", "1") actual = "".join([node.tagName for node in node_list]) self.assertEqual(actual, "ac")
def test_findElementsWithAttribute(self): doc1 = self.dom.parseString('<a foo="1"><b foo="2"/><c foo="1"/><d/></a>') node_list = domhelpers.findElementsWithAttribute(doc1, 'foo') actual = ''.join([node.tagName for node in node_list]) self.assertEqual(actual, 'abc') node_list = domhelpers.findElementsWithAttribute(doc1, 'foo', '1') actual = ''.join([node.tagName for node in node_list]) self.assertEqual(actual, 'ac')
def test_findElementsWithAttribute(self): doc1=microdom.parseString('<a foo="1"><b foo="2"/><c foo="1"/><d/></a>') node_list=domhelpers.findElementsWithAttribute(doc1, 'foo') actual=''.join([node.tagName for node in node_list]) expected='abc' assert actual==expected, 'expected %s, got %s' % (expected, actual) node_list=domhelpers.findElementsWithAttribute(doc1, 'foo', '1') actual=''.join([node.tagName for node in node_list]) expected='ac' assert actual==expected, 'expected %s, got %s' % (expected, actual)
def test_findElementsWithAttribute(self): doc1 = microdom.parseString( '<a foo="1"><b foo="2"/><c foo="1"/><d/></a>') node_list = domhelpers.findElementsWithAttribute(doc1, 'foo') actual = ''.join([node.tagName for node in node_list]) expected = 'abc' assert actual == expected, 'expected %s, got %s' % (expected, actual) node_list = domhelpers.findElementsWithAttribute(doc1, 'foo', '1') actual = ''.join([node.tagName for node in node_list]) expected = 'ac' assert actual == expected, 'expected %s, got %s' % (expected, actual)
def visitNode_body(self, node): # Adapted from tree.generateToC self.fontStack = [('standard', None)] # Title slide self.writer(self.start_h2) self.writer(self.title) self.writer(self.end_h2) self.writer('%center\n\n\n\n\n') for authorNode in domhelpers.findElementsWithAttribute( node, 'class', 'author'): getLatexText(authorNode, self.writer, entities=entities) self.writer('\n') # Table of contents self.writer(self.start_h2) self.writer(self.title) self.writer(self.end_h2) for element in getHeaders(node): level = int(element.tagName[1]) - 1 self.writer(level * '\t') self.writer(domhelpers.getNodeText(element)) self.writer('\n') self.visitNodeDefault(node)
def munge(document, template, linkrel, d, fullpath, ext, url, config): # FIXME: This has *way* to much duplicated crap in common with tree.munge #fixRelativeLinks(template, linkrel) removeH1(document) fixAPI(document, url) fontifyPython(document) addPyListings(document, d) addHTMLListings(document, d) #fixLinks(document, ext) #putInToC(template, generateToC(document)) template = template.cloneNode(1) # Insert the slides into the template slides = [] pos = 0 for title, slide in splitIntoSlides(document): t = template.cloneNode(1) setTitle(t, [microdom.Text(title)]) tmplbody = domhelpers.findElementsWithAttribute(t, "class", "body")[0] tmplbody.childNodes = slide tmplbody.setAttribute("class", "content") # FIXME: Next/Prev links # FIXME: Perhaps there should be a "Template" class? (setTitle/setBody # could be methods...) slides.append(HTMLSlide(t, title, pos)) pos += 1 insertPrevNextLinks(slides, os.path.splitext(os.path.basename(fullpath)), ext) return slides
def munge(document, template, linkrel, d, fullpath, ext, url, config): fixRelativeLinks(template, linkrel) addMtime(template, fullpath) removeH1(document) fixAPI(document, url) fontifyPython(document) addPyListings(document, d) addHTMLListings(document, d) fixLinks(document, ext) putInToC(template, generateToC(document)) footnotes(document) notes(document) # Insert the document into the template title = domhelpers.findNodesNamed(document, 'title')[0].childNodes setTitle(template, title) authors = domhelpers.findNodesNamed(document, 'link') authors = [(n.getAttribute('title',''), n.getAttribute('href', '')) for n in authors if n.getAttribute('rel', '') == 'author'] setAuthors(template, authors) body = domhelpers.findNodesNamed(document, "body")[0] tmplbody = domhelpers.findElementsWithAttribute(template, "class", "body")[0] tmplbody.childNodes = body.childNodes tmplbody.setAttribute("class", "content")
def makeBook(dom, d): body = microdom.Element('body') body.appendChild(domhelpers.findNodesNamed(dom, 'h1')[0]) toc = domhelpers.findElementsWithAttribute(dom, 'class', 'toc')[0] toc = domhelpers.findNodesNamed(toc, 'li') for node in toc: if (node.hasAttribute('class') and node.getAttribute('class')=='tocignore'): continue parents = domhelpers.getParents(node) nodeLevel = len([1 for parent in parents if hasattr(parent, 'tagName') and parent.tagName in ('ol', 'ul')]) data = node.childNodes[0].data != '' if not data: node = node.childNodes[1] newNode = lowerDocument(node.getAttribute('href'), d, nodeLevel) for child in newNode.childNodes: body.appendChild(child) else: text = microdom.Text(node.childNodes[0].data) newNode = microdom.Element('h'+str(nodeLevel)) newNode.appendChild(text) body.appendChild(newNode) origBody = domhelpers.findNodesNamed(dom, 'body')[0] origBody.parentNode.replaceChild(body, origBody)
def fixAPI(document, url): """ Replace API references with links to API documentation. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @type url: C{str} @param url: A string which will be interpolated with the fully qualified Python name of any API reference encountered in the input document, the result of which will be used as a link to API documentation for that name in the output document. @return: C{None} """ # API references for node in domhelpers.findElementsWithAttribute(document, "class", "API"): fullname = _getAPI(node) anchor = dom.Element('a') anchor.setAttribute('href', url % (fullname,)) anchor.setAttribute('title', fullname) while node.childNodes: child = node.childNodes[0] node.removeChild(child) anchor.appendChild(child) node.appendChild(anchor) if node.hasAttribute('base'): node.removeAttribute('base')
def addPyListings(document, dir): """ Insert Python source listings into the given document from files in the given directory based on C{py-listing} nodes. Any node in C{document} with a C{class} attribute set to C{py-listing} will have source lines taken from the file named in that node's C{href} attribute (searched for in C{dir}) inserted in place of that node. If a node has a C{skipLines} attribute, its value will be parsed as an integer and that many lines will be skipped at the beginning of the source file. @type document: A DOM Node or Document @param document: The document within which to make listing replacements. @type dir: C{str} @param dir: The directory in which to find source files containing the referenced Python listings. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(document, "class", "py-listing"): filename = node.getAttribute("href") outfile = cStringIO.StringIO() lines = map(string.rstrip, open(os.path.join(dir, filename)).readlines()) data = "\n".join(lines[int(node.getAttribute("skipLines", 0)) :]) data = cStringIO.StringIO(text.removeLeadingTrailingBlanks(data)) htmlizer.filter(data, outfile, writer=htmlizer.SmallerHTMLWriter) val = outfile.getvalue() _replaceWithListing(node, val, filename, "py-listing")
def setIndexLink(template, indexFilename): """ Insert a link to an index document. Any node with a C{class} attribute set to C{index-link} will have its tag name changed to C{a} and its C{href} attribute set to C{indexFilename}. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type indexFilename: C{str} @param indexFilename: The address of the index document to which to link. If any C{False} value, this function will remove all index-link nodes. @return: C{None} """ indexLinks = domhelpers.findElementsWithAttribute(template, "class", "index-link") for link in indexLinks: if indexFilename is None: link.parentNode.removeChild(link) else: link.nodeName = link.tagName = link.endTagName = 'a' for attrName in link.attributes.keys(): link.removeAttribute(attrName) link.setAttribute('href', indexFilename)
def setIndexLink(template, indexFilename): if not indexFilename: return indexLinks = domhelpers.findElementsWithAttribute(template, "class", "index-link") for link in indexLinks: link.nodeName = link.tagName = link.endTagName = 'a' link.attributes = InsensitiveDict({'href': indexFilename})
def footnotes(document): """ Find footnotes in the given document, move them to the end of the body, and generate links to them. A footnote is any node with a C{class} attribute set to C{footnote}. Footnote links are generated as superscript. Footnotes are collected in a C{ol} node at the end of the document. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @return: C{None} """ footnotes = domhelpers.findElementsWithAttribute(document, "class", "footnote") if not footnotes: return footnoteElement = microdom.Element("ol") id = 1 for footnote in footnotes: href = microdom.parseString('<a href="#footnote-%(id)d">' "<super>%(id)d</super></a>" % vars()).documentElement text = " ".join(domhelpers.getNodeText(footnote).split()) href.setAttribute("title", text) target = microdom.Element("a", attributes={"name": "footnote-%d" % id}) target.childNodes = [footnote] footnoteContent = microdom.Element("li") footnoteContent.childNodes = [target] footnoteElement.childNodes.append(footnoteContent) footnote.parentNode.replaceChild(href, footnote) id += 1 body = domhelpers.findNodesNamed(document, "body")[0] header = microdom.parseString("<h2>Footnotes</h2>").documentElement body.childNodes.append(header) body.childNodes.append(footnoteElement)
def setTitle(template, title, chapterNumber): """ Add title and chapter number information to the template document. The title is added to the end of the first C{title} tag and the end of the first tag with a C{class} attribute set to C{title}. If specified, the chapter is inserted before the title. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type title: C{list} of DOM Nodes @param title: Nodes from the input document defining its title. @type chapterNumber: C{int} @param chapterNumber: The chapter number of this content in an overall document. If not applicable, any C{False} value will result in this information being omitted. @return: C{None} """ for nodeList in ( domhelpers.findNodesNamed(template, "title"), domhelpers.findElementsWithAttribute(template, "class", "title"), ): if nodeList: if numberer.getNumberSections() and chapterNumber: nodeList[0].childNodes.append(microdom.Text("%s. " % chapterNumber)) nodeList[0].childNodes.extend(title)
def fixAPI(document, url): """ Replace API references with links to API documentation. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @type url: C{str} @param url: A string which will be interpolated with the fully qualified Python name of any API reference encountered in the input document, the result of which will be used as a link to API documentation for that name in the output document. @return: C{None} """ # API references for node in domhelpers.findElementsWithAttribute(document, "class", "API"): fullname = _getAPI(node) node2 = microdom.Element('a', { 'href': url % fullname, 'title': fullname }) node2.childNodes = node.childNodes node.childNodes = [node2] node.removeAttribute('base')
def setTitle(template, title, chapterNumber): """ Add title and chapter number information to the template document. The title is added to the end of the first C{title} tag and the end of the first tag with a C{class} attribute set to C{title}. If specified, the chapter is inserted before the title. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type title: C{list} of DOM Nodes @param title: Nodes from the input document defining its title. @type chapterNumber: C{int} @param chapterNumber: The chapter number of this content in an overall document. If not applicable, any C{False} value will result in this information being omitted. @return: C{None} """ for nodeList in (domhelpers.findNodesNamed(template, "title"), domhelpers.findElementsWithAttribute( template, "class", 'title')): if nodeList: if numberer.getNumberSections() and chapterNumber: nodeList[0].childNodes.append( microdom.Text('%s. ' % chapterNumber)) nodeList[0].childNodes.extend(title)
def addHTMLListings(document, dir): for node in domhelpers.findElementsWithAttribute(document, "class", "html-listing"): filename = node.getAttribute("href") val = ('<pre class="htmlsource">\n%s</pre>' % cgi.escape(open(os.path.join(dir, filename)).read())) _replaceWithListing(node, val, filename, "html-listing")
def addPyListings(document, dir): """ Insert Python source listings into the given document from files in the given directory based on C{py-listing} nodes. Any node in C{document} with a C{class} attribute set to C{py-listing} will have source lines taken from the file named in that node's C{href} attribute (searched for in C{dir}) inserted in place of that node. If a node has a C{skipLines} attribute, its value will be parsed as an integer and that many lines will be skipped at the beginning of the source file. @type document: A DOM Node or Document @param document: The document within which to make listing replacements. @type dir: C{str} @param dir: The directory in which to find source files containing the referenced Python listings. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(document, "class", "py-listing"): filename = node.getAttribute("href") outfile = cStringIO.StringIO() lines = map(string.rstrip, open(os.path.join(dir, filename)).readlines()) data = '\n'.join(lines[int(node.getAttribute('skipLines', 0)):]) data = cStringIO.StringIO(text.removeLeadingTrailingBlanks(data)) htmlizer.filter(data, outfile, writer=htmlizer.SmallerHTMLWriter) val = outfile.getvalue() _replaceWithListing(node, val, filename, "py-listing")
def fixAPI(document, url): """ Replace API references with links to API documentation. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @type url: C{str} @param url: A string which will be interpolated with the fully qualified Python name of any API reference encountered in the input document, the result of which will be used as a link to API documentation for that name in the output document. @return: C{None} """ # API references for node in domhelpers.findElementsWithAttribute(document, "class", "API"): fullname = _getAPI(node) anchor = dom.Element('a') anchor.setAttribute('href', url % (fullname, )) anchor.setAttribute('title', fullname) while node.childNodes: child = node.childNodes[0] node.removeChild(child) anchor.appendChild(child) node.appendChild(anchor) if node.hasAttribute('base'): node.removeAttribute('base')
def munge(document, template, linkrel, d, fullpath, ext, url, config): # FIXME: This has *way* to much duplicated crap in common with tree.munge #fixRelativeLinks(template, linkrel) removeH1(document) fixAPI(document, url) fontifyPython(document) addPyListings(document, d) addHTMLListings(document, d) #fixLinks(document, ext) #putInToC(template, generateToC(document)) template = template.cloneNode(1) # Insert the slides into the template slides = [] pos = 0 for title, slide in splitIntoSlides(document): t = template.cloneNode(1) text = dom.Text() text.data = title setTitle(t, [text]) tmplbody = domhelpers.findElementsWithAttribute(t, "class", "body")[0] tmplbody.childNodes = slide tmplbody.setAttribute("class", "content") # FIXME: Next/Prev links # FIXME: Perhaps there should be a "Template" class? (setTitle/setBody # could be methods...) slides.append(HTMLSlide(t, title, pos)) pos += 1 insertPrevNextLinks(slides, os.path.splitext(os.path.basename(fullpath)), ext) return slides
def visitNode_body(self, node): # Adapted from tree.generateToC self.fontStack = [('standard', None)] # Title slide self.writer(self.start_h2) self.writer(self.title) self.writer(self.end_h2) self.writer('%center\n\n\n\n\n') for authorNode in domhelpers.findElementsWithAttribute(node, 'class', 'author'): getLatexText(authorNode, self.writer, entities=entities) self.writer('\n') # Table of contents self.writer(self.start_h2) self.writer(self.title) self.writer(self.end_h2) for element in getHeaders(node): level = int(element.tagName[1])-1 self.writer(level * '\t') self.writer(domhelpers.getNodeText(element)) self.writer('\n') self.visitNodeDefault(node)
def setIndexLink(template, indexFilename): """ Insert a link to an index document. Any node with a C{class} attribute set to C{index-link} will have its tag name changed to C{a} and its C{href} attribute set to C{indexFilename}. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type indexFilename: C{str} @param indexFilename: The address of the index document to which to link. If any C{False} value, this function will remove all index-link nodes. @return: C{None} """ indexLinks = domhelpers.findElementsWithAttribute(template, "class", "index-link") for link in indexLinks: if indexFilename is None: link.parentNode.removeChild(link) else: link.nodeName = link.tagName = link.endTagName = 'a' for attrName in link.attributes.keys(): link.removeAttribute(attrName) link.setAttribute('href', indexFilename)
def setAuthors(template, authors): # First, similarly to setTitle, insert text into an <div class="authors"> text = '' for name, href in authors: # FIXME: Do proper quoting/escaping (is it ok to use # xml.sax.saxutils.{escape,quoteattr}?) anchor = '<a href="%s">%s</a>' % (href, name) if (name, href) == authors[-1]: if len(authors) == 1: text = anchor else: text += 'and ' + anchor else: text += anchor + ',' childNodes = microdom.parseString('<span>' + text +'</span>').childNodes for node in domhelpers.findElementsWithAttribute(template, "class", 'authors'): node.childNodes.extend(childNodes) # Second, add appropriate <link rel="author" ...> tags to the <head>. head = domhelpers.findNodesNamed(template, 'head')[0] authors = [microdom.parseString('<link rel="author" href="%s" title="%s"/>' % (href, name)).childNodes[0] for name, href in authors] head.childNodes.extend(authors)
def fixAPI(document, url): # API references for node in domhelpers.findElementsWithAttribute(document, "class", "API"): fullname = _getAPI(node) node2 = microdom.Element('a', {'href': url%fullname, 'title': fullname}) node2.childNodes = node.childNodes node.childNodes = [node2] node.removeAttribute('base')
def setTitle(template, title, chapterNumber): for nodeList in (domhelpers.findNodesNamed(template, "title"), domhelpers.findElementsWithAttribute(template, "class", 'title')): if nodeList: if numberer.getNumberSections() and chapterNumber: nodeList[0].childNodes.append(microdom.Text('%s. ' % chapterNumber)) nodeList[0].childNodes.extend(title)
def insertPrevNextLinks(slides, filename, ext): for slide in slides: for name, offset in (("previous", -1), ("next", +1)): if (slide.pos > 0 and name == "previous") or \ (slide.pos < len(slides)-1 and name == "next"): for node in domhelpers.findElementsWithAttribute(slide.dom, "class", name): node.appendChild(microdom.Text(slides[slide.pos+offset].title)) node.setAttribute('href', '%s-%d%s' % (filename[0], slide.pos+offset, ext)) else: for node in domhelpers.findElementsWithAttribute(slide.dom, "class", name): pos = 0 for child in node.parentNode.childNodes: if child is node: del node.parentNode.childNodes[pos] break pos += 1
def setAuthors(template, authors): """ Add author information to the template document. Names and contact information for authors are added to each node with a C{class} attribute set to C{authors} and to the template head as C{link} nodes. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type authors: C{list} of two-tuples of C{str} @param authors: List of names and contact information for the authors of the input document. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(template, "class", 'authors'): # First, similarly to setTitle, insert text into an <div # class="authors"> container = dom.Element('span') for name, href in authors: anchor = dom.Element('a') anchor.setAttribute('href', href) anchorText = dom.Text() anchorText.data = name anchor.appendChild(anchorText) if (name, href) == authors[-1]: if len(authors) == 1: container.appendChild(anchor) else: andText = dom.Text() andText.data = 'and ' container.appendChild(andText) container.appendChild(anchor) else: container.appendChild(anchor) commaText = dom.Text() commaText.data = ', ' container.appendChild(commaText) node.appendChild(container) # Second, add appropriate <link rel="author" ...> tags to the <head>. head = domhelpers.findNodesNamed(template, 'head')[0] authors = [ dom.parseString('<link rel="author" href="%s" title="%s"/>' % (href, name)).childNodes[0] for name, href in authors ] head.childNodes.extend(authors)
def addPyListings(document, dir): for node in domhelpers.findElementsWithAttribute(document, "class", "py-listing"): filename = node.getAttribute("href") outfile = cStringIO.StringIO() lines = map(string.rstrip, open(os.path.join(dir, filename)).readlines()) data = '\n'.join(lines[int(node.getAttribute('skipLines', 0)):]) data = cStringIO.StringIO(text.removeLeadingTrailingBlanks(data)) htmlizer.filter(data, outfile, writer=htmlizer.SmallerHTMLWriter) val = outfile.getvalue() _replaceWithListing(node, val, filename, "py-listing")
def setAuthors(template, authors): """ Add author information to the template document. Names and contact information for authors are added to each node with a C{class} attribute set to C{authors} and to the template head as C{link} nodes. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type authors: C{list} of two-tuples of C{str} @param authors: List of names and contact information for the authors of the input document. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(template, "class", 'authors'): # First, similarly to setTitle, insert text into an <div # class="authors"> container = dom.Element('span') for name, href in authors: anchor = dom.Element('a') anchor.setAttribute('href', href) anchorText = dom.Text() anchorText.data = name anchor.appendChild(anchorText) if (name, href) == authors[-1]: if len(authors) == 1: container.appendChild(anchor) else: andText = dom.Text() andText.data = 'and ' container.appendChild(andText) container.appendChild(anchor) else: container.appendChild(anchor) commaText = dom.Text() commaText.data = ', ' container.appendChild(commaText) node.appendChild(container) # Second, add appropriate <link rel="author" ...> tags to the <head>. head = domhelpers.findNodesNamed(template, 'head')[0] authors = [dom.parseString('<link rel="author" href="%s" title="%s"/>' % (href, name)).childNodes[0] for name, href in authors] head.childNodes.extend(authors)
def test_setIndexLink(self): """ Tests to make sure that index links are processed when an index page exists and removed when there is not. """ templ = dom.parse(open(d["template"])) indexFilename = "theIndexFile" numLinks = len(domhelpers.findElementsWithAttribute(templ, "class", "index-link")) # if our testing template has no index-link nodes, complain about it self.assertNotEquals([], domhelpers.findElementsWithAttribute(templ, "class", "index-link")) tree.setIndexLink(templ, indexFilename) self.assertEquals([], domhelpers.findElementsWithAttribute(templ, "class", "index-link")) indexLinks = domhelpers.findElementsWithAttribute(templ, "href", indexFilename) self.assertTrue(len(indexLinks) >= numLinks) templ = dom.parse(open(d["template"])) self.assertNotEquals([], domhelpers.findElementsWithAttribute(templ, "class", "index-link")) indexFilename = None tree.setIndexLink(templ, indexFilename) self.assertEquals([], domhelpers.findElementsWithAttribute(templ, "class", "index-link"))
def setUp(self, request, node, data): # node = widgets.Widget.generateDOM(self,request,node) lmn = lmx(node) if not node.hasAttribute('action'): lmn['action'] = (request.prepath+request.postpath)[-1] if not node.hasAttribute("method"): lmn['method'] = 'post' lmn['enctype'] = 'multipart/form-data' self.errorNodes = errorNodes = {} # name: nodes which trap errors self.inputNodes = inputNodes = {} for errorNode in domhelpers.findElementsWithAttribute(node, 'errorFor'): errorNodes[errorNode.getAttribute('errorFor')] = errorNode argz={} # list to figure out which nodes are in the template already and which aren't hasSubmit = 0 argList = self.model.fmethod.getArgs() for arg in argList: if isinstance(arg, formmethod.Submit): hasSubmit = 1 argz[arg.name] = arg inNodes = domhelpers.findElements( node, lambda n: n.tagName.lower() in ('textarea', 'select', 'input', 'div')) for inNode in inNodes: t = inNode.getAttribute("type") if t and t.lower() == "submit": hasSubmit = 1 if not inNode.hasAttribute("name"): continue nName = inNode.getAttribute("name") if argz.has_key(nName): #send an empty content shell - we just want the node inputNodes[nName] = self.convergeInput(request, lmx(), argz[nName], inNode) inNode.parentNode.replaceChild(inputNodes[nName], inNode) del argz[nName] # TODO: # * some arg types should only have a single node (text, string, etc) # * some should have multiple nodes (choice, checkgroup) # * some have a bunch of ancillary nodes that are possible values (menu, radiogroup) # these should all be taken into account when walking through the template if argz: shell = self.createShell(request, node, data) # create inputs, in the same order they were passed to us: for remArg in [arg for arg in argList if argz.has_key(arg.name)]: inputNode, errorNode = self.createInput(request, shell, remArg) errorNodes[remArg.name] = errorNode inputNodes[remArg.name] = inputNode if not hasSubmit: lmn.input(type="submit")
def setUp(self, request, node, data): # node = widgets.Widget.generateDOM(self,request,node) lmn = lmx(node) if not node.hasAttribute('action'): lmn['action'] = (request.prepath + request.postpath)[-1] if not node.hasAttribute("method"): lmn['method'] = 'post' lmn['enctype'] = 'multipart/form-data' self.errorNodes = errorNodes = {} # name: nodes which trap errors self.inputNodes = inputNodes = {} for errorNode in domhelpers.findElementsWithAttribute( node, 'errorFor'): errorNodes[errorNode.getAttribute('errorFor')] = errorNode argz = {} # list to figure out which nodes are in the template already and which aren't hasSubmit = 0 argList = self.model.fmethod.getArgs() for arg in argList: if isinstance(arg, formmethod.Submit): hasSubmit = 1 argz[arg.name] = arg inNodes = domhelpers.findElements( node, lambda n: n.tagName.lower() in ('textarea', 'select', 'input', 'div')) for inNode in inNodes: t = inNode.getAttribute("type") if t and t.lower() == "submit": hasSubmit = 1 if not inNode.hasAttribute("name"): continue nName = inNode.getAttribute("name") if argz.has_key(nName): #send an empty content shell - we just want the node inputNodes[nName] = self.convergeInput(request, lmx(), argz[nName], inNode) inNode.parentNode.replaceChild(inputNodes[nName], inNode) del argz[nName] # TODO: # * some arg types should only have a single node (text, string, etc) # * some should have multiple nodes (choice, checkgroup) # * some have a bunch of ancillary nodes that are possible values (menu, radiogroup) # these should all be taken into account when walking through the template if argz: shell = self.createShell(request, node, data) # create inputs, in the same order they were passed to us: for remArg in [arg for arg in argList if argz.has_key(arg.name)]: inputNode, errorNode = self.createInput(request, shell, remArg) errorNodes[remArg.name] = errorNode inputNodes[remArg.name] = inputNode if not hasSubmit: lmn.input(type="submit")
def insertPrevNextLinks(slides, filename, ext): for slide in slides: for name, offset in (("previous", -1), ("next", +1)): if (slide.pos > 0 and name == "previous") or \ (slide.pos < len(slides)-1 and name == "next"): for node in domhelpers.findElementsWithAttribute( slide.dom, "class", name): if node.tagName == 'a': node.setAttribute( 'href', '%s-%d%s' % (filename[0], slide.pos + offset, ext)) else: node.appendChild( microdom.Text(slides[slide.pos + offset].title)) else: for node in domhelpers.findElementsWithAttribute( slide.dom, "class", name): pos = 0 for child in node.parentNode.childNodes: if child is node: del node.parentNode.childNodes[pos] break pos += 1
def putInToC(document, toc): """ Insert the given table of contents into the given document. The node with C{class} attribute set to C{toc} has its children replaced with C{toc}. @type document: A DOM Node or Document @type toc: A DOM Node """ tocOrig = domhelpers.findElementsWithAttribute(document, "class", "toc") if tocOrig: tocOrig = tocOrig[0] tocOrig.childNodes = [toc]
def putInToC(document, toc): """ Insert the given table of contents into the given document. The node with C{class} attribute set to C{toc} has its children replaced with C{toc}. @type document: A DOM Node or Document @type toc: A DOM Node """ tocOrig = domhelpers.findElementsWithAttribute(document, 'class', 'toc') if tocOrig: tocOrig = tocOrig[0] tocOrig.childNodes = [toc]
def templateMutate(self, document, parentCount=0): if self.metaTemplate: newDoc = self.metaTemplate.cloneNode(1) if parentCount: dotdot = parentCount * '../' for ddname in 'href', 'src', 'action': for node in domhelpers.findElementsWithAttribute(newDoc, ddname): node.setAttribute(ddname, dotdot + node.getAttribute(ddname)) ttl = domhelpers.findNodesNamed(newDoc, "title")[0] ttl2 = domhelpers.findNodesNamed(document, "title")[0] ttl.childNodes[:] = [] for n in ttl2.childNodes: ttl.appendChild(n) body = domhelpers.findElementsWithAttribute(newDoc, "class", "__BODY__")[0] body2 = domhelpers.findNodesNamed(document, "body")[0] ndx = body.parentNode.childNodes.index(body) body.parentNode.childNodes[ndx:ndx+1] = body2.childNodes for n in body2.childNodes: n.parentNode = body.parentNode f = open("garbage.html", "wb") f.write(newDoc.toprettyxml()) return newDoc return document
def addMtime(document, fullpath): """ Set the last modified time of the given document. @type document: A DOM Node or Document @param document: The output template which defines the presentation of the last modified time. @type fullpath: C{str} @param fullpath: The file name from which to take the last modified time. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(document, "class", "mtime"): node.appendChild(microdom.Text(time.ctime(os.path.getmtime(fullpath))))
def setVersion(template, version): """ Add a version indicator to the given template. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type version: C{str} @param version: The version string to add to the template. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(template, "class", "version"): node.appendChild(microdom.Text(version))
def fixLinks(document, ext): supported_schemes=['http', 'https', 'ftp', 'mailto'] for node in domhelpers.findElementsWithAttribute(document, 'href'): href = node.getAttribute("href") if urlparse.urlparse(href)[0] in supported_schemes: continue if node.getAttribute("class", "") == "absolute": continue # This is a relative link, so it should be munged. if href.endswith('.html') or href[:href.rfind('#')].endswith('.html'): fname, fext = os.path.splitext(href) fext = fext.replace('.html', ext) node.setAttribute("href", fname + fext)
def addMtime(document, fullpath): """ Set the last modified time of the given document. @type document: A DOM Node or Document @param document: The output template which defines the presentation of the last modified time. @type fullpath: C{str} @param fullpath: The file name from which to take the last modified time. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(document, "class","mtime"): node.appendChild(microdom.Text(time.ctime(os.path.getmtime(fullpath))))
def setVersion(template, version): """ Add a version indicator to the given template. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type version: C{str} @param version: The version string to add to the template. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(template, "class", "version"): node.appendChild(microdom.Text(version))
def index(document, filename, chapterReference): entries = domhelpers.findElementsWithAttribute(document, "class", "index") if not entries: return i = 0; for entry in entries: i += 1 anchor = 'index%02d' % i if chapterReference: ref = getSectionReference(entry) or chapterReference else: ref = 'link' indexer.addEntry(filename, anchor, entry.attributes['value'], ref) # does nodeName even affect anything? entry.nodeName = entry.tagName = entry.endTagName = 'a' entry.attributes = InsensitiveDict({'name': anchor})
def setAuthors(template, authors): """ Add author information to the template document. Names and contact information for authors are added to each node with a C{class} attribute set to C{authors} and to the template head as C{link} nodes. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type authors: C{list} of two-tuples of C{str} @param authors: List of names and contact information for the authors of the input document. @return: C{None} """ # First, similarly to setTitle, insert text into an <div class="authors"> text = '' for name, href in authors: # FIXME: Do proper quoting/escaping (is it ok to use # xml.sax.saxutils.{escape,quoteattr}?) anchor = '<a href="%s">%s</a>' % (href, name) if (name, href) == authors[-1]: if len(authors) == 1: text = anchor else: text += 'and ' + anchor else: text += anchor + ',' childNodes = microdom.parseString('<span>' + text + '</span>').childNodes for node in domhelpers.findElementsWithAttribute(template, "class", 'authors'): node.childNodes.extend(childNodes) # Second, add appropriate <link rel="author" ...> tags to the <head>. head = domhelpers.findNodesNamed(template, 'head')[0] authors = [ microdom.parseString('<link rel="author" href="%s" title="%s"/>' % (href, name)).childNodes[0] for name, href in authors ] head.childNodes.extend(authors)
def fixRelativeLinks(document, linkrel): """ Replace relative links in C{str} and C{href} attributes with links relative to C{linkrel}. @type document: A DOM Node or Document @param document: The output template. @type linkrel: C{str} @param linkrel: An prefix to apply to all relative links in C{src} or C{href} attributes in the input document when generating the output document. """ for attr in 'src', 'href': for node in domhelpers.findElementsWithAttribute(document, attr): href = node.getAttribute(attr) if not href.startswith('http') and not href.startswith('/'): node.setAttribute(attr, linkrel + node.getAttribute(attr))
def fixRelativeLinks(document, linkrel): """ Replace relative links in C{str} and C{href} attributes with links relative to C{linkrel}. @type document: A DOM Node or Document @param document: The output template. @type linkrel: C{str} @param linkrel: An prefix to apply to all relative links in C{src} or C{href} attributes in the input document when generating the output document. """ for attr in "src", "href": for node in domhelpers.findElementsWithAttribute(document, attr): href = node.getAttribute(attr) if not href.startswith("http") and not href.startswith("/"): node.setAttribute(attr, linkrel + node.getAttribute(attr))
def notes(document): """ Find notes in the given document and mark them up as such. A note is any node with a C{class} attribute set to C{note}. (I think this is a very stupid feature. When I found it I actually exclaimed out loud. -exarkun) @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @return: C{None} """ notes = domhelpers.findElementsWithAttribute(document, "class", "note") notePrefix = dom.parseString('<strong>Note: </strong>').documentElement for note in notes: note.childNodes.insert(0, notePrefix)
def fixLinks(document, ext): """ Rewrite links to XHTML lore input documents so they point to lore XHTML output documents. Any node with an C{href} attribute which does not contain a value starting with C{http}, C{https}, C{ftp}, or C{mailto} and which does not have a C{class} attribute of C{absolute} or which contains C{listing} and which does point to an URL ending with C{html} will have that attribute value rewritten so that the filename extension is C{ext} instead of C{html}. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @type ext: C{str} @param ext: The extension to use when selecting an output file name. This replaces the extension of the input file name. @return: C{None} """ supported_schemes = ['http', 'https', 'ftp', 'mailto'] for node in domhelpers.findElementsWithAttribute(document, 'href'): href = node.getAttribute("href") if urlparse.urlparse(href)[0] in supported_schemes: continue if node.getAttribute("class") == "absolute": continue if node.getAttribute("class").find('listing') != -1: continue # This is a relative link, so it should be munged. if href.endswith('html') or href[:href.rfind('#')].endswith('html'): fname, fext = os.path.splitext(href) if '#' in fext: fext = ext + '#' + fext.split('#', 1)[1] else: fext = ext node.setAttribute("href", fname + fext)
def footnotes(document): """ Find footnotes in the given document, move them to the end of the body, and generate links to them. A footnote is any node with a C{class} attribute set to C{footnote}. Footnote links are generated as superscript. Footnotes are collected in a C{ol} node at the end of the document. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @return: C{None} """ footnotes = domhelpers.findElementsWithAttribute(document, "class", "footnote") if not footnotes: return footnoteElement = dom.Element('ol') id = 1 for footnote in footnotes: href = dom.parseString('<a href="#footnote-%(id)d">' '<super>%(id)d</super></a>' % vars()).documentElement text = ' '.join(domhelpers.getNodeText(footnote).split()) href.setAttribute('title', text) target = dom.Element('a') target.setAttribute('name', 'footnote-%d' % (id, )) target.childNodes = [footnote] footnoteContent = dom.Element('li') footnoteContent.childNodes = [target] footnoteElement.childNodes.append(footnoteContent) footnote.parentNode.replaceChild(href, footnote) id += 1 body = domhelpers.findNodesNamed(document, "body")[0] header = dom.parseString('<h2>Footnotes</h2>').documentElement body.childNodes.append(header) body.childNodes.append(footnoteElement)
def test_setIndexLink(self): """ Tests to make sure that index links are processed when an index page exists and removed when there is not. """ templ = dom.parse(open(d['template'])) indexFilename = 'theIndexFile' numLinks = len(domhelpers.findElementsWithAttribute(templ, "class", "index-link")) # if our testing template has no index-link nodes, complain about it self.assertNotEquals( [], domhelpers.findElementsWithAttribute(templ, "class", "index-link")) tree.setIndexLink(templ, indexFilename) self.assertEqual( [], domhelpers.findElementsWithAttribute(templ, "class", "index-link")) indexLinks = domhelpers.findElementsWithAttribute(templ, "href", indexFilename) self.assertTrue(len(indexLinks) >= numLinks) templ = dom.parse(open(d['template'])) self.assertNotEquals( [], domhelpers.findElementsWithAttribute(templ, "class", "index-link")) indexFilename = None tree.setIndexLink(templ, indexFilename) self.assertEqual( [], domhelpers.findElementsWithAttribute(templ, "class", "index-link"))
def index(document, filename, chapterReference): """ Extract index entries from the given document and store them for later use and insert named anchors so that the index can link back to those entries. Any node with a C{class} attribute set to C{index} is considered an index entry. @type document: A DOM Node or Document @param document: The input document which contains all of the content to be presented. @type filename: C{str} @param filename: A link to the output for the given document which will be included in the index to link to any index entry found here. @type chapterReference: ??? @param chapterReference: ??? @return: C{None} """ entries = domhelpers.findElementsWithAttribute(document, "class", "index") if not entries: return i = 0 for entry in entries: i += 1 anchor = 'index%02d' % i if chapterReference: ref = getSectionReference(entry) or chapterReference else: ref = 'link' indexer.addEntry(filename, anchor, entry.getAttribute('value'), ref) # does nodeName even affect anything? entry.nodeName = entry.tagName = entry.endTagName = 'a' for attrName in entry.attributes.keys(): entry.removeAttribute(attrName) entry.setAttribute('name', anchor)
def setTitle(template, title, chapterNumber): """ Add title and chapter number information to the template document. The title is added to the end of the first C{title} tag and the end of the first tag with a C{class} attribute set to C{title}. If specified, the chapter is inserted before the title. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type title: C{list} of DOM Nodes @param title: Nodes from the input document defining its title. @type chapterNumber: C{int} @param chapterNumber: The chapter number of this content in an overall document. If not applicable, any C{False} value will result in this information being omitted. @return: C{None} """ if numberer.getNumberSections() and chapterNumber: titleNode = dom.Text() # This is necessary in order for cloning below to work. See Python # isuse 4851. titleNode.ownerDocument = template.ownerDocument titleNode.data = '%s. ' % (chapterNumber, ) title.insert(0, titleNode) for nodeList in (domhelpers.findNodesNamed(template, "title"), domhelpers.findElementsWithAttribute( template, "class", 'title')): if nodeList: for titleNode in title: nodeList[0].appendChild(titleNode.cloneNode(True))
def addPlainListings(document, dir): """ Insert text listings into the given document from files in the given directory based on C{listing} nodes. Any node in C{document} with a C{class} attribute set to C{listing} will have source lines taken from the file named in that node's C{href} attribute (searched for in C{dir}) inserted in place of that node. @type document: A DOM Node or Document @param document: The document within which to make listing replacements. @type dir: C{str} @param dir: The directory in which to find source files containing the referenced text listings. @return: C{None} """ for node in domhelpers.findElementsWithAttribute(document, "class", "listing"): filename = node.getAttribute("href") val = ('<pre>\n%s</pre>' % cgi.escape(open(os.path.join(dir, filename)).read())) _replaceWithListing(node, val, filename, "listing")
def visitNode_head(self, node): authorNodes = domhelpers.findElementsWithAttribute( node, 'rel', 'author') authorNodes = [n for n in authorNodes if n.tagName == 'link'] if authorNodes: self.writer('\\author{') authors = [] for aNode in authorNodes: name = aNode.getAttribute('title') href = aNode.getAttribute('href') if href.startswith('mailto:'): href = href[7:] if href: if name: name += ' ' name += '$<$' + href + '$>$' if name: authors.append(name) self.writer(' \\and '.join(authors)) self.writer('}') self.visitNodeDefault(node)
def setIndexLink(template, indexFilename): """ Insert a link to an index document. Any node with a C{class} attribute set to C{index-link} will have its tag name changed to C{a} and its C{href} attribute set to C{indexFilename}. @type template: A DOM Node or Document @param template: The output template which defines the presentation of the version information. @type indexFilename: C{str} @param indexFilename: The address of the index document to which to link. If any C{False} value, this function will do nothing. @return: C{None} """ if not indexFilename: return indexLinks = domhelpers.findElementsWithAttribute(template, "class", "index-link") for link in indexLinks: link.nodeName = link.tagName = link.endTagName = 'a' link.attributes = InsensitiveDict({'href': indexFilename})