Commits

Anonymous committed 23ce89c

[svn] o added auto_discovery_link_tag to asset_tag helper
o fixed a bug in compute_public_path, and it now avoids munging fully-fledged URLs (e.g. http://example.com)
o added tests for both these functions

Comments (0)

Files changed (3)

 WebHelpers ChangeLog
 
 0.1.3
-* Fixed type in feedgenerator import, reported by tiksin@free.fr.
+* Fixed typo in feedgenerator import, reported by tiksin@free.fr.
+
+* Added ``webhelpers.rails.asset_tag``, for generating links to other assets
+  such as javascripts, stylesheets, and feeds.

tests/test_asset_tag.py

 import unittest
 
 from webhelpers.rails.asset_tag import *
+from webhelpers.rails.asset_tag import compute_public_path
 
 class TestAssetTagHelper(TestCase):
+    def test_auto_discovery_link_tag(self):
+        self.assertEqual('<link href="http://feed.com/feed.xml" rel="alternate" title="RSS" type="application/rss+xml" />',
+                         auto_discovery_link_tag('http://feed.com/feed.xml'))
+        self.assertEqual('<link href="http://feed.com/feed.xml" rel="alternate" title="ATOM" type="application/atom+xml" />',
+                         auto_discovery_link_tag('http://feed.com/feed.xml', type='atom'))
+        self.assertEqual('<link href="app.rss" rel="alternate" title="atom feed" type="application/atom+xml" />',
+                         auto_discovery_link_tag('app.rss', type='atom', title='atom feed'))
+        self.assertEqual('<link href="app.rss" rel="alternate" title="My RSS" type="application/rss+xml" />',
+                         auto_discovery_link_tag('app.rss', title='My RSS'))
+        self.assertEqual('<link href="/app.rss" rel="alternate" title="" type="text/html" />',
+                         auto_discovery_link_tag('/app.rss', type='text/html'))
+        self.assertEqual('<link href="/app.html" rel="alternate" title="My RSS" type="text/html" />',
+                         auto_discovery_link_tag('/app.html', title='My RSS', type='text/html'))
+        
     def test_image_tag(self):
         self.assertEqual('<img alt="Xml" src="/images/xml.png" />',
                          image_tag('xml'))
         self.assertEqual('<link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />\n<link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />',
                          stylesheet_link_tag('random.styles', '/css/stylish'))
 
+    def test_compute_public_path(self):
+        self.assertEqual('/test.js', compute_public_path('/test.js'))
+        self.assertEqual('/test.js', compute_public_path('/test.js', 'javascripts'))
+        self.assertEqual('test.js', compute_public_path('test.js'))
+        self.assertEqual('test.js', compute_public_path('test', ext='js'))
+        self.assertEqual('/javascripts/test.js',
+                         compute_public_path('test.js', 'javascripts'))
+        self.assertEqual('/javascripts/test.js',
+                         compute_public_path('test', 'javascripts', 'js'))
+        self.assertEqual('/javascripts/test.js',
+                         compute_public_path('test.js', 'javascripts', 'js'))
+        self.assertEqual('http://www.pylonshq.com',
+                         compute_public_path('http://www.pylonshq.com'))
+        self.assertEqual('http://www.pylonshq.com',
+                         compute_public_path('http://www.pylonshq.com', 'javascripts'))
+        self.assertEqual('http://www.pylonshq.com',
+                         compute_public_path('http://www.pylonshq.com', 'javascripts', 'js'))
+        self.assertEqual('mailto:bdfl@python.org',
+                         compute_public_path('mailto:bdfl@python.org'))
+        self.assertEqual('mailto:bdfl@python.org',
+                         compute_public_path('mailto:bdfl@python.org', 'javascripts'))
+        self.assertEqual('mailto:bdfl@python.org',
+                         compute_public_path('mailto:bdfl@python.org', 'javascripts', 'js'))
+        
 if __name__ == '__main__':
     suite = [unittest.makeSuite(TestAssetTagHelper)]
     for testsuite in suite:

webhelpers/rails/asset_tag.py

 javascripts, stylesheets, and feeds.
 """
 import os
+import urlparse
 from tags import *
 from routes import request_config
 
 # supporting .js files
 javascript_builtins = ('prototype.js', 'scriptaculous.js')
 
+def auto_discovery_link_tag(source, type='rss', **kwargs):
+    """
+    Returns a link tag allowing browsers and news readers (that support it) to auto-detect
+    an RSS or ATOM feed for current page.
+
+    ``source``
+        The URL of the feed. The URL is ultimately prepended with the environment's
+        ``SCRIPT_NAME`` (the root path of the web application), unless the URL is
+        fully-fledged (e.g. http://example.com).
+
+    ``type``
+        The type of feed. Specifying 'rss' or 'atom' automatically translates to a type of
+        'application/rss+xml' or 'application/atom+xml', respectively. Otherwise the type
+        is used as specified. Defaults to 'rss'.
+        
+    Examples::
+
+        >>> auto_discovery_link_tag('http://feed.com/feed.xml')
+        '<link href="http://feed.com/feed.xml" rel="alternate" title="RSS" type="application/rss+xml" />'
+
+        >>> auto_discovery_link_tag('http://feed.com/feed.xml', type='atom')
+        '<link href="http://feed.com/feed.xml" rel="alternate" title="ATOM" type="application/atom+xml" />'
+
+        >>> auto_discovery_link_tag('app.rss', type='atom', title='atom feed')
+        '<link href="app.rss" rel="alternate" title="atom feed" type="application/atom+xml" />'
+
+        >>> auto_discovery_link_tag('/app.html', type='text/html')
+        '<link href="/app.html" rel="alternate" title="" type="text/html" />'
+    """
+    title = ''
+    if type.lower() in ('rss', 'atom'):
+        title = type.upper()
+        type='application/%s+xml' % type.lower()
+
+    tag_args = dict(rel='alternate', type=type, title=title,
+                    href=compute_public_path(source))
+    kwargs.pop('href', None)
+    kwargs.pop('type', None)
+    tag_args.update(kwargs)
+    return tag('link', **tag_args)
+
 def image_tag(source, alt=None, size=None, **options):
     """
     Returns an image tag for the specified ``source``.
 
-    The source's URL path is prepended with '/images/', unless its full path is
-    specified. The source's URL path is ultimately prepended with the environment's
-    ``SCRIPT_NAME`` (the root path of the web application). A source with no filename
-    extension will be appended with the '.png' extension.
+    ``source``
+        The source URL of the image. The URL is prepended with '/images/', unless its full
+        path is specified. The URL is ultimately prepended with the environment's
+        ``SCRIPT_NAME`` (the root path of the web application), unless the URL is
+        fully-fledged (e.g. http://example.com). A source with no filename extension will
+        be automatically appended with the '.png' extension.
     
     ``alt``
         The img's alt tag. Defaults to the source's filename, title cased.
 
         >>> image_tag('xml')
         '<img alt="Xml" src="/images/xml.png" />'
+
         >>> image_tag('rss', 'rss syndication')
         '<img alt="rss syndication" src="/images/rss.png" />'    
     """
 
     Each source's URL path is prepended with '/javascripts/' unless their full path is
     specified. Each source's URL path is ultimately prepended with the environment's
-    ``SCRIPT_NAME`` (the root path of the web application). Sources with no filename
-    extensions will be appended with the '.js' extension.
+    ``SCRIPT_NAME`` (the root path of the web application), unless the URL path is a
+    full-fledged URL (e.g. http://example.com). Sources with no filename extension will be
+    appended with the '.js' extension.
 
     Optionally includes (prepended) WebHelpers' built-in javascripts when passed the
     ``builtins=True`` keyword argument.
 
     Each source's URL path is prepended with '/stylesheets/' unless their full path is
     specified. Each source's URL path is ultimately prepended with the environment's
-    ``SCRIPT_NAME`` (the root path of the web application). Sources with no filename
-    extension will be appended with the '.css' extension.
+    ``SCRIPT_NAME`` (the root path of the web application), unless the URL path is a
+    full-fledged URL (e.g. http://example.com). Sources with no filename extension will be
+    appended with the '.css' extension.
     
     Examples::
 
         >>> stylesheet_link_tag('style')
         '<link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />'
+
         >>> stylesheet_link_tag('/dir/file', media='all')
         '<link href="/dir/file.css" media="all" rel="Stylesheet" type="text/css" />'
     """
                                **tag_options)) for source in sources]
     return '\n'.join(tags)
     
-def compute_public_path(source, root_path, ext=None):
+def compute_public_path(source, root_path=None, ext=None):
     """
-    Format the specified source for publishing, via the public directory.
+    Format the specified source for publishing, via the public directory, if applicable.
     """
-    # Prefix apps deployed under any SCRIPT_NAME path
-    script_name = get_script_name()
-    if ext is not None and not os.path.splitext(os.path.basename(source))[1]:
+    if ext and not os.path.splitext(os.path.basename(source))[1]:
         source = '%s.%s' % (source, ext)
-    if source.startswith('/') or source.startswith('http://'):
-        source = '%s%s' % (script_name, source)
-    else:
-        source = '%s/%s/%s' % (script_name, root_path, source)
+
+    # Avoid munging fully-fledged URLs, including 'mailto:'
+    parsed = urlparse.urlparse(source)
+    if not (parsed[0] and (parsed[1] or parsed[2])):
+        # Prefix apps deployed under any SCRIPT_NAME path
+        if not root_path or source.startswith('/'):
+            source = '%s%s' % (get_script_name(), source)
+        else:
+            source = '%s/%s/%s' % (get_script_name(), root_path, source)
     return source
 
 def get_script_name():
         script_name = config.environ.get('SCRIPT_NAME', '')
     return script_name
 
-__all__ = ['javascript_path', 'javascript_builtins', 'image_tag', 'javascript_include_tag',
-           'stylesheet_link_tag']
+__all__ = ['javascript_path', 'javascript_builtins', 'auto_discovery_link_tag',
+           'image_tag', 'javascript_include_tag', 'stylesheet_link_tag']
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.