70 | | - theme.html (as this is our default theme page) |
71 | | |
72 | | In more details, this is what happens with |
73 | | [source:tags/trac-1.0.9/trac/search/templates/search.html search.html]: |
74 | | - it starts by including the layout.html page: |
75 | | {{{#!xml |
76 | | <xi:include href="layout.html" /> |
77 | | }}} |
78 | | - the [source:tags/trac-1.0.9/trac/templates/layout.html layout.html] page: |
79 | | - defines `<py:match>` filters for transforming the content provided |
80 | | in `<head>` and `<body>` elements |
81 | | - then **dynamically** includes some "theme" page: |
82 | | {{{#!xml |
83 | | <xi:include href="$chrome.theme"><xi:fallback /></xi:include> |
84 | | }}} |
85 | | - by default, this will be our |
86 | | [source:tags/trac-1.0.9/trac/templates/theme.html theme.html]: |
87 | | - it defines a `<py:match>` filter on the `<body>` tag |
88 | | (the one that will be produced by the previously applied filters, |
89 | | i.e. the output of the `<py:match>` from the layout.html) |
90 | | and it will **embed** that element into some predefined HTML |
91 | | structure (inside a div element), and |
92 | | it will prepend and append other divs around it: |
93 | | {{{#!xml |
94 | | <body> |
95 | | <div id="banner"> |
96 | | ... |
97 | | </div> |
98 | | <div id="main"> |
99 | | ... |
100 | | (here goes the content of the <body></body> produced by layout.html) |
101 | | </div> |
102 | | <div id="footer"> |
103 | | ... |
104 | | </div> |
105 | | </body> |
106 | | }}} |
107 | | - the search.html page then provide the `<head>` and `<body>` elements |
108 | | specific to that search page; these elements will be processed by the |
109 | | `<py:match>`es filters defined so far in the order in which |
110 | | they have been included (so first the ones defined in layout.html, |
111 | | then the one for the `body` defined in theme.html) |
112 | | |
113 | | The scheme can be extended with more intermediate levels, |
114 | | for example what we have for the admin panels, e.g the |
115 | | [source:tags/trac-1.0.9/trac/admin/templates/admin_basics.html admin_basics.html] panel: |
116 | | - it starts by including the admin.html page: |
117 | | {{{#!xml |
118 | | <xi:include href="admin.html" /> |
119 | | }}} |
120 | | - the [source:tags/trac-1.0.9/trac/admin/templates/admin.html admin.html] page |
121 | | - defines `<py:match>` filters for `<head>` and `<body>`, |
122 | | which in turn will produce modified `<head>` and `<body>` elements |
123 | | - it then includes the layout.html page (see above) |
124 | | - then it provides the `<head>` and `<body>` elements specific to that panel |
125 | | (they will be process by the `<py:match>` filters in the order seen, so |
126 | | first those from admin.html, then those from layout.html and finally those |
127 | | from the dynamically included theme page |
| 70 | - $chrome.theme (typically "theme.html", the default theme page that ships with Trac) |
| 71 | |
| 72 | In more details, the |
| 73 | [source:tags/trac-1.0.9/trac/search/templates/search.html search.html] is structured like this: |
| 74 | {{{#!html+genshi |
| 75 | <html> |
| 76 | <xi:include href="layout.html" /> |
| 77 | <head> |
| 78 | <title>Search</title> |
| 79 | ... |
| 80 | </head> |
| 81 | <body> |
| 82 | <div id="content" class="search"> |
| 83 | <h1>Search</h1> |
| 84 | ... |
| 85 | </div> |
| 86 | </body> |
| 87 | </html> |
| 88 | }}} |
| 89 | - it starts by including the layout.html page (`<xi:include href="layout.html" />`) |
| 90 | - it then provides the `<head>` and `<body>` elements specific to that search page; |
| 91 | these elements will be processed by the `<py:match>`es filters defined so far, |
| 92 | in the order in which they have been included |
| 93 | |
| 94 | The [source:tags/trac-1.0.9/trac/templates/layout.html layout.html] |
| 95 | page in turn is structure like this: |
| 96 | {{{#!html+genshi |
| 97 | <html> |
| 98 | <py:match path="head"><head> |
| 99 | <title py:with="title = list(select('title/text()'))"> |
| 100 | ${title} – ${project.name or 'Trac'} <!-- e.g. "Search - Trac" --> |
| 101 | </title> |
| 102 | ... |
| 103 | ${select("*[local-name() != 'title']|text()|comment()")} |
| 104 | </head></py:match> |
| 105 | |
| 106 | <py:match path="body"><body> |
| 107 | |
| 108 | ${select('*|text()|comment()')} <!-- e.g. "<h1>Search</h1>" |
| 109 | ... --> |
| 110 | ... |
| 111 | <div id="altlinks" py:if="'alternate' in chrome.links"> |
| 112 | ... |
| 113 | </div> |
| 114 | </body></py:match> |
| 115 | |
| 116 | <xi:include href="$chrome.theme"><xi:fallback /></xi:include> |
| 117 | </html> |
| 118 | }}} |
| 119 | - it defines `<py:match>` filters for transforming the content provided |
| 120 | in `<head>` and `<body>` elements in the including template (search.html); |
| 121 | the head filter adds some content to the `<title>` and prepends some content |
| 122 | in the <head>, the body filter appends some content in the <body> |
| 123 | - it then **dynamically** includes some "theme" page, `$chrome.theme` |
| 124 | |
| 125 | By default, this theme page will be our |
| 126 | [source:tags/trac-1.0.9/trac/templates/theme.html theme.html] template: |
| 127 | {{{#!xml |
| 128 | <html> |
| 129 | <body> |
| 130 | <div id="banner"> |
| 131 | ... |
| 132 | </div> |
| 133 | <div id="main"> |
| 134 | ... |
| 135 | ${select('*|text()|comment()')} <!-- e.g. "<h1>Search</h1>" |
| 136 | ... |
| 137 | <div id="altlinks" ... </div> --> |
| 138 | </div> |
| 139 | <div id="footer"> |
| 140 | ... |
| 141 | </div> |
| 142 | </body> |
| 143 | </html> |
| 144 | }}} |
| 145 | - it defines a `<py:match>` filter on the `<body>` tag |
| 146 | (the one that will be produced by the previously applied filters, |
| 147 | i.e. the output of the `<py:match>` from the layout.html) |
| 148 | and it will **embed** that element into some predefined HTML |
| 149 | structure (inside a div element), and |
| 150 | it will prepend and append other divs around it: |
| 151 | |
| 152 | So this dynamic theme template has the last say, and can theoretically re-order |
| 153 | the content generated by the previous filters any way it likes, although in practice |
| 154 | it simply inserts the body content produced by previous steps inside a predefined |
| 155 | structure (the `<div id="main">`). |
| 156 | |
| 157 | An example of another theme page: [https://github.com/chevah/trac-bootstrap-theme/blob/master/templates/theme.html trac-bootstrap-theme's theme.html]. |
| 158 | |
| 159 | |
| 160 | |
| 161 | Note that this scheme can be extended to having more intermediate levels, |
| 162 | for example what we have for the admin panels. |
| 163 | |
| 164 | One such panel is |
| 165 | [source:tags/trac-1.0.9/trac/admin/templates/admin_basics.html admin_basics.html]: |
| 166 | {{{#!html+genshi |
| 167 | <html> |
| 168 | <xi:include href="admin.html" /> |
| 169 | <head> |
| 170 | <title>Basics</title> |
| 171 | </head> |
| 172 | |
| 173 | <body> |
| 174 | ... |
| 175 | </body> |
| 176 | </html> |
| 177 | }}} |
| 178 | - it starts by including the admin.html page |
| 179 | - then it provides the `<head>` and `<body>` elements specific to that panel |
| 180 | |
| 181 | The [source:tags/trac-1.0.9/trac/admin/templates/admin.html admin.html] page |
| 182 | is similar to the search.html page in that it includes the layout.html, but |
| 183 | it also first contains its own `<py:match>` templates to organize the content of |
| 184 | the admin panel which included it: |
| 185 | {{{#!html+genshi |
| 186 | <html> |
| 187 | <py:match path="head" once="true"><head> |
| 188 | <title>Administration: ${select('title/text()')}</title> |
| 189 | ${select("*[local-name() != 'title']")} |
| 190 | </head></py:match> |
| 191 | |
| 192 | <py:match path="body" once="true" buffer="false"><body> |
| 193 | <div id="content" class="admin"> |
| 194 | <h1>Administration</h1> |
| 195 | <div id="tabs"> |
| 196 | <div id="tabcontent"> |
| 197 | ${select("*|text()")} |
| 198 | <br style="clear: right" /> |
| 199 | </div> |
| 200 | </div> |
| 201 | |
| 202 | </body></py:match> |
| 203 | |
| 204 | <xi:include href="layout.html" /> |
| 205 | </html> |
| 206 | }}} |
| 207 | - defines `<py:match>` filters for `<head>` and `<body>` (of the including panel page), |
| 208 | which in turn will produce modified `<head>` and `<body>` elements |
| 209 | - it then includes the layout.html page (see above) |