Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: tools/md_browser/md_browser.py

Issue 1356203004: Check in a simple pure-python based Markdown previewer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@add
Patch Set: patch for review Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« tools/md_browser/README.md ('K') | « tools/md_browser/header.html ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/md_browser/md_browser.py
diff --git a/tools/md_browser/md_browser.py b/tools/md_browser/md_browser.py
new file mode 100644
index 0000000000000000000000000000000000000000..58571f0ef75cd39f92561c9202b0e6c8070f6cb3
--- /dev/null
+++ b/tools/md_browser/md_browser.py
@@ -0,0 +1,101 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Simple Markdown browser for a Git checkout."""
+
+import SimpleHTTPServer
+import SocketServer
+import argparse
+import codecs
+import os
+import socket
+import sys
+
+
+SRC_DIR = os.path.dirname(os.path.dirname(
+ os.path.dirname(os.path.abspath(__file__))))
+sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown'))
+import markdown
+
+
+def main(argv):
+ parser = argparse.ArgumentParser(prog='md_browser')
scottmg 2015/09/22 04:58:01 +4 like an animal! :)
Dirk Pranke 2015/09/22 21:16:27 will fix. stupid chromium coding standards :).
+ parser.add_argument('-p', '--port', type=int, default=8080,
+ help='port to run on (default = %(default)s)')
+ args = parser.parse_args(argv)
+
+ try:
+ s = Server(args.port, SRC_DIR)
+ s.serve_forever()
+ s.shutdown()
+ return 0
+ except KeyboardInterrupt:
+ return 130
+
+
+class Server(SocketServer.TCPServer):
+ def __init__(self, port, top_level):
+ SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler)
+ self.port = port
+ self.top_level = top_level
+
+ def server_bind(self):
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.socket.bind(self.server_address)
+
+
+class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+ def do_GET(self):
+ full_path = os.path.abspath(os.path.join(self.server.top_level,
+ self.path[1:]))
scottmg 2015/09/22 04:58:01 I guess it doesn't matter for this usage, but you
nodir 2015/09/22 16:38:18 os.path.abspath returns a normalized path, so the
scottmg 2015/09/22 17:32:46 (I meant that by entering localhost:8080/../../../
Dirk Pranke 2015/09/22 21:16:27 Right, but Nodir's saying (correctly, I believe) t
scottmg 2015/09/22 21:26:39 Oh, you're right. Sorry.
+ if not full_path.startswith(self.server.top_level):
+ self._do_unknown()
+ elif self.path == '/doc.css':
+ self._write_file('doc.css')
+ elif not os.path.exists(full_path):
+ self._do_not_found()
+ elif self.path.endswith('.md'):
nodir 2015/09/22 16:38:18 self.path.lower()... JIC
Dirk Pranke 2015/09/22 21:16:27 Done, though I worry about what other sorts of wei
+ self._do_md()
+ else:
+ self._do_unknown()
+
+ def _do_md(self):
+ extensions = [
+ 'markdown.extensions.fenced_code',
+ 'markdown.extensions.tables',
+ 'markdown.extensions.toc',
+ ]
+
+ contents = self._read(self.path[1:])
scottmg 2015/09/22 04:58:01 it seems like this is already stripping the leadin
Dirk Pranke 2015/09/22 21:16:27 Made things more consistent.
+ md_fragment = markdown.markdown(contents,
+ extensions=extensions,
+ output_format='html4').encode('utf-8')
+ try:
+ self._write_file('header.html')
+ self.wfile.write(md_fragment)
+ self._write_file('footer.html')
+ except:
+ raise
+
+ def _do_not_found(self):
+ self.wfile.write('<html><body>%s not found</body></html>' % self.path)
+
+ def _do_unknown(self):
+ self.wfile.write('<html><body>I do not know how to serve %s.</body>'
+ '</html>' % self.path)
+
+ def _read(self, path):
+ if not path.startswith('/'):
nodir 2015/09/22 16:38:18 this if is unnecessary: os.path.join('/foo', '/bar
Dirk Pranke 2015/09/22 21:16:27 true, but the code was confusing regardless. Made
+ path = os.path.join(self.server.top_level, path)
+ return codecs.open(path, mode='r', encoding='utf-8').read()
nodir 2015/09/22 16:38:18 mode='r' is unnecessary, it is default
nodir 2015/09/22 16:38:18 This seems to leave the fd open? Shouldn't you wi
Dirk Pranke 2015/09/22 21:16:27 Done, and good catch on the fd.
+
+ def _write_file(self, path):
+ assert os.sep not in path
+ contents = self._read(os.path.join(SRC_DIR, 'tools', 'md_browser',
nodir 2015/09/22 16:38:18 nit: I think moving the line break to the position
Dirk Pranke 2015/09/22 21:16:27 Once I switch to 2-space indents the whole thing f
+ path))
+ self.wfile.write(contents.encode('utf-8'))
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
« tools/md_browser/README.md ('K') | « tools/md_browser/header.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698