[Checkins] SVN: hurry.resource/trunk/ * Implement top-level render functionality
Martijn Faassen
faassen at startifact.com
Wed Dec 16 12:28:00 EST 2009
Log message for revision 106638:
* Implement top-level render functionality
* implement GroupInclusion that can be used to group other
inclusions together.
Changed:
U hurry.resource/trunk/CHANGES.txt
U hurry.resource/trunk/src/hurry/resource/README.txt
U hurry.resource/trunk/src/hurry/resource/__init__.py
U hurry.resource/trunk/src/hurry/resource/core.py
U hurry.resource/trunk/src/hurry/resource/interfaces.py
-=-
Modified: hurry.resource/trunk/CHANGES.txt
===================================================================
--- hurry.resource/trunk/CHANGES.txt 2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/CHANGES.txt 2009-12-16 17:28:00 UTC (rev 106638)
@@ -4,6 +4,19 @@
0.4 (unreleased)
================
+* Expose a ``GroupInclusion`` that only exists to depend on other
+ inclusions. This way it becomes possible to expose a set of
+ different resources together without there being a central resource
+ that depends on them. The GroupInclusion itself is therefore not
+ rendered.
+
+* Create ``render_into_html`` and ``render_topbottom_into_html``
+ functionality, which insert the rendered inclusions into HTML.
+
+* Expose ``render``, ``render_into_html``, ``render_topbottom`` and
+ ``render_topbottom_into_html`` as top-level functions in
+ ``hurry.resource``.
+
* Fix NameError when trying to render an inclusion with unknown extension.
* Document inclusion renderers mechanism in the README.txt.
Modified: hurry.resource/trunk/src/hurry/resource/README.txt
===================================================================
--- hurry.resource/trunk/src/hurry/resource/README.txt 2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/README.txt 2009-12-16 17:28:00 UTC (rev 106638)
@@ -77,6 +77,32 @@
As you can see, ``css`` resources are sorted before ``js`` resources.
+Grouping resources
+==================
+
+It is also possible to define a group that doesn't get rendered
+itself, but groups other resources together that should be rendered::
+
+ >>> from hurry.resource import GroupInclusion
+ >>> group = GroupInclusion([x1, x2])
+
+When we need a group, we'll get all inclusions referenced in it::
+
+ >>> needed = NeededInclusions()
+ >>> needed.need(group)
+ >>> group.inclusions()
+ [<ResourceInclusion 'a.js' in library 'foo'>,
+ <ResourceInclusion 'b.css' in library 'foo'>]
+
+A group can also be depended on; it won't show up in the list of
+inclusions directly::
+
+ >>> more_stuff = ResourceInclusion(foo, 'more_stuff.js', depends=[group])
+ >>> more_stuff.inclusions()
+ [<ResourceInclusion 'a.js' in library 'foo'>,
+ <ResourceInclusion 'b.css' in library 'foo'>,
+ <ResourceInclusion 'more_stuff.js' in library 'foo'>]
+
A convenience spelling
======================
@@ -713,6 +739,52 @@
<script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
<script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+Let's set this a currently needed inclusions::
+
+ >>> request.needed = needed
+
+There is a function available as well for rendering the resources for
+the currently needed inclusion::
+
+ >>> from hurry import resource
+ >>> print resource.render()
+ <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+ <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+
+Inserting resources in HTML
+===========================
+
+When you have the HTML it can be convenient to have a way to insert
+resources directly into some HTML.
+
+The insertion system assumes a HTML text that has a ``<head>`` tag in it::
+
+ >>> html = "<html><head>something more</head></html>"
+
+To insert the resources directly in HTML we can use ``render_into_html``
+on ``needed``::
+
+ >>> print needed.render_into_html(html)
+ <html><head>
+ <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+ <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+ something more</head></html>
+
+The top-level convenience function does this for the currently needed
+resources::
+
+ >>> print resource.render_into_html(html)
+ <html><head>
+ <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+ <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+ something more</head></html>
+
+See below for a way to insert into HTML when bottom fragments are
+involved.
+
Top and bottom fragments
========================
@@ -797,6 +869,17 @@
>>> print bottom
<script type="text/javascript" src="http://localhost/static/foo/y2.js"></script>
+There's also a convenience function for the currently needed inclusion::
+
+ >>> request.needed = needed
+ >>> top, bottom = resource.render_topbottom()
+ >>> print top
+ <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+ <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+ >>> print bottom
+ <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script>
+
When we force bottom rendering of Javascript, there is no effect of
making a resource bottom-safe: all ``.js`` resources will be rendered
at the bottom anyway::
@@ -825,6 +908,35 @@
included at the bottom of the page and still be able to depend on
Javascript code that is.
+Inserting top and bottom resources in HTML
+==========================================
+
+You can also insert top and bottom fragments into HTML. This assumes a
+HTML text that has a ``<head>`` tag in it as well as a ``</body>``
+tag::
+
+ >>> html = "<html><head>rest of head</head><body>rest of body</body></html>"
+
+To insert the resources directly in HTML we can use
+``render_topbottom_into_html`` on ``needed``::
+
+ >>> print needed.render_topbottom_into_html(html)
+ <html><head>
+ <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+ rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script></body></html>
+
+There's also a function available to do this for the currently needed
+resources::
+
+ >>> print resource.render_topbottom_into_html(html)
+ <html><head>
+ <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+ rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+ <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script></body></html>
+
bottom convenience
==================
Modified: hurry.resource/trunk/src/hurry/resource/__init__.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/__init__.py 2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/__init__.py 2009-12-16 17:28:00 UTC (rev 106638)
@@ -1,6 +1,11 @@
-from hurry.resource.core import (Library, ResourceInclusion, NeededInclusions)
+from hurry.resource.core import (Library,
+ ResourceInclusion,
+ GroupInclusion,
+ NeededInclusions)
-from hurry.resource.core import mode, bottom, rollup
+from hurry.resource.core import (mode, bottom, rollup,
+ render, render_topbottom, render_into_html,
+ render_topbottom_into_html)
from hurry.resource.core import (sort_inclusions_topological,
sort_inclusions_by_extension,
Modified: hurry.resource/trunk/src/hurry/resource/core.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/core.py 2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/core.py 2009-12-16 17:28:00 UTC (rev 106638)
@@ -122,12 +122,35 @@
result.append(self)
return result
+class GroupInclusion(object):
+ """An inclusion used to group resources together.
+
+ It doesn't define a resource itself.
+ """
+ implements(interfaces.IInclusion)
+
+ def __init__(self, depends):
+ self.depends = depends
+
+ def need(self):
+ needed = component.getUtility(
+ interfaces.ICurrentNeededInclusions)()
+ needed.need(self)
+
+ def inclusions(self):
+ """Get all inclusions needed by this inclusion.
+ """
+ result = []
+ for depend in self.depends:
+ result.extend(depend.inclusions())
+ return result
+
def normalize_inclusions(library, inclusions):
return [normalize_inclusion(library, inclusion)
for inclusion in inclusions]
def normalize_inclusion(library, inclusion):
- if isinstance(inclusion, ResourceInclusion):
+ if interfaces.IInclusion.providedBy(inclusion):
return inclusion
assert isinstance(inclusion, basestring)
return ResourceInclusion(library, inclusion)
@@ -180,7 +203,11 @@
def render(self):
return render_inclusions(self.inclusions())
-
+
+ def render_into_html(self, html):
+ to_insert = self.render()
+ return html.replace('<head>', '<head>\n %s\n' % to_insert, 1)
+
def render_topbottom(self):
inclusions = self.inclusions()
@@ -208,6 +235,14 @@
return (render_inclusions(top_inclusions, library_urls),
render_inclusions(bottom_inclusions, library_urls))
+ def render_topbottom_into_html(self, html):
+ top, bottom = self.render_topbottom()
+ if top:
+ html = html.replace('<head>', '<head>\n %s\n' % top, 1)
+ if bottom:
+ html = html.replace('</body>', '%s</body>' % bottom, 1)
+ return html
+
def mode(mode):
"""Set the mode for the currently needed resources.
"""
@@ -227,11 +262,31 @@
interfaces.ICurrentNeededInclusions)()
needed.rollup(disable)
+def render():
+ needed = component.getUtility(
+ interfaces.ICurrentNeededInclusions)()
+ return needed.render()
+
+def render_into_html(html):
+ needed = component.getUtility(
+ interfaces.ICurrentNeededInclusions)()
+ return needed.render_into_html(html)
+
+def render_topbottom():
+ needed = component.getUtility(
+ interfaces.ICurrentNeededInclusions)()
+ return needed.render_topbottom()
+
+def render_topbottom_into_html(html):
+ needed = component.getUtility(
+ interfaces.ICurrentNeededInclusions)()
+ return needed.render_topbottom_into_html(html)
+
def apply_mode(inclusions, mode):
return [inclusion.mode(mode) for inclusion in inclusions]
def remove_duplicates(inclusions):
- """Given a set of inclusions, consolidate them so each nly occurs once.
+ """Given a set of inclusions, consolidate them so each only occurs once.
"""
seen = set()
result = []
Modified: hurry.resource/trunk/src/hurry/resource/interfaces.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/interfaces.py 2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/interfaces.py 2009-12-16 17:28:00 UTC (rev 106638)
@@ -9,7 +9,25 @@
"""
name = Attribute("The unique name of the library")
-class IResourceInclusion(Interface):
+class IInclusion(Interface):
+ """Base to all inclusions.
+ """
+ depends = Attribute("A list of inclusions that this "
+ "resource depends on")
+
+ def need():
+ """Express need directly for the current INeededInclusions.
+
+ This is a convenience method to help express inclusions more
+ easily, just do myinclusion.need() to have it be included in
+ the HTML that is currently being rendered.
+ """
+
+ def inclusions():
+ """Get all inclusions needed by this inclusion.
+ """
+
+class IResourceInclusion(IInclusion):
"""Resource inclusion
A resource inclusion specifies how to include a single resource in a
@@ -18,8 +36,6 @@
library = Attribute("The resource library this resource is in")
relpath = Attribute("The relative path of the resource "
"within the resource library")
- depends = Attribute("A list of ResourceInclusions that this "
- "resource depends on")
rollups = Attribute("A list of potential rollup ResourceInclusions "
"that this resource is part of")
bottom = Attribute("A flag. When set to True, this resource "
@@ -45,23 +61,11 @@
If we cannot find a particular mode for a resource, the
original resource inclusion is returned.
"""
-
+
def key():
"""Returns a unique, hashable identifier for the resource inclusion.
"""
- def need():
- """Express need directly for the current INeededInclusions.
-
- This is a convenience method to help express inclusions more
- easily, just do myinclusion.need() to have it be included in
- the HTML that is currently being rendered.
- """
-
- def inclusions():
- """Get all inclusions needed by this inclusion, including itself.
- """
-
class INeededInclusions(Interface):
"""A collection of inclusions that are needed for page display.
"""
@@ -136,7 +140,17 @@
``force_bottom`` settings are ignored; everything is always
rendered on top.
"""
-
+
+ def render_into_html(html):
+ """Render all resource inclusions into HTML.
+
+ The HTML supplied needs to a <head> tag available. The
+ inclusions HTML snippet will be rendered just after this.
+
+ ``force_bottom`` settings are ignored; everything is always
+ rendered on top.
+ """
+
def render_topbottom():
"""Render all resource inclusions into top and bottom snippet.
@@ -162,7 +176,17 @@
Returns top and bottom HTML fragments.
"""
-
+
+ def render_topbottom_into_html(html):
+ """Render all resource inclusions into HTML (top and bottom).
+
+ The HTML supplied needs to a <head> tag available. The
+ top inclusions HTML snippet will be rendered just after this.
+
+ The HTML supplied also needs to have a </body> tag available.
+ bottom inclusions HTML snippet will be rendered just before this.
+ """
+
class ICurrentNeededInclusions(Interface):
def __call__():
"""Return the current needed inclusions object.
More information about the checkins
mailing list