| 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 |