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 |
11 import argparse | 11 import argparse |
12 import codecs | 12 import codecs |
13 import os | 13 import os |
14 import re | 14 import re |
15 import socket | 15 import socket |
16 import sys | 16 import sys |
17 import threading | 17 import threading |
18 import time | 18 import time |
19 import webbrowser | 19 import webbrowser |
20 | 20 |
21 | 21 |
22 THIS_DIR = os.path.abspath(os.path.dirname(__file__)) | 22 THIS_DIR = os.path.realpath(os.path.dirname(__file__)) |
23 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) | 23 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) |
24 sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown')) | 24 sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown')) |
25 import markdown | 25 import markdown |
26 | 26 |
27 | 27 |
28 def main(argv): | 28 def main(argv): |
29 parser = argparse.ArgumentParser(prog='md_browser') | 29 parser = argparse.ArgumentParser(prog='md_browser') |
30 parser.add_argument('-p', '--port', type=int, default=8080, | 30 parser.add_argument('-p', '--port', type=int, default=8080, |
31 help='port to run on (default = %(default)s)') | 31 help='port to run on (default = %(default)s)') |
32 parser.add_argument('-d', '--directory', type=str, default=SRC_DIR) | 32 parser.add_argument('-d', '--directory', type=str, default=SRC_DIR) |
33 parser.add_argument('file', nargs='?', | 33 parser.add_argument('file', nargs='?', |
34 help='open file in browser') | 34 help='open file in browser') |
35 args = parser.parse_args(argv) | 35 args = parser.parse_args(argv) |
36 | 36 |
37 top_level = os.path.abspath(args.directory) | 37 top_level = os.path.realpath(args.directory) |
38 | 38 |
39 s = Server(args.port, top_level) | 39 s = Server(args.port, top_level) |
40 | 40 |
41 print('Listening on http://localhost:%s/' % args.port) | 41 print('Listening on http://localhost:%s/' % args.port) |
42 thread = None | 42 thread = None |
43 if args.file: | 43 if args.file: |
44 path = os.path.abspath(args.file) | 44 path = os.path.realpath(args.file) |
45 if not path.startswith(top_level): | 45 if not path.startswith(top_level): |
46 print('%s is not under %s' % (args.file, args.directory)) | 46 print('%s is not under %s' % (args.file, args.directory)) |
47 return 1 | 47 return 1 |
48 rpath = os.path.relpath(path, top_level) | 48 rpath = os.path.relpath(path, top_level) |
49 url = 'http://localhost:%d/%s' % (args.port, rpath) | 49 url = 'http://localhost:%d/%s' % (args.port, rpath) |
50 print('Opening %s' % url) | 50 print('Opening %s' % url) |
51 thread = threading.Thread(target=_open_url, args=(url,)) | 51 thread = threading.Thread(target=_open_url, args=(url,)) |
52 thread.start() | 52 thread.start() |
53 | 53 |
54 elif os.path.isfile(os.path.join(top_level, 'docs', 'README.md')): | 54 elif os.path.isfile(os.path.join(top_level, 'docs', 'README.md')): |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 value = re.sub(r'[^- a-zA-Z0-9]', '_', value) # Non-alphanumerics to '_'. | 101 value = re.sub(r'[^- a-zA-Z0-9]', '_', value) # Non-alphanumerics to '_'. |
102 value = value.replace(u' ', u'-') | 102 value = value.replace(u' ', u'-') |
103 value = re.sub(r'([-_])[-_]+', r'\1', value) # Fold hyphens and underscores. | 103 value = re.sub(r'([-_])[-_]+', r'\1', value) # Fold hyphens and underscores. |
104 return value | 104 return value |
105 | 105 |
106 | 106 |
107 class Server(SocketServer.TCPServer): | 107 class Server(SocketServer.TCPServer): |
108 def __init__(self, port, top_level): | 108 def __init__(self, port, top_level): |
109 SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler) | 109 SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler) |
110 self.port = port | 110 self.port = port |
111 self.top_level = os.path.abspath(top_level) | 111 self.top_level = top_level |
112 self.retcode = None | 112 self.retcode = None |
113 | 113 |
114 def server_bind(self): | 114 def server_bind(self): |
115 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | 115 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
116 self.socket.bind(self.server_address) | 116 self.socket.bind(self.server_address) |
117 | 117 |
118 | 118 |
119 class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): | 119 class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): |
120 def do_GET(self): | 120 def do_GET(self): |
121 path = self.path | 121 path = self.path |
122 | 122 |
123 # strip off the repo and branch info, if present, for compatibility | 123 # strip off the repo and branch info, if present, for compatibility |
124 # with gitiles. | 124 # with gitiles. |
125 if path.startswith('/chromium/src/+/master'): | 125 if path.startswith('/chromium/src/+/master'): |
126 path = path[len('/chromium/src/+/master'):] | 126 path = path[len('/chromium/src/+/master'):] |
127 | 127 |
128 full_path = os.path.abspath(os.path.join(self.server.top_level, path[1:])) | 128 full_path = os.path.realpath(os.path.join(self.server.top_level, path[1:])) |
129 | 129 |
130 if not full_path.startswith(self.server.top_level): | 130 if not full_path.startswith(self.server.top_level): |
131 self._DoUnknown() | 131 self._DoUnknown() |
132 elif path == '/doc.css': | 132 elif path == '/doc.css': |
133 self._DoCSS('doc.css') | 133 self._DoCSS('doc.css') |
134 elif not os.path.exists(full_path): | 134 elif not os.path.exists(full_path): |
135 self._DoNotFound() | 135 self._DoNotFound() |
136 elif path.lower().endswith('.md'): | 136 elif path.lower().endswith('.md'): |
137 self._DoMD(path) | 137 self._DoMD(path) |
138 elif os.path.exists(full_path + '/README.md'): | 138 elif os.path.exists(full_path + '/README.md'): |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 self.end_headers() | 194 self.end_headers() |
195 | 195 |
196 def _WriteTemplate(self, template): | 196 def _WriteTemplate(self, template): |
197 contents = self._Read(os.path.join('tools', 'md_browser', template), | 197 contents = self._Read(os.path.join('tools', 'md_browser', template), |
198 relative_to=SRC_DIR) | 198 relative_to=SRC_DIR) |
199 self.wfile.write(contents.encode('utf-8')) | 199 self.wfile.write(contents.encode('utf-8')) |
200 | 200 |
201 | 201 |
202 if __name__ == '__main__': | 202 if __name__ == '__main__': |
203 sys.exit(main(sys.argv[1:])) | 203 sys.exit(main(sys.argv[1:])) |
OLD | NEW |