changeset 40:f8a5a6ee2097 trunk

Initial support for using Markup in Trac. Only the settings page migrated so far.
author cmlenz
date Mon, 03 Jul 2006 20:20:48 +0000
parents 93b4dcbafd7b
children 686059a8a32b
files examples/trac/trac/Settings.py examples/trac/trac/ticket/web_ui.py examples/trac/trac/web/api.py examples/trac/trac/web/chrome.py examples/trac/trac/web/main.py
diffstat 5 files changed, 83 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/examples/trac/trac/Settings.py
+++ b/examples/trac/trac/Settings.py
@@ -49,12 +49,11 @@
             elif action == 'load':
                 self._do_load(req)
 
-        req.hdf['title'] = 'Settings'
-        req.hdf['settings'] = req.session
+        data = {'session': req.session}
         if req.authname == 'anonymous':
-            req.hdf['settings.session_id'] = req.session.sid
+            data['session_id'] = req.session.sid
 
-        return 'settings.cs', None
+        return 'settings.html', {'settings': data}, None
 
     # Internal methods
 
--- a/examples/trac/trac/ticket/web_ui.py
+++ b/examples/trac/trac/ticket/web_ui.py
@@ -22,7 +22,6 @@
 from trac.attachment import attachments_to_hdf, Attachment, AttachmentModule
 from trac.config import BoolOption, Option
 from trac.core import *
-from trac.env import IEnvironmentSetupParticipant
 from trac.ticket import Milestone, Ticket, TicketSystem, ITicketManipulator
 from trac.ticket.notification import TicketNotifyEmail
 from trac.Timeline import ITimelineEventProvider
@@ -59,30 +58,7 @@
 
 class NewticketModule(TicketModuleBase):
 
-    implements(IEnvironmentSetupParticipant, INavigationContributor,
-               IRequestHandler)
-
-    # IEnvironmentSetupParticipant methods
-
-    def environment_created(self):
-        """Create the `site_newticket.cs` template file in the environment."""
-        if self.env.path:
-            templates_dir = os.path.join(self.env.path, 'templates')
-            if not os.path.exists(templates_dir):
-                os.mkdir(templates_dir)
-            template_name = os.path.join(templates_dir, 'site_newticket.cs')
-            template_file = file(template_name, 'w')
-            template_file.write("""<?cs
-####################################################################
-# New ticket prelude - Included directly above the new ticket form
-?>
-""")
-
-    def environment_needs_upgrade(self, db):
-        return False
-
-    def upgrade_environment(self, db):
-        pass
+    implements(INavigationContributor, IRequestHandler)
 
     # INavigationContributor methods
 
--- a/examples/trac/trac/web/api.py
+++ b/examples/trac/trac/web/api.py
@@ -328,15 +328,17 @@
         else:
             data = self.hdf.render(template)
 
+        self.send(data, content_type, status)
+
+    def send(self, content, content_type='text/html', status=200):
         self.send_response(status)
         self.send_header('Cache-control', 'must-revalidate')
-        self.send_header('Expires', 'Fri, 01 Jan 1999 00:00:00 GMT')
         self.send_header('Content-Type', content_type + ';charset=utf-8')
-        self.send_header('Content-Length', len(data))
+        self.send_header('Content-Length', len(content))
         self.end_headers()
 
         if self.method != 'HEAD':
-            self.write(data)
+            self.write(content)
         raise RequestDone
 
     def send_error(self, exc_info, template='error.cs',
--- a/examples/trac/trac/web/chrome.py
+++ b/examples/trac/trac/web/chrome.py
@@ -37,10 +37,8 @@
         link['type'] = mimetype
     if classname:
         link['class'] = classname
-    idx = 0
-    while req.hdf.get('chrome.links.%s.%d.href' % (rel, idx)):
-        idx += 1
-    req.hdf['chrome.links.%s.%d' % (rel, idx)] = link
+    # FIXME: don't add the same link more than once
+    req.environ.setdefault('trac.chrome.links', {}).setdefault(rel, []).append(link)
 
 def add_stylesheet(req, filename, mimetype='text/css'):
     """Add a link to a style sheet to the HDF data set so that it gets included
@@ -60,16 +58,9 @@
         filename = filename[7:]
     else:
         href = Href(req.base_path).chrome
-    href = href(filename)
-    idx = 0
-    while True:
-        js = req.hdf.get('chrome.scripts.%i.href' % idx)
-        if not js:
-            break
-        if js == href: # already added
-            return
-        idx += 1
-    req.hdf['chrome.scripts.%i' % idx] = {'href': href, 'type': mimetype}
+    script = {'href': href(filename), 'type': mimetype}
+    # FIXME: don't add the same script more than once
+    req.environ.setdefault('trac.chrome.scripts', []).append(script)
 
 def add_javascript(req, filename):
     """Deprecated: use `add_script()` instead."""
@@ -161,40 +152,21 @@
     # IEnvironmentSetupParticipant methods
 
     def environment_created(self):
-        """Create the templates directory and some templates for
-        customization.
-        """
-        def _create_file(filename, data=None):
-            fd = open(filename, 'w')
-            if data:
-                fd.write(data)
-            fd.close()
-
+        """Create the environment templates directory."""
         if self.env.path:
             templates_dir = os.path.join(self.env.path, 'templates')
             if not os.path.exists(templates_dir):
                 os.mkdir(templates_dir)
-            _create_file(os.path.join(templates_dir, 'README'),
-                        'This directory contains project-specific custom '
-                        'templates and style sheet.\n')
-            _create_file(os.path.join(templates_dir, 'site_header.cs'),
-                         """<?cs
-####################################################################
-# Site header - Contents are automatically inserted above Trac HTML
-?>
-""")
-            _create_file(os.path.join(templates_dir, 'site_footer.cs'),
-                         """<?cs
-#########################################################################
-# Site footer - Contents are automatically inserted after main Trac HTML
-?>
-""")
-            _create_file(os.path.join(templates_dir, 'site_css.cs'),
-                         """<?cs
-##################################################################
-# Site CSS - Place custom CSS, including overriding styles here.
-?>
-""")
+
+            fileobj = open(os.path.join(templates_dir, 'site.html'), 'w')
+            try:
+                fileobj.write("""<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:py="http://purl.org/kid/ns#" py:strip="">
+  <!-- Custom match templates fo here -->
+</html>""")
+            finally:
+                fileobj.close()
+
 
     def environment_needs_upgrade(self, db):
         return False
@@ -202,7 +174,6 @@
     def upgrade_environment(self, db):
         pass
 
-
     # IRequestHandler methods
 
     anonymous_request = True
@@ -263,6 +234,40 @@
             dirs += provider.get_templates_dirs()
         return dirs
 
+    def render_response(self, req, template_name, content_type, data):
+        from markup.input import HTML, XML
+        from markup.template import Context, TemplateLoader
+        loader = TemplateLoader(self.get_all_templates_dirs())
+        template = loader.load(template_name)
+
+        data.setdefault('chrome', {}).update({
+            'logo': req.environ.get('trac.chrome.logo', {}),
+            'links': req.environ.get('trac.chrome.links', []),
+            'nav': req.environ.get('trac.chrome.nav', {}),
+            'scripts': req.environ.get('trac.chrome.scripts', [])
+        })
+        data['config'] = self.config
+        data['href'] = req.href
+        data['perm'] = req.perm
+        data['HTML'] = HTML
+        data['XML'] = XML
+        stream = template.generate(Context(**data))
+
+        if content_type is None:
+            content_type = 'text/html'
+        method = {'text/html': 'html'}.get(content_type, 'xml')
+        return stream.render(method)
+
+    def _finalize_hdf(self, req):
+        req.hdf['chrome.links'] = req.environ.get('trac.chrome.links', [])
+        req.hdf['chrome.logo'] = req.environ.get('trac.chrome.logo', {})
+        req.hdf['chrome.scripts'] = req.environ.get('trac.chrome.scripts', [])
+
+        for category, items in req.environ.get('trac.chrome.nav', {}).items():
+            for item in items:
+                prefix = 'chrome.nav.%s.%s' % (category, item['name'])
+                req.hdf[prefix] = item['label']
+
     def populate_hdf(self, req, handler):
         """Add chrome-related data to the HDF."""
 
@@ -293,6 +298,7 @@
             add_link(req, 'shortcut icon', icon, mimetype=mimetype)
 
         # Logo image
+        logo = {}
         logo_src = self.logo_src
         if logo_src:
             logo_src_abs = logo_src.startswith('http://') or \
@@ -304,24 +310,26 @@
                     logo_src = href.chrome('common', logo_src)
             width = self.logo_width > -1 and self.logo_width
             height = self.logo_height > -1 and self.logo_height
-            req.hdf['chrome.logo'] = {
+            logo = {
                 'link': self.logo_link, 'src': logo_src,
                 'src_abs': logo_src_abs, 'alt': self.logo_alt,
                 'width': width, 'height': height
             }
         else:
-            req.hdf['chrome.logo.link'] = self.logo_link
+            logo = {'link': self.logo_link}
+        req.environ['trac.chrome.logo'] = logo
 
         # Navigation links
-        navigation = {}
+        allitems = {}
         active = None
         for contributor in self.navigation_contributors:
             for category, name, text in contributor.get_navigation_items(req):
-                navigation.setdefault(category, {})[name] = text
+                allitems.setdefault(category, {})[name] = text
             if contributor is handler:
                 active = contributor.get_active_navigation_item(req)
 
-        for category, items in [(k, v.items()) for k, v in navigation.items()]:
+        nav = {}
+        for category, items in [(k, v.items()) for k, v in allitems.items()]:
             order = getattr(self, category + '_order')
             def navcmp(x, y):
                 if x[0] not in order:
@@ -331,7 +339,10 @@
                 return cmp(order.index(x[0]), order.index(y[0]))
             items.sort(navcmp)
 
-            for name, text in items:
-                req.hdf['chrome.nav.%s.%s' % (category, name)] = text
+            nav[category] = []
+            for name, label in items:
+                nav[category].append({'name': name, 'label': label})
                 if name == active:
-                    req.hdf['chrome.nav.%s.%s.active' % (category, name)] = 1
+                    nav[category][-1]['active'] = True
+
+        req.environ['trac.chrome.nav'] = nav
--- a/examples/trac/trac/web/main.py
+++ b/examples/trac/trac/web/main.py
@@ -198,10 +198,18 @@
             try:
                 resp = chosen_handler.process_request(req)
                 if resp:
+                    chrome = Chrome(self.env)
                     for filter_ in reversed(self.filters):
                         resp = filter_.post_process_request(req, *resp)
-                    template, content_type = resp
-                    req.display(template, content_type or 'text/html')
+                    if len(resp) == 2:
+                        template, content_type = resp
+                        chrome._finalize_hdf(req)
+                        req.display(template, content_type or 'text/html')
+                    else:
+                        template, data, content_type = resp
+                        output = chrome.render_response(req, template,
+                                                        content_type, data)
+                        req.send(output, content_type or 'text/html')
                 else:
                     for filter_ in reversed(self.filters):
                         filter_.post_process_request(req, None, None)
Copyright (C) 2012-2017 Edgewall Software