44 | | == Themes == |
45 | | A theme looks like the theme defined above. So this could be the `mytheme/site.html`: |
46 | | |
| 71 | == Templates == |
| 72 | Chances in the templates are quite small. The `layout.html` should look like this: |
| 73 | {{{ |
| 74 | #!html |
| 75 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
| 76 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| 77 | <html xmlns="http://www.w3.org/1999/xhtml" |
| 78 | xmlns:xi="http://www.w3.org/2001/XInclude" |
| 79 | xmlns:py="http://genshi.edgewall.org/" |
| 80 | py:strip=""> |
| 81 | |
| 82 | <head py:match="head"> |
| 83 | <title py:with="title = list(select('title/text()'))"> |
| 84 | <py:if test="title">${title} –</py:if> |
| 85 | ${' – '.join(filter(None, [project.name, 'Trac']))} |
| 86 | </title> |
| 87 | <py:if test="chrome.links"> |
| 88 | <py:for each="rel, links in chrome.links.items()"> |
| 89 | <link rel="${rel}" py:for="link in links" py:attrs="link" /> |
| 90 | </py:for> |
| 91 | </py:if> |
| 92 | <py:if test="'SEARCH_VIEW' in perm" id="search"> |
| 93 | <link type="application/opensearchdescription+xml" rel="search" |
| 94 | href="${href.search('opensearch')}" title="Search $project.name"/> |
| 95 | </py:if> |
| 96 | <script py:for="script in chrome.scripts" |
| 97 | type="${script.type}" src="${script.href}"></script> |
| 98 | ${Markup('<!--[if lt IE 7]>')} |
| 99 | <script type="text/javascript" src="${href.chrome('common/js/ie_pre7_hacks.js')}"></script> |
| 100 | ${Markup('<![endif]-->')} |
| 101 | ${select("*[local-name() != 'title']")} |
| 102 | </head> |
| 103 | |
| 104 | <!-- navigation helper --> |
| 105 | <div py:def="navigation(category)" id="${category}" class="nav"> |
| 106 | <ul py:if="chrome.nav[category]"> |
| 107 | <li py:for="idx, item in enumerate(chrome.nav[category])" |
| 108 | class="${classes(first_last(idx, chrome.nav[category]), active=item.active)}">${item.label}</li> |
| 109 | </ul> |
| 110 | </div> |
| 111 | |
| 112 | <body py:match="body"> |
| 113 | |
| 114 | <!-- search form --> |
| 115 | <form py:if="'SEARCH_VIEW' in perm" id="search" |
| 116 | action="${href.search()}" method="get"><div> |
| 117 | <label for="proj-search">Search:</label> |
| 118 | <input type="text" id="proj-search" name="q" size="18" accesskey="f" value="" /> |
| 119 | <input type="submit" value="Search" /> |
| 120 | <input type="hidden" name="wiki" value="on" /> |
| 121 | <input type="hidden" name="changeset" value="on" /> |
| 122 | <input type="hidden" name="ticket" value="on" /> |
| 123 | </div></form> |
| 124 | |
| 125 | <!-- meta navigation --> |
| 126 | ${navigation('metanav')} |
| 127 | |
| 128 | <!-- main navigation --> |
| 129 | ${navigation('mainnav')} |
| 130 | |
| 131 | <!-- trac body --> |
| 132 | <div id="body"> |
| 133 | ${select('*|text()')} |
| 134 | |
| 135 | <script type="text/javascript" py:if="chrome.late_links"> |
| 136 | <py:for each="link in chrome.late_links.get('stylesheet')"> |
| 137 | $.loadStyleSheet("${link.href}", "${link.title}"); |
| 138 | </py:for> |
| 139 | </script> |
| 140 | <script py:for="script in chrome.late_scripts" |
| 141 | type="${script.type}" src="${script.href}"></script> |
| 142 | </div> |
| 143 | |
| 144 | <!-- alternative links --> |
| 145 | <div id="altlinks" py:if="'alternate' in chrome.links"> |
| 146 | <h3>Download in other formats:</h3> |
| 147 | <ul> |
| 148 | <li py:for="idx, link in enumerate(chrome.links.alternate)" |
| 149 | class="${first_last(idx, chrome.links.alternate)}"> |
| 150 | <a rel="nofollow" href="${link.href}" class="${link['class']}" |
| 151 | py:content="link.title" /> |
| 152 | </li> |
| 153 | </ul> |
| 154 | </div> |
| 155 | |
| 156 | <!-- footer --> |
| 157 | <div id="footer"><hr/> |
| 158 | <a id="tracpowered" href="http://trac.edgewall.org/"><img |
| 159 | src="${href.chrome('common/trac_logo_mini.png')}" height="30" |
| 160 | width="107" alt="Trac Powered"/></a> |
| 161 | <p class="left"> |
| 162 | Powered by <a href="${href.about()}"><strong>Trac ${trac.version}</strong></a><br /> |
| 163 | By <a href="http://www.edgewall.org/">Edgewall Software</a>. |
| 164 | </p> |
| 165 | <p class="right">${chrome.footer}</p> |
| 166 | </div> |
| 167 | </body> |
| 168 | |
| 169 | <xi:include href="${theme.get_theme_site_template()}"><xi:fallback /></xi:include> |
| 170 | </html> |
| 171 | }}} |
| 172 | |
| 173 | All the data elements moved into little div/ul boxes which are quite flat. The included filename is retrieved from the theme provider. |
| 174 | |
| 175 | == Default Theme == |
| 176 | Here the default theme for the new structure. |
| 177 | |
| 178 | |
| 179 | {{{ |
| 180 | #!python |
| 181 | class TracTheme(Component): |
| 182 | implements(IThemeProvider) |
| 183 | |
| 184 | # IThemeProvider |
| 185 | def get_theme_htdocs_id(self): |
| 186 | return 'common' |
| 187 | |
| 188 | def get_theme_site_template(self): |
| 189 | return 'trac_site.html' |
| 190 | }}} |
| 191 | |
| 192 | And here the `trac_site.html`. It's called this way so that we can load `site.html` from the instance folder. All other themes have to create a folder for their themes with an unique name. |
60 | | <!-- normal design used by the project webpage --> |
61 | | <div id="header"> |
62 | | <h1>Project Trac</h1> |
63 | | </div> |
64 | | <div id="navigation"> |
65 | | <li><a href="/">Index</a></li> |
66 | | <li><a href="/downloads">Downloads</a></li> |
67 | | <li><a href="/wiki/">Wiki</a></li> |
68 | | <li class="active"><a href="/trac/">Development</a></li> |
69 | | </div> |
70 | | |
71 | | <!-- embbed the trac --> |
72 | | <div id="body"> |
73 | | <div id="x-trac"> |
74 | | <div class="sidebar"> |
75 | | <!-- combine all three navigation bars into one --> |
76 | | <ul class="navigation"> |
77 | | <!-- include main navigation --> |
78 | | ${select('ul[@id="mainnav"]/*')} |
79 | | <!-- include meta nav --> |
80 | | ${select('ul[@id="metanav"]/*')} |
81 | | <!-- include ctx nav --> |
82 | | ${select('ul[@id="ctxtnav"]/*')} |
83 | | </ul> |
84 | | <li>Search |
85 | | ${select('div[@id="banner"]/form[@id="search"]')} |
86 | | </li> |
87 | | </ul> |
88 | | <!-- search box --> |
89 | | ${select('form[@id="search"]')} |
| 204 | <div id="x-trac"> |
| 205 | <div id="banner"> |
| 206 | <div id="header" py:choose=""> |
| 207 | <a py:when="chrome.logo.src" id="logo" href="${chrome.logo.link}"><img |
| 208 | src="${chrome.logo.src}" alt="${chrome.logo.alt}" /></a> |
| 209 | <h1 py:otherwise=""><a href="${chrome.logo.link}">${project.name}</a></h1> |