aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Yunusov <nedrlab@gmail.com>2008-07-31 03:06:39 +0500
committerArtem Yunusov <nedrlab@gmail.com>2008-07-31 03:06:39 +0500
commitbd185087dc899b6157f821fdd29561caffcc4682 (patch)
treedb9445d13bdbd59fb999664462031d3630e0ffb0
parentc99366a182afa3b0cd8da12075cd9ff8e15ae089 (diff)
downloadmarkdown-bd185087dc899b6157f821fdd29561caffcc4682.tar.gz
markdown-bd185087dc899b6157f821fdd29561caffcc4682.tar.bz2
markdown-bd185087dc899b6157f821fdd29561caffcc4682.zip
A lot of bug fixes, added ElementTree support for extensions, some new tests.
-rwxr-xr-x[-rw-r--r--]markdown.py154
-rw-r--r--mdx_footnotes.py117
-rw-r--r--mdx_rss.py102
-rw-r--r--tests/extensions-x-footnotes/footnote.html82
-rwxr-xr-xtests/markdown-test/angle-links-and-img.html7
-rwxr-xr-xtests/markdown-test/angle-links-and-img.txt4
-rwxr-xr-xtests/misc/blockquote-below-paragraph.html6
-rwxr-xr-xtests/misc/blockquote-below-paragraph.txt3
-rwxr-xr-xtests/misc/html-comments.html2
-rwxr-xr-xtests/misc/html-comments.txt2
10 files changed, 263 insertions, 216 deletions
diff --git a/markdown.py b/markdown.py
index e4235ff..3891ac3 100644..100755
--- a/markdown.py
+++ b/markdown.py
@@ -62,26 +62,32 @@ def message(level, text):
def isstr(s):
return isinstance(s, unicode) or isinstance(s, str)
-try:
- # Python 2.5+
- import xml.etree.cElementTree as etree
-except ImportError:
+def importETree():
+ """ Importing best variant of ElementTree
+ and returning module object """
+
try:
# Python 2.5+
- import xml.etree.ElementTree as etree
+ import xml.etree.cElementTree as etree
except ImportError:
try:
- # normal cElementTree install
- import cElementTree as etree
+ # Python 2.5+
+ import xml.etree.ElementTree as etree
except ImportError:
try:
- # normal ElementTree install
- import elementtree.ElementTree as etree
+ # normal cElementTree install
+ import cElementTree as etree
except ImportError:
- message(CRITICAL,
- "Failed to import ElementTree from any known place")
- sys.exit(1)
+ try:
+ # normal ElementTree install
+ import elementtree.ElementTree as etree
+ except ImportError:
+ message(CRITICAL,
+ "Failed to import ElementTree from any known place")
+ sys.exit(1)
+ return etree
+etree = importETree()
def indentETree(elem, level=0):
@@ -173,8 +179,8 @@ def isBlockLevel (tag):
def codepoint2name(code):
- """ Returns entity defenition by code, or code
- if there is no such entity defenition"""
+ """ Returns entity definition by code, or code
+ if there is no such entity definition"""
entity = htmlentitydefs.codepoint2name.get(code)
if entity:
return "%s%s;" % (AND_SUBSTITUTE, entity)
@@ -351,7 +357,7 @@ class HeaderPreprocessor(Preprocessor):
"""
Replace underlined headers with hashed headers to avoid
- the nead for lookahead later.
+ the need for lookahead later.
"""
def run (self, lines):
@@ -394,7 +400,7 @@ class LinePreprocessor(Preprocessor):
blockquote_re = re.compile(r'^(> )+')
def run (self, lines):
- """ Find a store HR lines. """
+ """ Find and replace HR lines. """
for i in range(len(lines)):
prefix = ''
@@ -467,9 +473,8 @@ expression and needs support the following methods:
pattern.getCompiledRegExp() - returns a regular expression
- pattern.handleMatch(m, doc) - takes a match object and returns
- a NanoDom node (as a part of the provided
- doc) or None
+ pattern.handleMatch(m) - takes a match object and returns
+ a ElementTree element or just plain text
All of python markdown's built-in patterns subclass from Pattern,
but you can add additional patterns that don't.
@@ -521,16 +526,20 @@ else:
#LINK_RE = NOIMG + BRK + r'\s*\(([^\)]*)\)' # [text](url)
LINK_RE = NOIMG + BRK + \
-r'''\(\s*(((?:(?:\(.*?\))|[^\(\)]))*?|<\10*?>)\s*((['"])(.*)\12)?\)''' # [text](url) or [text](<url>)
+r'''\(\s*(<.*?>|((?:(?:\(.*?\))|[^\(\)]))*?)\s*((['"])(.*)\12)?\)''' # [text](url) or [text](<url>)
+#r'''\(\s*(<.*?>|((?:(?:\(.*?\))|[^\(\)]))*)\s*((['"])(.*)\12)?\)''' # [text](url) or [text](<url>)
+
+#LINK_RE2 = NOIMG + BRK + \
+#r'''\(\s*(((?:(?:\(.*?\))|[^\(\)]))*?|<\10*?>)\s*((['"])(.*)\12)?\)''' # [text](url) or [text](<url>)
-IMAGE_LINK_RE = r'\!' + BRK + r'\s*\(([^\)]*)\)' # ![alttxt](http://x.com/)
+IMAGE_LINK_RE = r'\!' + BRK + r'\s*\((<.*?>|([^\)]*))\)' # ![alttxt](http://x.com/) or ![alttxt](<http://x.com/>)
REFERENCE_RE = NOIMG + BRK+ r'\s*\[([^\]]*)\]' # [Google][3]
IMAGE_REFERENCE_RE = r'\!' + BRK + '\s*\[([^\]]*)\]' # ![alt text][2]
NOT_STRONG_RE = r'( \* )' # stand-alone * or _
AUTOLINK_RE = r'<((?:f|ht)tps?://[^>]*)>' # <http://www.123.com>
AUTOMAIL_RE = r'<([^> \!]*@[^> ]*)>' # <me@example.com>
#HTML_RE = r'(\<[^\>]*\>)' # <...>
-HTML_RE = r'(\<[a-zA-Z/][^\>]*\>)' # <...>
+HTML_RE = r'(\<([a-zA-Z/][^\>]*?|\!--.*?--)\>)' # <...>
ENTITY_RE = r'(&[\#a-zA-Z0-9]*;)' # &amp;
LINE_BREAK_RE = r' \n' # two spaces at end of line
LINE_BREAK_2_RE = r' $' # two spaces at end of text
@@ -559,15 +568,13 @@ class Pattern:
def handleMatch(self, m):
"""
- Return a NanoDom element from the given match. Subclasses should
+ Return a ElementTree element from the given match. Subclasses should
override this method.
Keyword arguments:
* m: A re match object containing a match of the pattern.
- * doc: An instance of a NanoDom Document.
-
"""
pass
@@ -578,7 +585,7 @@ class Pattern:
BasePattern = Pattern # for backward compatibility
class SimpleTextPattern (Pattern):
- """ Return a simple TextNode of group(2) of a Pattern. """
+ """ Return a simple text of group(2) of a Pattern. """
def handleMatch(self, m):
text = m.group(2)
if text == INLINE_PLACEHOLDER_PREFIX:
@@ -587,7 +594,7 @@ class SimpleTextPattern (Pattern):
class SimpleTagPattern (Pattern):
"""
- Return NanoDom Element of type `tag` with a child TextNode of group(2)
+ Return element of type `tag` with a text attribute of group(3)
of a Pattern.
"""
@@ -601,12 +608,12 @@ class SimpleTagPattern (Pattern):
return el
class SubstituteTagPattern (SimpleTagPattern):
- """ Return a NanoDom ELement of type `tag` with no children. """
+ """ Return a eLement of type `tag` with no children. """
def handleMatch (self, m):
return etree.Element(self.tag)
class BacktickPattern (Pattern):
- """ Return a NanoDom `<code>` Element containing the matching text. """
+ """ Return a `<code>` element containing the matching text. """
def __init__ (self, pattern):
Pattern.__init__(self, pattern)
self.tag = "code"
@@ -619,7 +626,7 @@ class BacktickPattern (Pattern):
class DoubleTagPattern (SimpleTagPattern):
"""
- Return a TextNode nested in tag2 nested in tag1.
+ Return a ElementTree element nested in tag2 nested in tag1.
Usefull for strong emphasis etc.
"""
@@ -642,7 +649,7 @@ class HtmlPattern (Pattern):
class LinkPattern (Pattern):
- """ Return a NanoDom link Element from the given match. """
+ """ Return a link element from the given match. """
def handleMatch(self, m):
el = etree.Element("a")
el.text = m.group(2)
@@ -693,13 +700,16 @@ class LinkPattern (Pattern):
return urlunparse(url)
class ImagePattern(LinkPattern):
- """ Return a NanoDom img Element from the given match. """
+ """ Return a img element from the given match. """
def handleMatch(self, m):
el = etree.Element("img")
src_parts = m.group(9).split()
if src_parts:
- el.set('src', self.sanatize_url(src_parts[0]))
+ src = src_parts[0]
+ if src[0] == "<" and src[-1] == ">":
+ src = src[1:-1]
+ el.set('src', self.sanatize_url(src))
else:
el.set('src', "")
if len(src_parts) > 1:
@@ -714,7 +724,7 @@ class ImagePattern(LinkPattern):
return el
class ReferencePattern(LinkPattern):
- """ Match to a stored reference and return a NanoDom link Element. """
+ """ Match to a stored reference and return link element. """
def handleMatch(self, m):
if m.group(9):
@@ -743,7 +753,7 @@ class ReferencePattern(LinkPattern):
class ImageReferencePattern (ReferencePattern):
- """ Match to a stored reference and return a NanoDom img Element. """
+ """ Match to a stored reference and return img element. """
def makeTag(self, href, title, text):
el = etree.Element("img")
el.set("src", self.sanatize_url(href))
@@ -821,10 +831,10 @@ There are two types of post-processors: Postprocessor and TextPostprocessor
class Postprocessor:
"""
- Postprocessors are run before the dom it converted back into text.
+ Postprocessors are run before the ElementTree serialization.
Each Postprocessor implements a "run" method that takes a pointer to a
- NanoDom document, modifies it as necessary and returns a NanoDom
+ ElementTree, modifies it as necessary and returns a ElementTree
document.
Postprocessors must extend markdown.Postprocessor.
@@ -834,11 +844,10 @@ class Postprocessor:
"""
- def run(self, dom):
+ def run(self, et):
"""
Subclasses of Postprocessor should implement a `run` method, which
- takes a NanoDOm document and returns a (possably modified) NanoDom
- document.
+ takes a ElementTree and returns a (possably modified) ElementTree.
"""
pass
@@ -847,7 +856,7 @@ class Postprocessor:
class TextPostprocessor:
"""
- TextPostprocessors are run after the dom it converted back into text.
+ TextPostprocessors are run after the ElementTree it converted back into text.
Each TextPostprocessor implements a "run" method that takes a pointer to a
text string, modifies it as necessary and returns a text string.
@@ -1107,6 +1116,7 @@ class CorePatterns:
'isline2': r'(\-*)', # ---
'isline3': r'(\_*)', # ___
'tabbed': r'((\t)|( ))(.*)', # an indented line
+ 'tabbed2': r'(()( ))(.*)', # an indented line
'quoted': r'[ ]{0,2}> ?(.*)', # a quoted block ("> ...")
}
@@ -1279,8 +1289,7 @@ class Markdown:
for prep in self.preprocessors :
self.lines = prep.run(self.lines)
- # Create a NanoDom tree from the lines and attach it to Document
-
+ # Create a ElementTree from the lines
buffer = []
for line in self.lines:
@@ -1292,16 +1301,7 @@ class Markdown:
buffer.append(line)
self._processSection(self.root, buffer)
-
- #self._processSection(self.top_element, self.lines)
-
- # Not sure why I put this in but let's leave it for now.
- #self.top_element.appendChild(self.doc.createTextNode('\n'))
-
- # Run the post-processors
- for postprocessor in self.postprocessors:
- postprocessor.run(self.doc)
-
+
return etree.ElementTree(self.root)
@@ -1323,10 +1323,15 @@ class Markdown:
Returns: None
"""
-
+
# Loop through lines until none left.
while lines:
-
+
+ # Skipping empty line
+ if not lines[0]:
+ lines = lines[1:]
+ continue
+
# Check if this section starts with a list, a blockquote or
# a code block
@@ -1370,7 +1375,7 @@ class Markdown:
else: # Ok, so it's just a simple block
paragraph, lines = self._linesUntil(lines, lambda line:
- not line.strip())
+ not line.strip() or line[0] == '>')
if len(paragraph) and paragraph[0].startswith('#'):
self._processHeader(parent_elem, paragraph)
@@ -1448,7 +1453,7 @@ class Markdown:
Keyword arguments:
- * parent_elem: A dom element to which the content will be added
+ * parent_elem: A ElementTree element to which the content will be added
* lines: a list of lines
* inList: a level
@@ -1486,7 +1491,7 @@ class Markdown:
# Check if the next non-blank line is still a part of the list
if ( RE.regExp['ul'].match(next) or
RE.regExp['ol'].match(next) or
- RE.regExp['tabbed'].match(next) ):
+ RE.regExp['tabbed'].match(next)):
# get rid of any white space in the line
items[item].append(line.strip())
looseList = loose or looseList
@@ -1497,7 +1502,7 @@ class Markdown:
# Now we need to detect list items (at the current level)
# while also detabing child elements if necessary
- for expr in ['ul', 'ol', 'tabbed']:
+ for expr in ['ul', 'ol', 'tabbed', 'tabbed2']:
m = RE.regExp[expr].match(line)
if m:
@@ -1507,7 +1512,7 @@ class Markdown:
# at the beginning of the list item
items.append([m.group(1)])
item += 1
- elif expr == 'tabbed': # This line needs to be detabbed
+ elif expr == 'tabbed' or expr == 'tabbed2': # This line needs to be detabbed
items[item].append(m.group(4)) #after the 'tab'
i += 1
@@ -1518,7 +1523,7 @@ class Markdown:
else:
i += 1
- # Add the dom elements
+ # Add the ElementTree elements
for item in items:
li = etree.SubElement(ul, "li")
@@ -1540,7 +1545,8 @@ class Markdown:
i = -1
for line in lines:
i += 1
- if condition(line): break
+ if condition(line):
+ break
else:
i += 1
return lines[:i], lines[i:]
@@ -1554,7 +1560,7 @@ class Markdown:
Keyword arguments:
- * parent_elem: DOM element to which the content will be added
+ * parent_elem: ElementTree element to which the content will be added
* lines: a list of lines
* inList: a level
@@ -1592,13 +1598,13 @@ class Markdown:
def _processCodeBlock(self, parent_elem, lines, inList):
"""
Given a list of document lines starting with a code block
- finds the end of the block, puts it into the dom verbatim
+ finds the end of the block, puts it into the ElementTree verbatim
wrapped in ("<pre><code>") and recursively processes the
the remainder of the text file.
Keyword arguments:
- * parent_elem: DOM element to which the content will be added
+ * parent_elem: ElementTree element to which the content will be added
* lines: a list of lines
* inList: a level
@@ -1710,11 +1716,11 @@ class Markdown:
def _processPlaceholders(self, data, parent):
"""
- Processes string with placeholders and generates DOM tree.
+ Processes string with placeholders and generates ElementTree tree.
- * data: string with placeholders instead of DOM elements.
+ * data: string with placeholders instead of ElementTree elements.
- Returns: NanoDOM Document object with applied inline patterns.
+ Returns: list with ElementTree elements with applied inline patterns.
"""
def linkText(text):
@@ -1880,7 +1886,6 @@ class Markdown:
markdownTree = self._transform()
-
return markdownTree
@@ -1898,9 +1903,16 @@ class Markdown:
"""
tree = self.markdownToTree(source)
-
+
root = self.applyInlinePatterns(tree).getroot()
-
+
+ # Run the post-processors
+ for postprocessor in self.postprocessors:
+ postprocessor.stash = self.htmlStash
+ newRoot = postprocessor.run(root)
+ if newRoot:
+ root = newRoot
+
indentETree(root)
xml = codecs.decode(etree.tostring(root, encoding="utf8"), "utf8")
diff --git a/mdx_footnotes.py b/mdx_footnotes.py
index 4464c50..b46efbb 100644
--- a/mdx_footnotes.py
+++ b/mdx_footnotes.py
@@ -27,6 +27,7 @@ FN_BACKLINK_TEXT = "zz1337820767766393qq"
import re, markdown, random
+from markdown import etree
class FootnoteExtension (markdown.Extension):
@@ -80,15 +81,21 @@ class FootnoteExtension (markdown.Extension):
self.used_footnotes={}
self.footnotes = {}
- def findFootnotesPlaceholder(self, doc) :
- def findFootnotePlaceholderFn(node=None, indent=0):
- if node.type == 'text':
- if node.value.find(self.getConfig("PLACE_MARKER")) > -1 :
- return True
-
- fn_div_list = doc.find(findFootnotePlaceholderFn)
- if fn_div_list :
- return fn_div_list[0]
+ def findFootnotesPlaceholder(self, root):
+
+ def finder(element):
+ for child in element:
+ if child.text:
+ if child.text.find(self.getConfig("PLACE_MARKER")) > -1:
+ return child, True
+ if child.tail:
+ if child.tail.find(self.getConfig("PLACE_MARKER")) > -1:
+ return (child, element), False
+ finder(child)
+ return None
+
+ res = finder(root)
+ return res
def setFootnote(self, id, text) :
@@ -100,7 +107,7 @@ class FootnoteExtension (markdown.Extension):
def makeFootnoteRefId(self, num) :
return 'fnr%d%s' % (num, self.footnote_suffix)
- def makeFootnotesDiv (self, doc) :
+ def makeFootnotesDiv (self, root) :
"""Creates the div with class='footnote' and populates it with
the text of the footnotes.
@@ -109,45 +116,39 @@ class FootnoteExtension (markdown.Extension):
if not self.footnotes.keys() :
return None
- div = doc.createElement("div")
- div.setAttribute('class', 'footnote')
- hr = doc.createElement("hr")
- div.appendChild(hr)
- ol = doc.createElement("ol")
- div.appendChild(ol)
+ div = etree.Element("div")
+ div.set('class', 'footnote')
+ hr = etree.SubElement(div, "hr")
+ ol = etree.SubElement(div, "ol")
+
footnotes = [(self.used_footnotes[id], id)
for id in self.footnotes.keys()]
footnotes.sort()
for i, id in footnotes :
- li = doc.createElement('li')
- li.setAttribute('id', self.makeFootnoteId(i))
+ li = etree.SubElement(ol, "li")
+ li.set("id", self.makeFootnoteId(i))
self.md._processSection(li, self.footnotes[id].split("\n"), looseList=1)
- #li.appendChild(doc.createTextNode(self.footnotes[id]))
-
- backlink = doc.createElement('a')
- backlink.setAttribute('href', '#' + self.makeFootnoteRefId(i))
- backlink.setAttribute('class', 'footnoteBackLink')
- backlink.setAttribute('title',
- 'Jump back to footnote %d in the text' % i)
- backlink.appendChild(doc.createTextNode(FN_BACKLINK_TEXT))
-
- if li.childNodes :
- node = li.childNodes[-1]
- if node.type == "text" :
- li.appendChild(backlink)
- elif node.nodeName == "p":
- node.appendChild(backlink)
+ backlink = etree.Element("a")
+ backlink.set("href", "#" + self.makeFootnoteRefId(i))
+ backlink.set("class", "footnoteBackLink")
+ backlink.set("title",
+ "Jump back to footnote %d in the text" % i)
+ backlink.text = FN_BACKLINK_TEXT
+
+ if li.getchildren():
+ node = li[-1]
+ if node.text:
+ li.append(backlink)
+ elif node.tag == "p":
+ node.append(backlink)
else:
- p = doc.createElement('p')
- p.appendChild(backlink)
- li.appendChild(p)
-
- ol.appendChild(li)
-
+ p = etree.SubElement(li, "p")
+ p.append(backlink)
+ div = self.md.applyInlinePatterns(etree.ElementTree(div)).getroot()
return div
@@ -194,7 +195,7 @@ class FootnotePreprocessor :
plain = lines[:i]
detabbed, theRest = self.blockGuru.detectTabbed(lines[i+1:])
-
+
self.footnotes.setFootnote(id,
footnote + "\n"
+ "\n".join(detabbed))
@@ -227,15 +228,14 @@ class FootnotePattern (markdown.Pattern) :
markdown.Pattern.__init__(self, pattern)
self.footnotes = footnotes
- def handleMatch(self, m, doc) :
- sup = doc.createElement('sup')
- a = doc.createElement('a')
- sup.appendChild(a)
+ def handleMatch(self, m) :
+ sup = etree.Element("sup")
+ a = etree.SubElement(sup, "a")
id = m.group(2)
num = self.footnotes.used_footnotes[id]
- sup.setAttribute('id', self.footnotes.makeFootnoteRefId(num))
- a.setAttribute('href', '#' + self.footnotes.makeFootnoteId(num))
- a.appendChild(doc.createTextNode(str(num)))
+ sup.set('id', self.footnotes.makeFootnoteRefId(num))
+ a.set('href', '#' + self.footnotes.makeFootnoteId(num))
+ a.text = str(num)
return sup
class FootnotePostprocessor (markdown.Postprocessor):
@@ -243,14 +243,25 @@ class FootnotePostprocessor (markdown.Postprocessor):
def __init__ (self, footnotes) :
self.footnotes = footnotes
- def run(self, doc) :
- footnotesDiv = self.footnotes.makeFootnotesDiv(doc)
- if footnotesDiv :
- fnPlaceholder = self.extension.findFootnotesPlaceholder(doc)
- if fnPlaceholder :
+ def run(self, root):
+ footnotesDiv = self.footnotes.makeFootnotesDiv(root)
+ if footnotesDiv:
+ result = self.extension.findFootnotesPlaceholder(root)
+
+ if result:
+ node, isText = result
+ if isText:
+ node.text = None
+ node.getchildren().insert(0, footnotesDiv)
+ else:
+ child, element = node
+ ind = element.getchildren().find(child)
+ element.getchildren().insert(ind + 1, footnotesDiv)
+ child.tail = None
+
fnPlaceholder.parent.replaceChild(fnPlaceholder, footnotesDiv)
else :
- doc.documentElement.appendChild(footnotesDiv)
+ root.append(footnotesDiv)
class FootnoteTextPostprocessor (markdown.Postprocessor):
diff --git a/mdx_rss.py b/mdx_rss.py
index 2117baf..b88b9b5 100644
--- a/mdx_rss.py
+++ b/mdx_rss.py
@@ -1,4 +1,5 @@
import markdown
+from markdown import etree
DEFAULT_URL = "http://www.freewisdom.org/projects/python-markdown/"
DEFAULT_CREATOR = "Yuri Takhteyev"
@@ -18,7 +19,7 @@ month_map = { "Jan" : "01",
"November" : "11",
"December" : "12" }
-def get_time(heading) :
+def get_time(heading):
heading = heading.split("-")[0]
heading = heading.strip().replace(",", " ").replace(".", " ")
@@ -28,7 +29,7 @@ def get_time(heading) :
return rdftime(" ".join((month, date, year, "12:00:00 AM")))
-def rdftime(time) :
+def rdftime(time):
time = time.replace(":", " ")
time = time.replace("/", " ")
@@ -37,12 +38,12 @@ def rdftime(time) :
time[3], time[4], time[5])
-def get_date(text) :
+def get_date(text):
return "date"
class RssExtension (markdown.Extension):
- def extendMarkdown(self, md, md_globals) :
+ def extendMarkdown(self, md, md_globals):
self.config = { 'URL' : [DEFAULT_URL, "Main URL"],
'CREATOR' : [DEFAULT_CREATOR, "Feed creator's name"],
@@ -59,62 +60,59 @@ class RssExtension (markdown.Extension):
class RssPostProcessor (markdown.Postprocessor):
- def __init__(self, md) :
+ def __init__(self, md):
pass
- def run (self, doc) :
+ def run (self, root):
- oldDocElement = doc.documentElement
- rss = doc.createElement("rss")
- rss.setAttribute('version', '2.0')
+ rss = etree.Element("rss")
+ rss.set("version", "2.0")
- doc.appendChild(rss)
+ channel = etree.SubElement(rss, "channel")
- channel = doc.createElement("channel")
- rss.appendChild(channel)
for tag, text in (("title", self.ext.getConfig("TITLE")),
("link", self.ext.getConfig("URL")),
("description", None)):
- channel.appendChild(doc.createElement(tag, textNode = text))
-
- for child in oldDocElement.childNodes :
-
- if child.type == "element" :
-
- if child.nodeName in ["h1", "h2", "h3", "h4", "h5"] :
-
- heading = child.childNodes[0].value.strip()
-
- item = doc.createElement("item")
- channel.appendChild(item)
- item.appendChild(doc.createElement("link",
- self.ext.getConfig("URL")))
-
- item.appendChild(doc.createElement("title", heading))
-
- guid = ''.join([x for x in heading if x.isalnum()])
-
- guidElem = doc.createElement("guid", guid)
- guidElem.setAttribute("isPermaLink", "false")
- item.appendChild(guidElem)
-
- elif child.nodeName in ["p"] :
-
- description = doc.createElement("description")
-
-
- content = "\n".join([node.toxml()
- for node in child.childNodes])
-
- cdata = doc.createCDATA(content)
-
- description.appendChild(cdata)
-
- if item :
- item.appendChild(description)
-
-
-def makeExtension(configs) :
+
+ element = etree.SubElement(channel, tag)
+ element.text = text
+
+ for child in root:
+
+
+ if child.tag in ["h1", "h2", "h3", "h4", "h5"] :
+
+ heading = child.text.strip()
+
+ item = etree.SubElement(channel, "item")
+
+ link = etree.SubElement(item, "link")
+ link.text = self.ext.getConfig("URL")
+
+ title = etree.SubElement(item, "title")
+ title.text = heading
+
+ guid = ''.join([x for x in heading if x.isalnum()])
+
+ guidElem = etree.SubElement(item, "guid")
+ guidElem.text = guid
+ guidElem.set("isPermaLink", "false")
+
+ elif child.tag in ["p"] :
+ if item:
+ description = etree.SubElement(item, "description")
+ if len(child):
+ content = "\n".join([etree.tostring(node)
+ for node in child])
+ else:
+ content = child.text
+ pholder = self.stash.store("<![CDATA[ %s]]>" % content)
+ description.text = pholder
+
+ return rss
+
+
+def makeExtension(configs):
return RssExtension(configs)
diff --git a/tests/extensions-x-footnotes/footnote.html b/tests/extensions-x-footnotes/footnote.html
index de0070d..4a844be 100644
--- a/tests/extensions-x-footnotes/footnote.html
+++ b/tests/extensions-x-footnotes/footnote.html
@@ -1,40 +1,42 @@
-<p>This is the body with a footnote<sup id="fnr1-5771256"><a href="#fn1-5771256">1</a></sup> or two<sup id="fnr2-5771256"><a href="#fn2-5771256">2</a></sup> or more<sup id="fnr3-5771256"><a href="#fn3-5771256">3</a></sup> <sup id="fnr4-5771256"><a href="#fn4-5771256">4</a></sup>.
-</p>
-
-<div class="footnote"><hr/><ol>
- <li id="fn1-5771256"><p>Footnote that ends with a list:
-</p>
-<ul>
- <li>
- item 1
- </li>
-
- <li>
- item 2
- </li>
-</ul>
-<p><a href="#fnr1-5771256" class="footnoteBackLink" title="Jump back to footnote 1 in the text">&#8617;</a>
-</p>
-
- </li>
-
- <li id="fn2-5771256"><blockquote><p>This footnote is a blockquote.
-</p>
-</blockquote><p><a href="#fnr2-5771256" class="footnoteBackLink" title="Jump back to footnote 2 in the text">&#8617;</a>
-</p>
-
- </li>
-
- <li id="fn3-5771256"><p>A simple oneliner.<a href="#fnr3-5771256" class="footnoteBackLink" title="Jump back to footnote 3 in the text">&#8617;</a>
-</p>
-
- </li>
-
- <li id="fn4-5771256"><p>A footnote with multiple paragraphs.
-</p>
-<p>Paragraph two.<a href="#fnr4-5771256" class="footnoteBackLink" title="Jump back to footnote 4 in the text">&#8617;</a>
-</p>
-
- </li>
-</ol>
-</div> \ No newline at end of file
+<p>This is the body with a footnote<sup id="fnr1-506476047">
+ <a href="#fn1-506476047">1</a>
+ </sup> or two<sup id="fnr2-506476047">
+ <a href="#fn2-506476047">2</a>
+ </sup> or more<sup id="fnr3-506476047">
+ <a href="#fn3-506476047">3</a>
+ </sup>
+ <sup id="fnr4-506476047">
+ <a href="#fn4-506476047">4</a>
+ </sup>.</p>
+<div class="footnote">
+ <hr />
+ <ol>
+ <li id="fn1-506476047">
+ <p>Footnote that ends with a list:</p>
+ <ul>
+ <li>item 1</li>
+ <li>item 2</li>
+ </ul>
+ <p>
+ <a class="footnoteBackLink" href="#fnr1-506476047" title="Jump back to footnote 1 in the text">&#8617;</a>
+ </p>
+ </li>
+ <li id="fn2-506476047">
+ <blockquote>
+ <p>This footnote is a blockquote.</p>
+ </blockquote>
+ <p>
+ <a class="footnoteBackLink" href="#fnr2-506476047" title="Jump back to footnote 2 in the text">&#8617;</a>
+ </p>
+ </li>
+ <li id="fn3-506476047">
+ <p>A simple oneliner.<a class="footnoteBackLink" href="#fnr3-506476047" title="Jump back to footnote 3 in the text">&#8617;</a>
+ </p>
+ </li>
+ <li id="fn4-506476047">
+ <p>A footnote with multiple paragraphs.</p>
+ <p>Paragraph two.<a class="footnoteBackLink" href="#fnr4-506476047" title="Jump back to footnote 4 in the text">&#8617;</a>
+ </p>
+ </li>
+ </ol>
+</div>
diff --git a/tests/markdown-test/angle-links-and-img.html b/tests/markdown-test/angle-links-and-img.html
new file mode 100755
index 0000000..e32b6e6
--- /dev/null
+++ b/tests/markdown-test/angle-links-and-img.html
@@ -0,0 +1,7 @@
+<p>
+ <a href="simple link" title="title">link</a>
+ <img alt="image" src="http://example.com/image.jpg" />
+ <a href="http://example.com/(()((())923)(">link</a>
+ <img alt="image" src="link(()))(" />
+</p>
+
diff --git a/tests/markdown-test/angle-links-and-img.txt b/tests/markdown-test/angle-links-and-img.txt
new file mode 100755
index 0000000..1dbf404
--- /dev/null
+++ b/tests/markdown-test/angle-links-and-img.txt
@@ -0,0 +1,4 @@
+[link](<simple link> "title")
+![image](<http://example.com/image.jpg>)
+[link](<http://example.com/(()((())923)(>)
+![image](<link(()))(>)
diff --git a/tests/misc/blockquote-below-paragraph.html b/tests/misc/blockquote-below-paragraph.html
new file mode 100755
index 0000000..5757a9a
--- /dev/null
+++ b/tests/misc/blockquote-below-paragraph.html
@@ -0,0 +1,6 @@
+<p>Paragraph</p>
+<blockquote>
+ <p>Block quote
+Yep</p>
+</blockquote>
+
diff --git a/tests/misc/blockquote-below-paragraph.txt b/tests/misc/blockquote-below-paragraph.txt
new file mode 100755
index 0000000..0dd4d5c
--- /dev/null
+++ b/tests/misc/blockquote-below-paragraph.txt
@@ -0,0 +1,3 @@
+Paragraph
+>Block quote
+>Yep
diff --git a/tests/misc/html-comments.html b/tests/misc/html-comments.html
new file mode 100755
index 0000000..ac08082
--- /dev/null
+++ b/tests/misc/html-comments.html
@@ -0,0 +1,2 @@
+<p>Here is HTML <!-- **comment** -->
+and once more <p><!--comment--></p></p>
diff --git a/tests/misc/html-comments.txt b/tests/misc/html-comments.txt
new file mode 100755
index 0000000..cac4da5
--- /dev/null
+++ b/tests/misc/html-comments.txt
@@ -0,0 +1,2 @@
+Here is HTML <!-- **comment** -->
+and once more <p><!--comment--></p>