16516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruimport markdown
26516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querufrom markdown import etree
36516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
46516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruDEFAULT_URL = "http://www.freewisdom.org/projects/python-markdown/"
56516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruDEFAULT_CREATOR = "Yuri Takhteyev"
66516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruDEFAULT_TITLE = "Markdown in Python"
76516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruGENERATOR = "http://www.freewisdom.org/projects/python-markdown/markdown2rss"
86516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
96516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querumonth_map = { "Jan" : "01",
106516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "Feb" : "02",
116516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "March" : "03",
126516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "April" : "04",
136516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "May" : "05",
146516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "June" : "06",
156516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "July" : "07",
166516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "August" : "08",
176516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "September" : "09",
186516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "October" : "10",
196516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "November" : "11",
206516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "December" : "12" }
216516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
226516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef get_time(heading):
236516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
246516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    heading = heading.split("-")[0]
256516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    heading = heading.strip().replace(",", " ").replace(".", " ")
266516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
276516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    month, date, year = heading.split()
286516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    month = month_map[month]
296516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
306516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return rdftime(" ".join((month, date, year, "12:00:00 AM")))
316516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
326516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef rdftime(time):
336516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
346516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    time = time.replace(":", " ")
356516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    time = time.replace("/", " ")
366516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    time = time.split()
376516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return "%s-%s-%sT%s:%s:%s-08:00" % (time[0], time[1], time[2],
386516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                                        time[3], time[4], time[5])
396516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
406516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
416516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef get_date(text):
426516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return "date"
436516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
446516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruclass RssExtension (markdown.Extension):
456516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
466516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    def extendMarkdown(self, md, md_globals):
476516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
486516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        self.config = { 'URL' : [DEFAULT_URL, "Main URL"],
496516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        'CREATOR' : [DEFAULT_CREATOR, "Feed creator's name"],
506516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        'TITLE' : [DEFAULT_TITLE, "Feed title"] }
516516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
526516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        md.xml_mode = True
536516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
546516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        # Insert a tree-processor that would actually add the title tag
556516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        treeprocessor = RssTreeProcessor(md)
566516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        treeprocessor.ext = self
576516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        md.treeprocessors['rss'] = treeprocessor
586516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        md.stripTopLevelTags = 0
596516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        md.docType = '<?xml version="1.0" encoding="utf-8"?>\n'
606516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
616516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruclass RssTreeProcessor(markdown.treeprocessors.Treeprocessor):
626516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
636516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    def run (self, root):
646516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
656516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        rss = etree.Element("rss")
666516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        rss.set("version", "2.0")
676516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
686516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        channel = etree.SubElement(rss, "channel")
696516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
706516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        for tag, text in (("title", self.ext.getConfig("TITLE")),
716516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                          ("link", self.ext.getConfig("URL")),
726516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                          ("description", None)):
736516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
746516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            element = etree.SubElement(channel, tag)
756516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            element.text = text
766516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
776516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        for child in root:
786516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
796516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if child.tag in ["h1", "h2", "h3", "h4", "h5"]:
806516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
816516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                heading = child.text.strip()
826516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                item = etree.SubElement(channel, "item")
836516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                link = etree.SubElement(item, "link")
846516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                link.text = self.ext.getConfig("URL")
856516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                title = etree.SubElement(item, "title")
866516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                title.text = heading
876516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
886516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                guid = ''.join([x for x in heading if x.isalnum()])
896516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                guidElem = etree.SubElement(item, "guid")
906516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                guidElem.text = guid
916516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                guidElem.set("isPermaLink", "false")
926516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
936516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            elif child.tag in ["p"]:
946516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                try:
956516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    description = etree.SubElement(item, "description")
966516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                except UnboundLocalError:
976516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    # Item not defined - moving on
986516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    pass
996516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                else:
1006516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    if len(child):
1016516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        content = "\n".join([etree.tostring(node)
1026516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                                             for node in child])
1036516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    else:
1046516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        content = child.text
1056516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    pholder = self.markdown.htmlStash.store(
1066516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                                                "<![CDATA[ %s]]>" % content)
1076516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    description.text = pholder
1086516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1096516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return rss
1106516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1116516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1126516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef makeExtension(configs):
1136516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1146516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return RssExtension(configs)
115