Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Simple Markdown browser for a Git checkout.""" | 5 """Simple Markdown browser for a Git checkout.""" |
| 6 from __future__ import print_function | 6 from __future__ import print_function |
| 7 | 7 |
| 8 import SimpleHTTPServer | 8 import SimpleHTTPServer |
| 9 import SocketServer | 9 import SocketServer |
| 10 import argparse | 10 import argparse |
| 11 import codecs | 11 import codecs |
| 12 import os | 12 import os |
| 13 import re | 13 import re |
| 14 import socket | 14 import socket |
| 15 import sys | 15 import sys |
| 16 | 16 |
| 17 | 17 |
| 18 THIS_DIR = os.path.abspath(os.path.dirname(__file__)) | 18 THIS_DIR = os.path.abspath(os.path.dirname(__file__)) |
| 19 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) | 19 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) |
| 20 sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown')) | 20 sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown')) |
| 21 import markdown | 21 import markdown |
| 22 | 22 |
| 23 | 23 |
| 24 def main(argv): | 24 def main(argv): |
| 25 parser = argparse.ArgumentParser(prog='md_browser') | 25 parser = argparse.ArgumentParser(prog='md_browser') |
| 26 parser.add_argument('-p', '--port', type=int, default=8080, | 26 parser.add_argument('-p', '--port', type=int, default=8080, |
| 27 help='port to run on (default = %(default)s)') | 27 help='port to run on (default = %(default)s)') |
| 28 parser.add_argument('-d', '--directory', type=str, default=SRC_DIR) | |
| 28 args = parser.parse_args(argv) | 29 args = parser.parse_args(argv) |
| 29 | 30 |
| 30 try: | 31 try: |
| 31 s = Server(args.port, SRC_DIR) | 32 s = Server(args.port, args.directory) |
| 32 print("Listening on http://localhost:%s/" % args.port) | 33 print("Listening on http://localhost:%s/" % args.port) |
| 33 print(" Try loading http://localhost:%s/docs/README.md" % args.port) | 34 print(" Try loading http://localhost:%s/docs/README.md" % args.port) |
|
Dirk Pranke
2016/05/06 01:23:41
Does it still make sense to execute line 34 if arg
agable
2016/05/09 21:00:00
Good point, put in something smarter.
| |
| 34 s.serve_forever() | 35 s.serve_forever() |
| 35 s.shutdown() | 36 s.shutdown() |
| 36 return 0 | 37 return 0 |
| 37 except KeyboardInterrupt: | 38 except KeyboardInterrupt: |
| 38 return 130 | 39 return 130 |
| 39 | 40 |
| 40 | 41 |
| 41 def _gitiles_slugify(value, _separator): | 42 def _gitiles_slugify(value, _separator): |
| 42 """Convert a string (representing a section title) to URL anchor name. | 43 """Convert a string (representing a section title) to URL anchor name. |
| 43 | 44 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 def do_GET(self): | 83 def do_GET(self): |
| 83 path = self.path | 84 path = self.path |
| 84 | 85 |
| 85 # strip off the repo and branch info, if present, for compatibility | 86 # strip off the repo and branch info, if present, for compatibility |
| 86 # with gitiles. | 87 # with gitiles. |
| 87 if path.startswith('/chromium/src/+/master'): | 88 if path.startswith('/chromium/src/+/master'): |
| 88 path = path[len('/chromium/src/+/master'):] | 89 path = path[len('/chromium/src/+/master'):] |
| 89 | 90 |
| 90 full_path = os.path.abspath(os.path.join(self.server.top_level, path[1:])) | 91 full_path = os.path.abspath(os.path.join(self.server.top_level, path[1:])) |
| 91 | 92 |
| 92 if not full_path.startswith(SRC_DIR): | 93 if not full_path.startswith(self.server.top_level): |
|
Dirk Pranke
2016/05/06 01:23:41
self.server.top_level isn't guaranteed to be an ab
agable
2016/05/09 21:00:00
Fixed, it becomes an abspath at Server.__init__ ti
| |
| 93 self._DoUnknown() | 94 self._DoUnknown() |
| 94 elif path == '/doc.css': | 95 elif path == '/doc.css': |
| 95 self._DoCSS('doc.css') | 96 self._DoCSS('doc.css') |
| 96 elif not os.path.exists(full_path): | 97 elif not os.path.exists(full_path): |
| 97 self._DoNotFound() | 98 self._DoNotFound() |
| 98 elif path.lower().endswith('.md'): | 99 elif path.lower().endswith('.md'): |
| 99 self._DoMD(path) | 100 self._DoMD(path) |
| 100 elif os.path.exists(full_path + '/README.md'): | 101 elif os.path.exists(full_path + '/README.md'): |
| 101 self._DoMD(path + '/README.md') | 102 self._DoMD(path + '/README.md') |
| 102 else: | 103 else: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 | 136 |
| 136 def _DoNotFound(self): | 137 def _DoNotFound(self): |
| 137 self._WriteHeader('text/html') | 138 self._WriteHeader('text/html') |
| 138 self.wfile.write('<html><body>%s not found</body></html>' % self.path) | 139 self.wfile.write('<html><body>%s not found</body></html>' % self.path) |
| 139 | 140 |
| 140 def _DoUnknown(self): | 141 def _DoUnknown(self): |
| 141 self._WriteHeader('text/html') | 142 self._WriteHeader('text/html') |
| 142 self.wfile.write('<html><body>I do not know how to serve %s.</body>' | 143 self.wfile.write('<html><body>I do not know how to serve %s.</body>' |
| 143 '</html>' % self.path) | 144 '</html>' % self.path) |
| 144 | 145 |
| 146 def _ReadBoilerplate(self, relpath): | |
|
Dirk Pranke
2016/05/06 01:23:41
maybe just change _Read to take a second, optional
agable
2016/05/09 21:00:00
Done.
| |
| 147 assert not relpath.startswith(os.sep) | |
| 148 path = os.path.join(SRC_DIR, relpath) | |
| 149 with codecs.open(path, encoding='utf-8') as fp: | |
| 150 return fp.read() | |
| 151 | |
| 145 def _Read(self, relpath): | 152 def _Read(self, relpath): |
| 146 assert not relpath.startswith(os.sep) | 153 assert not relpath.startswith(os.sep) |
| 147 path = os.path.join(self.server.top_level, relpath) | 154 path = os.path.join(self.server.top_level, relpath) |
| 148 with codecs.open(path, encoding='utf-8') as fp: | 155 with codecs.open(path, encoding='utf-8') as fp: |
| 149 return fp.read() | 156 return fp.read() |
| 150 | 157 |
| 151 def _WriteHeader(self, content_type='text/plain'): | 158 def _WriteHeader(self, content_type='text/plain'): |
| 152 self.send_response(200) | 159 self.send_response(200) |
| 153 self.send_header('Content-Type', content_type) | 160 self.send_header('Content-Type', content_type) |
| 154 self.end_headers() | 161 self.end_headers() |
| 155 | 162 |
| 156 def _WriteTemplate(self, template): | 163 def _WriteTemplate(self, template): |
| 157 contents = self._Read(os.path.join('tools', 'md_browser', template)) | 164 contents = self._ReadBoilerplate( |
| 165 os.path.join('tools', 'md_browser', template)) | |
| 158 self.wfile.write(contents.encode('utf-8')) | 166 self.wfile.write(contents.encode('utf-8')) |
| 159 | 167 |
| 160 | 168 |
| 161 if __name__ == '__main__': | 169 if __name__ == '__main__': |
| 162 sys.exit(main(sys.argv[1:])) | 170 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |