#!/usr/bin/env python

from HTMLParser import HTMLParser
from pelican import signals, readers, contents
import os, re, markdown

class Header:
    HeadRegex = re.compile("h[1-6]")
    def __init__(self, tag, value):
        self.tag = tag
        self.value = value

    def __repr__(self):
        return "{}:{}".format(self.tag, self.value.encode("UTF-8"))

    @classmethod
    def is_header(cls, tag):
        return None != cls.HeadRegex.match(tag)

class HeaderParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.headers = []
        self.tagOpen = False

    def handle_starttag(self, tag, attrs):
        if Header.is_header(tag):
            self.headers.append(Header(tag, ""))
            self.tagOpen = True

    def handle_endtag(self, tag):
        self.tagOpen = False

    def handle_data(self, data):
        if self.tagOpen and len(self.headers) > 0:
            self.headers[-1].value = data

def extract_headers(content):
    if isinstance(content, contents.Static):
        return

    markdownFilePath = content.source_path
    extension = os.path.splitext(markdownFilePath)[1][1:]
    if not extension in readers.MarkdownReader.file_extensions:
        return

    htmlContent = markdown.markdown(content._content, extensions=['headerid(forceid=False)'])
    parser = HeaderParser()
    parser.feed(htmlContent)
    content.html_headers = parser.headers
    # set article title to h1 if any
    content.html_h1 = ""
    for head in parser.headers:
        if "h1" == head.tag:
            content.html_h1 = head.value
        if not content.html_h1:
            content.html_h1 = content.title
    # set article toc
    content.html_toc = "<ul>"
    prevHead = None
    linkFormat = "<a href='#toc_{0}'>{0}</a>"
    #linkFormat = ""
    for i in xrange(len(parser.headers)):
        head = parser.headers[i]
        # first elem
        if 0 == i:
            content.html_toc += ("<li>" + linkFormat).format(head.value)
            continue
        # last elem
        if len(parser.headers) == (i + 1):
            content.html_toc += ("<li>" + linkFormat + "</li>").format(head.value)
            break;
        prevHead = parser.headers[i-1]
        nextHead = parser.headers[i+1]
        if head.tag > prevHead.tag:
            content.html_toc += ("<ul><li>" + linkFormat).format(head.value)
            if head.tag == nextHead.tag:
                content.html_toc += "</li>"
            elif head.tag >= nextHead.tag and nextHead.tag:
                content.html_toc += "</li></ul>"
        elif head.tag < prevHead.tag:
            content.html_toc += ("</li></ul></li><li>" + linkFormat).format(head.value)
        else:
            content.html_toc += ("</li><li>" + linkFormat).format(head.value)

    if len(parser.headers) > 1:
        content.html_toc += "</li></li></ul>"
    else:
        content.html_toc += "</li></ul>"
    print content.html_toc

def register():
    signals.content_object_init.connect(extract_headers)

if __name__ == "__main__":
    parser = H1Parser()
    htmlStr = open("./index.html").read()
    parser.feed(htmlStr)
    print parser.h1


@@ -1721,16 +1721,39 @@
  = None%0A
+    openListSetNum = 0%0A
     link
@@ -1886,16 +1886,43 @@
 ders%5Bi%5D%0A
+        head.parent = None%0A
         
@@ -2059,278 +2059,141 @@
     
-# last elem%0A        if len(parser.headers) == (i + 1):%0A            content.html_toc += (%22%3Cli%3E%22 + linkFormat + %22%3C/li%3E%22).format(head.value)%0A            break;%0A        prevHead = parser.headers%5Bi-1%5D%0A        nextHead = parser.headers%5Bi+1%5D%0A        if head.tag %3E prevHead.tag:
+prevHead = parser.headers%5Bi-1%5D%0A        if head.tag %3E prevHead.tag:%0A            head.parent = prevHead%0A            openListSetNum += 1
 %0A   
@@ -2270,28 +2270,26 @@
 ue)%0A        
-    
+el
 if head.tag 
@@ -2292,15 +2292,14 @@
 tag 
-== next
+%3C prev
 Head
@@ -2320,57 +2320,71 @@
     
-    content.html_toc += %22%3C/li%3E%22%0A            elif 
+currParent = prevHead.parent%0A            while currParent and (
 head
@@ -2392,41 +2392,63 @@
 tag 
-%3E= nextHead.tag and nextHead.tag:
+%3C= currParent.tag):%0A                openListSetNum -= 1
 %0A   
@@ -2472,32 +2472,33 @@
 ent.html_toc += 
+(
 %22%3C/li%3E%3C/ul%3E%22%0A   
@@ -2497,46 +2497,93 @@
 ul%3E%22
-%0A        elif head.tag %3C prevHead.tag:
+)%0A                currParent = currParent.parent%0A            head.parent = currParent
 %0A   
@@ -2623,18 +2623,8 @@
 li%3E%3C
-/ul%3E%3C/li%3E%3C
 li%3E%22
@@ -2663,32 +2663,74 @@
 )%0A        else:%0A
+            head.parent = prevHead.parent%0A
             cont
@@ -2800,34 +2800,32 @@
     
-if len(parser.headers) %3E 1
+while openListSetNum %3E 0
 :%0A  
@@ -2850,22 +2850,18 @@
 _toc += 
+(
 %22
-%3C/li%3E
 %3C/li%3E%3C/u
@@ -2867,17 +2867,68 @@
 ul%3E%22
-%0A    else
+)%0A        openListSetNum -= 1%0A    if len(parser.headers) %3E 1
 :%0A  
@@ -2970,21 +2970,29 @@
 l%3E%22%0A    
-print
+else:%0A       
  content
@@ -3000,16 +3000,27 @@
 html_toc
+ += %22%3C/ul%3E%22
 %0A%0Adef re

fix bugs in extract toc