OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Simple Markdown browser for a Git checkout.""" | 6 """Simple Markdown browser for a Git checkout.""" |
7 from __future__ import print_function | 7 from __future__ import print_function |
8 | 8 |
9 import SimpleHTTPServer | 9 import SimpleHTTPServer |
10 import SocketServer | 10 import SocketServer |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 self._DoUnknown() | 132 self._DoUnknown() |
133 elif path == '/doc.css': | 133 elif path == '/doc.css': |
134 self._DoCSS('doc.css') | 134 self._DoCSS('doc.css') |
135 elif not os.path.exists(full_path): | 135 elif not os.path.exists(full_path): |
136 self._DoNotFound() | 136 self._DoNotFound() |
137 elif path.lower().endswith('.md'): | 137 elif path.lower().endswith('.md'): |
138 self._DoMD(path) | 138 self._DoMD(path) |
139 elif os.path.exists(full_path + '/README.md'): | 139 elif os.path.exists(full_path + '/README.md'): |
140 self._DoMD(path + '/README.md') | 140 self._DoMD(path + '/README.md') |
141 else: | 141 else: |
142 self._DoUnknown() | 142 self._DoDirListing(full_path) |
143 | 143 |
144 def _DoMD(self, path): | 144 def _DoMD(self, path): |
145 extensions = [ | 145 extensions = [ |
146 'markdown.extensions.def_list', | 146 'markdown.extensions.def_list', |
147 'markdown.extensions.fenced_code', | 147 'markdown.extensions.fenced_code', |
148 'markdown.extensions.tables', | 148 'markdown.extensions.tables', |
149 'markdown.extensions.toc', | 149 'markdown.extensions.toc', |
150 'gitiles_ext_blocks', | 150 'gitiles_ext_blocks', |
151 ] | 151 ] |
152 extension_configs = { | 152 extension_configs = { |
(...skipping 26 matching lines...) Expand all Loading... |
179 | 179 |
180 def _DoCSS(self, template): | 180 def _DoCSS(self, template): |
181 self._WriteHeader('text/css') | 181 self._WriteHeader('text/css') |
182 self._WriteTemplate(template) | 182 self._WriteTemplate(template) |
183 | 183 |
184 def _DoNotFound(self): | 184 def _DoNotFound(self): |
185 self._WriteHeader('text/html', status_code=404) | 185 self._WriteHeader('text/html', status_code=404) |
186 self.wfile.write('<html><body>%s not found</body></html>' % self.path) | 186 self.wfile.write('<html><body>%s not found</body></html>' % self.path) |
187 | 187 |
188 def _DoUnknown(self): | 188 def _DoUnknown(self): |
189 self._WriteHeader('text/html') | 189 self._WriteHeader('text/html', status_code=501) |
190 self.wfile.write('<html><body>I do not know how to serve %s.</body>' | 190 self.wfile.write('<html><body>I do not know how to serve %s.</body>' |
191 '</html>' % self.path) | 191 '</html>' % self.path) |
192 | 192 |
| 193 def _DoDirListing(self, full_path): |
| 194 self._WriteHeader('text/html') |
| 195 self._WriteTemplate('header.html') |
| 196 |
| 197 self.wfile.write('<div class="Breadcrumbs">\n') |
| 198 self.wfile.write('<a class="Breadcrumbs-crumb">%s</a>\n' % self.path) |
| 199 self.wfile.write('</div>\n') |
| 200 |
| 201 for _, dirs, files in os.walk(full_path): |
| 202 for f in sorted(files): |
| 203 if f.startswith('.'): |
| 204 continue |
| 205 if f.endswith('.md'): |
| 206 bold = ('<b>', '</b>') |
| 207 else: |
| 208 bold = ('', '') |
| 209 self.wfile.write('<a href="%s/%s">%s%s%s</a><br/>\n' % |
| 210 (self.path.rstrip('/'), f, bold[0], f, bold[1])) |
| 211 |
| 212 self.wfile.write('<br/>\n') |
| 213 |
| 214 for d in sorted(dirs): |
| 215 if d.startswith('.'): |
| 216 continue |
| 217 self.wfile.write('<a href="%s/%s">%s/</a><br/>\n' % |
| 218 (self.path.rstrip('/'), d, d)) |
| 219 |
| 220 break |
| 221 |
| 222 self._WriteTemplate('footer.html') |
| 223 |
193 def _Read(self, relpath, relative_to=None): | 224 def _Read(self, relpath, relative_to=None): |
194 if relative_to is None: | 225 if relative_to is None: |
195 relative_to = self.server.top_level | 226 relative_to = self.server.top_level |
196 assert not relpath.startswith(os.sep) | 227 assert not relpath.startswith(os.sep) |
197 path = os.path.join(relative_to, relpath) | 228 path = os.path.join(relative_to, relpath) |
198 with codecs.open(path, encoding='utf-8') as fp: | 229 with codecs.open(path, encoding='utf-8') as fp: |
199 return fp.read() | 230 return fp.read() |
200 | 231 |
201 def _WriteHeader(self, content_type='text/plain', status_code=200): | 232 def _WriteHeader(self, content_type='text/plain', status_code=200): |
202 self.send_response(status_code) | 233 self.send_response(status_code) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 contents.text = 'Contents' | 294 contents.text = 'Contents' |
264 contents.tail = '\n' | 295 contents.tail = '\n' |
265 toc_aux = ElementTree.SubElement(toc_node, 'div', {'class': 'toc-aux'}) | 296 toc_aux = ElementTree.SubElement(toc_node, 'div', {'class': 'toc-aux'}) |
266 toc_aux.text = '\n' | 297 toc_aux.text = '\n' |
267 toc_aux.append(ul_with_the_desired_toc_entries) | 298 toc_aux.append(ul_with_the_desired_toc_entries) |
268 toc_aux.tail = '\n' | 299 toc_aux.tail = '\n' |
269 | 300 |
270 | 301 |
271 if __name__ == '__main__': | 302 if __name__ == '__main__': |
272 sys.exit(main(sys.argv[1:])) | 303 sys.exit(main(sys.argv[1:])) |
OLD | NEW |