| 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 |
| 18 import time |
| 19 import webbrowser |
| 17 | 20 |
| 18 | 21 |
| 19 THIS_DIR = os.path.abspath(os.path.dirname(__file__)) | 22 THIS_DIR = os.path.abspath(os.path.dirname(__file__)) |
| 20 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) | 23 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) |
| 21 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')) |
| 22 import markdown | 25 import markdown |
| 23 | 26 |
| 24 | 27 |
| 25 def main(argv): | 28 def main(argv): |
| 26 parser = argparse.ArgumentParser(prog='md_browser') | 29 parser = argparse.ArgumentParser(prog='md_browser') |
| 27 parser.add_argument('-p', '--port', type=int, default=8080, | 30 parser.add_argument('-p', '--port', type=int, default=8080, |
| 28 help='port to run on (default = %(default)s)') | 31 help='port to run on (default = %(default)s)') |
| 29 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='?', |
| 34 help='open file in browser') |
| 30 args = parser.parse_args(argv) | 35 args = parser.parse_args(argv) |
| 31 | 36 |
| 37 top_level = os.path.abspath(args.directory) |
| 38 |
| 39 s = Server(args.port, top_level) |
| 40 |
| 41 print('Listening on http://localhost:%s/' % args.port) |
| 42 thread = None |
| 43 if args.file: |
| 44 path = os.path.abspath(args.file) |
| 45 if not path.startswith(top_level): |
| 46 print('%s is not under %s' % (args.file, args.directory)) |
| 47 return 1 |
| 48 rpath = os.path.relpath(path, top_level) |
| 49 url = 'http://localhost:%d/%s' % (args.port, rpath) |
| 50 print('Opening %s' % url) |
| 51 thread = threading.Thread(target=_open_url, args=(url,)) |
| 52 thread.start() |
| 53 |
| 54 elif os.path.isfile(os.path.join(top_level, 'docs', 'README.md')): |
| 55 print(' Try loading http://localhost:%d/docs/README.md' % args.port) |
| 56 elif os.path.isfile(os.path.join(args.directory, 'README.md')): |
| 57 print(' Try loading http://localhost:%d/README.md' % args.port) |
| 58 |
| 59 retcode = 1 |
| 32 try: | 60 try: |
| 33 s = Server(args.port, args.directory) | |
| 34 print("Listening on http://localhost:%s/" % args.port) | |
| 35 if os.path.isfile(os.path.join(args.directory, 'docs', 'README.md')): | |
| 36 print(" Try loading http://localhost:%s/docs/README.md" % args.port) | |
| 37 elif os.path.isfile(os.path.join(args.directory, 'README.md')): | |
| 38 print(" Try loading http://localhost:%s/README.md" % args.port) | |
| 39 s.serve_forever() | 61 s.serve_forever() |
| 40 s.shutdown() | |
| 41 return 0 | |
| 42 except KeyboardInterrupt: | 62 except KeyboardInterrupt: |
| 43 return 130 | 63 retcode = 130 |
| 64 except Exception as e: |
| 65 print('Exception raised: %s' % str(e)) |
| 66 |
| 67 s.shutdown() |
| 68 if thread: |
| 69 thread.join() |
| 70 return retcode |
| 71 |
| 72 |
| 73 def _open_url(url): |
| 74 time.sleep(1) |
| 75 webbrowser.open(url) |
| 44 | 76 |
| 45 | 77 |
| 46 def _gitiles_slugify(value, _separator): | 78 def _gitiles_slugify(value, _separator): |
| 47 """Convert a string (representing a section title) to URL anchor name. | 79 """Convert a string (representing a section title) to URL anchor name. |
| 48 | 80 |
| 49 This function is passed to "toc" extension as an extension option, so we | 81 This function is passed to "toc" extension as an extension option, so we |
| 50 can emulate the way how Gitiles converts header titles to URL anchors. | 82 can emulate the way how Gitiles converts header titles to URL anchors. |
| 51 | 83 |
| 52 Gitiles' official documentation about the conversion is at: | 84 Gitiles' official documentation about the conversion is at: |
| 53 | 85 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 70 value = value.replace(u' ', u'-') | 102 value = value.replace(u' ', u'-') |
| 71 value = re.sub(r'([-_])[-_]+', r'\1', value) # Fold hyphens and underscores. | 103 value = re.sub(r'([-_])[-_]+', r'\1', value) # Fold hyphens and underscores. |
| 72 return value | 104 return value |
| 73 | 105 |
| 74 | 106 |
| 75 class Server(SocketServer.TCPServer): | 107 class Server(SocketServer.TCPServer): |
| 76 def __init__(self, port, top_level): | 108 def __init__(self, port, top_level): |
| 77 SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler) | 109 SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler) |
| 78 self.port = port | 110 self.port = port |
| 79 self.top_level = os.path.abspath(top_level) | 111 self.top_level = os.path.abspath(top_level) |
| 112 self.retcode = None |
| 80 | 113 |
| 81 def server_bind(self): | 114 def server_bind(self): |
| 82 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | 115 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| 83 self.socket.bind(self.server_address) | 116 self.socket.bind(self.server_address) |
| 84 | 117 |
| 85 | 118 |
| 86 class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): | 119 class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): |
| 87 def do_GET(self): | 120 def do_GET(self): |
| 88 path = self.path | 121 path = self.path |
| 89 | 122 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 self.end_headers() | 194 self.end_headers() |
| 162 | 195 |
| 163 def _WriteTemplate(self, template): | 196 def _WriteTemplate(self, template): |
| 164 contents = self._Read(os.path.join('tools', 'md_browser', template), | 197 contents = self._Read(os.path.join('tools', 'md_browser', template), |
| 165 relative_to=SRC_DIR) | 198 relative_to=SRC_DIR) |
| 166 self.wfile.write(contents.encode('utf-8')) | 199 self.wfile.write(contents.encode('utf-8')) |
| 167 | 200 |
| 168 | 201 |
| 169 if __name__ == '__main__': | 202 if __name__ == '__main__': |
| 170 sys.exit(main(sys.argv[1:])) | 203 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |