# HG changeset patch # User cmlenz # Date 1151958048 0 # Node ID f8a5a6ee2097a952c7bb5d83b113f66cdb47ab4e # Parent 93b4dcbafd7b09b5f53bf57ef1c4998541b2a889 Initial support for using Markup in Trac. Only the settings page migrated so far. diff --git a/examples/trac/trac/Settings.py b/examples/trac/trac/Settings.py --- 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 diff --git a/examples/trac/trac/ticket/web_ui.py b/examples/trac/trac/ticket/web_ui.py --- 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(""" -""") - - def environment_needs_upgrade(self, db): - return False - - def upgrade_environment(self, db): - pass + implements(INavigationContributor, IRequestHandler) # INavigationContributor methods diff --git a/examples/trac/trac/web/api.py b/examples/trac/trac/web/api.py --- 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', diff --git a/examples/trac/trac/web/chrome.py b/examples/trac/trac/web/chrome.py --- 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'), - """ -""") - _create_file(os.path.join(templates_dir, 'site_footer.cs'), - """ -""") - _create_file(os.path.join(templates_dir, 'site_css.cs'), - """ -""") + + fileobj = open(os.path.join(templates_dir, 'site.html'), 'w') + try: + fileobj.write(""" + +""") + 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 diff --git a/examples/trac/trac/web/main.py b/examples/trac/trac/web/main.py --- 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)