1import markdown 2from markdown import etree 3 4DEFAULT_URL = "http://www.freewisdom.org/projects/python-markdown/" 5DEFAULT_CREATOR = "Yuri Takhteyev" 6DEFAULT_TITLE = "Markdown in Python" 7GENERATOR = "http://www.freewisdom.org/projects/python-markdown/markdown2rss" 8 9month_map = { "Jan" : "01", 10 "Feb" : "02", 11 "March" : "03", 12 "April" : "04", 13 "May" : "05", 14 "June" : "06", 15 "July" : "07", 16 "August" : "08", 17 "September" : "09", 18 "October" : "10", 19 "November" : "11", 20 "December" : "12" } 21 22def get_time(heading): 23 24 heading = heading.split("-")[0] 25 heading = heading.strip().replace(",", " ").replace(".", " ") 26 27 month, date, year = heading.split() 28 month = month_map[month] 29 30 return rdftime(" ".join((month, date, year, "12:00:00 AM"))) 31 32def rdftime(time): 33 34 time = time.replace(":", " ") 35 time = time.replace("/", " ") 36 time = time.split() 37 return "%s-%s-%sT%s:%s:%s-08:00" % (time[0], time[1], time[2], 38 time[3], time[4], time[5]) 39 40 41def get_date(text): 42 return "date" 43 44class RssExtension (markdown.Extension): 45 46 def extendMarkdown(self, md, md_globals): 47 48 self.config = { 'URL' : [DEFAULT_URL, "Main URL"], 49 'CREATOR' : [DEFAULT_CREATOR, "Feed creator's name"], 50 'TITLE' : [DEFAULT_TITLE, "Feed title"] } 51 52 md.xml_mode = True 53 54 # Insert a tree-processor that would actually add the title tag 55 treeprocessor = RssTreeProcessor(md) 56 treeprocessor.ext = self 57 md.treeprocessors['rss'] = treeprocessor 58 md.stripTopLevelTags = 0 59 md.docType = '<?xml version="1.0" encoding="utf-8"?>\n' 60 61class RssTreeProcessor(markdown.treeprocessors.Treeprocessor): 62 63 def run (self, root): 64 65 rss = etree.Element("rss") 66 rss.set("version", "2.0") 67 68 channel = etree.SubElement(rss, "channel") 69 70 for tag, text in (("title", self.ext.getConfig("TITLE")), 71 ("link", self.ext.getConfig("URL")), 72 ("description", None)): 73 74 element = etree.SubElement(channel, tag) 75 element.text = text 76 77 for child in root: 78 79 if child.tag in ["h1", "h2", "h3", "h4", "h5"]: 80 81 heading = child.text.strip() 82 item = etree.SubElement(channel, "item") 83 link = etree.SubElement(item, "link") 84 link.text = self.ext.getConfig("URL") 85 title = etree.SubElement(item, "title") 86 title.text = heading 87 88 guid = ''.join([x for x in heading if x.isalnum()]) 89 guidElem = etree.SubElement(item, "guid") 90 guidElem.text = guid 91 guidElem.set("isPermaLink", "false") 92 93 elif child.tag in ["p"]: 94 try: 95 description = etree.SubElement(item, "description") 96 except UnboundLocalError: 97 # Item not defined - moving on 98 pass 99 else: 100 if len(child): 101 content = "\n".join([etree.tostring(node) 102 for node in child]) 103 else: 104 content = child.text 105 pholder = self.markdown.htmlStash.store( 106 "<![CDATA[ %s]]>" % content) 107 description.text = pholder 108 109 return rss 110 111 112def makeExtension(configs): 113 114 return RssExtension(configs) 115