| 1 | # -*- coding: utf-8 -*- |
|---|
| 2 | |
|---|
| 3 | """ |
|---|
| 4 | PyLucid headline anchor |
|---|
| 5 | ~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 6 | |
|---|
| 7 | A middleware to add a human readable, url safe anchor to all html headlines. |
|---|
| 8 | Every anchor is a permalink to the page. So you can easy copy&paste the |
|---|
| 9 | links for several use. |
|---|
| 10 | |
|---|
| 11 | more info: http://pylucid.org/_goto/147/Headline-anchor/ |
|---|
| 12 | |
|---|
| 13 | Last commit info: |
|---|
| 14 | ~~~~~~~~~~~~~~~~~ |
|---|
| 15 | $LastChangedDate: $ |
|---|
| 16 | $Rev: $ |
|---|
| 17 | $Author: $ |
|---|
| 18 | |
|---|
| 19 | :copyleft: 2008 by the PyLucid team, see AUTHORS for more details. |
|---|
| 20 | :license: GNU GPL v3 or above, see LICENSE for more details. |
|---|
| 21 | """ |
|---|
| 22 | |
|---|
| 23 | import string, re |
|---|
| 24 | |
|---|
| 25 | from PyLucid.tools.shortcuts import makeUnique |
|---|
| 26 | |
|---|
| 27 | HEADLINE_RE = re.compile(r"<h(\d)>(.+?)</h(\d)>(?iusm)") |
|---|
| 28 | |
|---|
| 29 | HEADLINE = ( |
|---|
| 30 | u'<h%(no)s id="%(anchor)s">' |
|---|
| 31 | '<a title="Link to this section" href="%(link)s#%(anchor)s" class="anchor">' |
|---|
| 32 | '%(txt)s</a>' |
|---|
| 33 | '</h%(no)s>\n' |
|---|
| 34 | ) |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | class HeadlineAnchor(object): |
|---|
| 38 | def process_response(self, request, response): |
|---|
| 39 | """ |
|---|
| 40 | Add anchors to every html headlines. |
|---|
| 41 | """ |
|---|
| 42 | # Put only the statistic into HTML pages |
|---|
| 43 | if not "html" in response._headers["content-type"][1]: |
|---|
| 44 | # No HTML Page |
|---|
| 45 | return response |
|---|
| 46 | |
|---|
| 47 | try: |
|---|
| 48 | context = request.CONTEXT |
|---|
| 49 | except AttributeError: |
|---|
| 50 | # No cms page request (e.g. the _install section) -> do nothing |
|---|
| 51 | return response |
|---|
| 52 | |
|---|
| 53 | # Get the permalink to the current page |
|---|
| 54 | current_page = context["PAGE"] |
|---|
| 55 | self.permalink = current_page.get_permalink() |
|---|
| 56 | |
|---|
| 57 | # A list of all existing anchors, used in self.add_anchor() |
|---|
| 58 | self.anchor_list = [] |
|---|
| 59 | |
|---|
| 60 | content = response.content |
|---|
| 61 | if not isinstance(content, unicode): |
|---|
| 62 | # FIXME: In my shared webhosting environment is response.content a |
|---|
| 63 | # string and not unicode. Why? |
|---|
| 64 | from django.utils.encoding import force_unicode |
|---|
| 65 | try: |
|---|
| 66 | content = force_unicode(content) |
|---|
| 67 | except: |
|---|
| 68 | return response |
|---|
| 69 | |
|---|
| 70 | # add the anchor with re.sub |
|---|
| 71 | new_content = HEADLINE_RE.sub(self.add_anchor, content) |
|---|
| 72 | response.content = new_content |
|---|
| 73 | |
|---|
| 74 | return response |
|---|
| 75 | |
|---|
| 76 | def add_anchor(self, matchobj): |
|---|
| 77 | """ |
|---|
| 78 | add a unique anchor to a html headline. |
|---|
| 79 | """ |
|---|
| 80 | txt = matchobj.group(2) |
|---|
| 81 | |
|---|
| 82 | # Strip all non-ASCII and make the anchor unique |
|---|
| 83 | anchor = makeUnique(txt, self.anchor_list) |
|---|
| 84 | |
|---|
| 85 | # Remember the current anchor. So makeUnique can add a number on double |
|---|
| 86 | # anchors. |
|---|
| 87 | self.anchor_list.append(anchor) |
|---|
| 88 | |
|---|
| 89 | result = HEADLINE % { |
|---|
| 90 | "no": matchobj.group(1), |
|---|
| 91 | "txt": txt, |
|---|
| 92 | "link": self.permalink, |
|---|
| 93 | "anchor": anchor, |
|---|
| 94 | } |
|---|
| 95 | return result |
|---|