Skip to content
This repository
Browse code

shake.templates.link_to now can match the current URL to a list of UR…

…Ls and/or endpoint names
  • Loading branch information...
commit a3cfc46c4dfa9e9db1ff65023f0dfb3c9dd7d6d5 1 parent 837a36f
Juan-Pablo Scaletti authored October 16, 2012
5  CHANGES.md
Source Rendered
... ...
@@ -1,5 +1,10 @@
1 1
 # Shake Changelog
2 2
 
  3
+## Version 1.6
  4
+
  5
+- `shake.templates.link_to` now can match the current URL to a list of URLs and/or endpoint names.
  6
+- Impoved project skeleton
  7
+
3 8
 ## Version 1.5
4 9
 
5 10
 - Fix bug that was preventing to set the session cookie while using the development server.
2  shake/__init__.py
@@ -53,5 +53,5 @@ def hello(request):
53 53
 NotAllowed = Forbidden
54 54
 redirect_to = redirect
55 55
 
56  
-__version__ = '1.5.4'
  56
+__version__ = '1.5.5' #dev
57 57
 
62  shake/templates.py
@@ -6,11 +6,12 @@
6 6
     Template globals, filters and tests
7 7
 
8 8
 """
  9
+import re
9 10
 from xml.sax.saxutils import quoteattr
10 11
 
11 12
 from jinja2 import Markup
12 13
 
13  
-from .helpers import local, to_unicode
  14
+from .helpers import local, to_unicode, url_for
14 15
 
15 16
 
16 17
 __all__ = (
@@ -28,7 +29,7 @@ def dumb_plural(num, plural='s', singular=''):
28 29
 def html_attrs(classes=None, **kwargs):
29 30
     """Generate HTML attributes from the provided keyword arguments.
30 31
 
31  
-    The output value is sorted by the passed keys, to provide consistent
  32
+    The output value is sorted by the passed keys, to provide a consistent
32 33
     output.  Because of the frequent use of the normally reserved keyword
33 34
     `class`, `classes` is used instead. Also, all underscores are translated
34 35
     to regular dashes.
@@ -64,19 +65,23 @@ def html_attrs(classes=None, **kwargs):
64 65
     return u' '.join(attrs)
65 66
 
66 67
 
67  
-def link_to(text='', url='', classes='', partial=False, wrapper=None, **kwargs):
  68
+URL_RE = ur'^([a-z]{3,7}:(//)?)?([^/:]+%s|([0-9]{1,3}\.){3}[0-9]{1,3})(:[0-9]+)?(\/.*)?$'
  69
+
  70
+
  71
+def link_to(text='', endpoint='', classes='', wrapper=None, partial=False, **kwargs):
68 72
     """Build an HTML anchor element for the provided URL.
69 73
     If the url match the beginning of that in the current request, an `active`
70 74
     class is added.  This is intended to be use to build navigation links.
71 75
 
72 76
     Other HTML attributes are generated from the keyword argument
73 77
     (see the `html_attrs` function).
  78
+
74 79
     Example:
75 80
 
76 81
         >>> link_to('Hello', '/hello/', title='click me')
77 82
         u'<a href="/hello/" title="click me">Hello</a>'
78  
-        >>> link_to('Hello', '/hello/', wrapper='li', classes='last', title='Hi')
79  
-        u'<li class="last" title="Hi"><a href="/hello/">Hello</a></li>'
  83
+        >>> link_to('Hello', '/hello/', wrapper='li', classes='last')
  84
+        u'<li class="last"><a href="/hello/">Hello</a></li>'
80 85
 
81 86
         >>> from werkzeug.test import EnvironBuilder
82 87
         >>> builder = EnvironBuilder(method='GET', path='/foo/')
@@ -86,15 +91,52 @@ class is added.  This is intended to be use to build navigation links.
86 91
         >>> link_to('Bar', '/foo/')
87 92
         u'<a href="/foo/" class="active">Bar</a>'
88 93
 
  94
+    :param text:
  95
+        The text (or HTML) of the link.
  96
+
  97
+    :param endpoint:
  98
+        URL or endpoint name. This can also be a *list* of URLs and/or
  99
+        endpoint names. The first one will be used for the link, the rest only
  100
+        to match the current page
  101
+
  102
+    :param classes:
  103
+        Because of the frequent use of the normally reserved keyword
  104
+        `class`, `classes` is used instead.
  105
+
  106
+    :param wrapper:
  107
+        Optional tag name of a wrapper element for the link.
  108
+        The "active" class and other attributes will be applied to this
  109
+        element instead of the <a>. Example:
  110
+
  111
+        >>> link_to('Hello', '/hello/', wrapper='li', title='Hi')
  112
+        u'<li title="Hi"><a href="/hello/">Hello</a></li>'
  113
+
  114
+    :param partial:
  115
+        If True, the endpoint will be matched against the beginning of the
  116
+        current URL. For instance, if the current URL is `/foo/bar/123/`,
  117
+        an endpoint like `/foo/bar/` will be considered a match.
  118
+
  119
+    :param kwargs:
  120
+        Extra HTML attributes. All underscores will be translated to
  121
+        regular dashes.
  122
+
89 123
     """
90 124
     request = local.request
91  
-    path_ = request.path.rstrip('/')
92  
-    url_ = url.rstrip('/')
93  
-    if path_ == url_ or (partial and path_.startswith(url_)):
94  
-        classes += ' active'
  125
+    path = request.path.rstrip('/')
  126
+
  127
+    patterns = endpoint if isinstance(endpoint, (list, tuple)) else [endpoint]
  128
+    patterns = [p
  129
+        if p.startswith('/') or re.match(URL_RE, p) else url_for(p)
  130
+        for p in patterns]
  131
+
  132
+    for url in patterns:
  133
+        url = url.rstrip('/')
  134
+        if path == url or (partial and path.startswith(url)):
  135
+            classes += ' active'
  136
+            break
95 137
 
96 138
     data = {
97  
-        'url': url,
  139
+        'url': patterns[0],
98 140
         'text': text,
99 141
         'attrs': html_attrs(classes, **kwargs),
100 142
     }
8  tests/test_render.py
@@ -158,6 +158,14 @@ def test_link_to():
158 158
     expected = u'<a href="/foo/" class="active">Bar</a>'
159 159
     assert expected == html
160 160
 
  161
+    html = link_to('Bar', ['/hello/', path])
  162
+    expected = u'<a href="/hello/" class="active">Bar</a>'
  163
+    assert expected == html
  164
+
  165
+    html = link_to('Hello', ['/hello/', '/world/'], title='click me')
  166
+    expected = u'<a href="/hello/" title="click me">Hello</a>'
  167
+    assert expected == html
  168
+
161 169
 # -----------------------------------------------------------------------------
162 170
 
163 171
 def get_test_env(path='/', **kwargs):

0 notes on commit a3cfc46

Please sign in to comment.
Something went wrong with that request. Please try again.