toc.py: now we can generate a table-of-contents
[webber:webber.git] / plugins / toc.py
1 # -*- coding: iso-8859-1 -*-
2 from webber import *
3 import htmlentitydefs, re
4
5
6 reHeader = re.compile(r'<h(\d)(.*)>(.*)</h\1>', re.IGNORECASE | re.MULTILINE)
7 toc = []
8 labels = {}
9
10
11 toc_min_lines = 30
12
13
14 @set_hook("checkconfig")
15 def checkconfig(params):
16         if cfg.has_key("toc_min_lines"):
17                 global toc_min_lines
18                 toc_min_lines = int(cfg.toc_min_times)
19
20
21 def slugify(text, separator):
22     """Based on http://snipplr.com/view/26266/create-slugs-in-python/"""
23
24     ret = ""
25     for c in text.lower():
26         try:
27             ret += htmlentitydefs.codepoint2name[ord(c)]
28         except:
29             ret += c
30     ret = re.sub("([a-zA-Z])(uml|acute|grave|circ|tilde|cedil)", r"\1", ret)
31     ret = re.sub("\W", " ", ret)
32     ret = re.sub(" +", separator, ret)
33     return ret.strip()
34
35
36 def repl(m):
37     global toc
38     label = slugify(m.group(3), "_")
39     if labels.has_key(label):
40         n = 0
41         while True:
42             l = "%s_%d" % (label, n)
43             if not labels.has_key(l):
44                 label = l
45                 break
46             n += 1
47
48     toc.append( (label, int(m.group(1))-1, m.group(3)) )
49     return '<h%s%s>%s<a name="%s">&nbsp;</a></h%s>' % (
50         m.group(1),
51         m.group(2),
52         m.group(3),
53         label,
54         m.group(1))
55
56
57 @set_hook("linkify")
58 def linkify(params):
59     global toc
60     global labels
61     toc = []
62     labels = {}
63
64     # Very small pages don't need a table-of-contents
65     if params.file.contents.count("\n") < toc_min_lines:
66         return
67
68     params.file.contents = reHeader.sub(repl, params.file.contents)
69
70
71
72 @set_function("get_toc")
73 def get_toc():
74     level = 1
75     res = []
76     res.append('<ul id="toc">')
77     for (label, lvl, txt) in toc:
78         while lvl > level:
79             res.append("%s<ul>" % ("  "*level))
80             level += 1
81         while lvl < level:
82             level -= 1
83             res.append("%s</ul>" % ("  "*level))
84         res.append('%s<li><a href="#%s">%s</a></li>' % ("  " * level, label, txt))
85     while level:
86         level -= 1
87         res.append("%s</ul>" % ("  "*level))
88     return "\n".join(res)