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 |