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

Side by Side Diff: tools/md_browser/md_browser.py

Issue 2482703002: Change [TOC] processing in MD browser to match gitiles (Closed)
Patch Set: reparent Created 4 years, 1 month 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 from xml.etree import ElementTree
20 21
21 22
22 THIS_DIR = os.path.realpath(os.path.dirname(__file__)) 23 THIS_DIR = os.path.realpath(os.path.dirname(__file__))
23 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR)) 24 SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR))
24 sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown')) 25 sys.path.insert(0, os.path.join(SRC_DIR, 'third_party', 'Python-Markdown'))
25 import markdown 26 import markdown
26 27
27 28
28 def main(argv): 29 def main(argv):
29 parser = argparse.ArgumentParser(prog='md_browser') 30 parser = argparse.ArgumentParser(prog='md_browser')
30 parser.add_argument('-p', '--port', type=int, default=8080, 31 parser.add_argument('-p', '--port', type=int, default=8080,
31 help='port to run on (default = %(default)s)') 32 help='port to run on (default = %(default)s)')
32 parser.add_argument('-d', '--directory', type=str, default=SRC_DIR) 33 parser.add_argument('-d', '--directory', type=str, default=SRC_DIR)
33 parser.add_argument('file', nargs='?', 34 parser.add_argument('file', nargs='?',
34 help='open file in browser') 35 help='open file in browser')
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 'markdown.extensions.toc', 149 'markdown.extensions.toc',
149 'gitiles_ext_blocks', 150 'gitiles_ext_blocks',
150 ] 151 ]
151 extension_configs = { 152 extension_configs = {
152 'markdown.extensions.toc': { 153 'markdown.extensions.toc': {
153 'slugify': _gitiles_slugify 154 'slugify': _gitiles_slugify
154 }, 155 },
155 } 156 }
156 157
157 contents = self._Read(path[1:]) 158 contents = self._Read(path[1:])
158 md_fragment = markdown.markdown(contents, 159
159 extensions=extensions, 160 md = markdown.Markdown(extensions=extensions,
160 extension_configs=extension_configs, 161 extension_configs=extension_configs,
161 output_format='html4').encode('utf-8') 162 output_format='html4')
163
164 has_a_single_h1 = (len([line for line in contents.splitlines()
165 if (line.startswith('#') and
166 not line.startswith('##'))]) == 1)
167
168 md.treeprocessors['adjust_toc'] = _AdjustTOC(has_a_single_h1)
169
170 md_fragment = md.convert(contents).encode('utf-8')
171
162 try: 172 try:
163 self._WriteHeader('text/html') 173 self._WriteHeader('text/html')
164 self._WriteTemplate('header.html') 174 self._WriteTemplate('header.html')
165 self.wfile.write(md_fragment) 175 self.wfile.write(md_fragment)
166 self._WriteTemplate('footer.html') 176 self._WriteTemplate('footer.html')
167 except: 177 except:
168 raise 178 raise
169 179
170 def _DoCSS(self, template): 180 def _DoCSS(self, template):
171 self._WriteHeader('text/css') 181 self._WriteHeader('text/css')
(...skipping 20 matching lines...) Expand all
192 self.send_response(200) 202 self.send_response(200)
193 self.send_header('Content-Type', content_type) 203 self.send_header('Content-Type', content_type)
194 self.end_headers() 204 self.end_headers()
195 205
196 def _WriteTemplate(self, template): 206 def _WriteTemplate(self, template):
197 contents = self._Read(os.path.join('tools', 'md_browser', template), 207 contents = self._Read(os.path.join('tools', 'md_browser', template),
198 relative_to=SRC_DIR) 208 relative_to=SRC_DIR)
199 self.wfile.write(contents.encode('utf-8')) 209 self.wfile.write(contents.encode('utf-8'))
200 210
201 211
212 class _AdjustTOC(markdown.treeprocessors.Treeprocessor):
213 def __init__(self, has_a_single_h1):
214 super(_AdjustTOC, self).__init__()
215 self.has_a_single_h1 = has_a_single_h1
216
217 def run(self, tree):
218 # The markdown.extensions.toc extension will replace
219 #
220 # # H1
221 #
222 # [TOC]
223 #
224 # ## first H2
225 #
226 # ## second H2
227 #
228 # with the following HTML:
229 #
230 # <div class='toc'>
231 # <ul><li><a>H1</a>
232 # <ul><li>first H2
233 # <li>second H2</li></ul></li><ul></div>
234 #
235 # We want to replace the first ul with the second one, and also patch
236 # in a new H2 header for the TOC itself, ending up with:
237 #
238 # <div class='toc'>
239 # <h2>Contents</h2>
240 # <div class='toc-aux'>
241 # <ul><li>first H2
242 # <li>second H2</li></ul></div></div>
243 #
244 # If the document has more than one H1, or no H1s at all, we leave
245 # the tree alone but still wrap it in a toc-aux div and add the
246 # Contents header.
247
248 toc_nodes = tree.findall(".//*[@class='toc']")
249 if not toc_nodes:
250 return
251
252 for toc_node in toc_nodes:
253 if self.has_a_single_h1:
254 toc_ul = toc_node[0]
255 toc_ul_li = toc_ul[0]
256 toc_ul_li_ul = toc_ul_li[1]
257 children = toc_ul_li_ul
258 del toc_node[0]
259 else:
260 children = list(toc_node)
jsbell 2016/11/08 17:29:12 I'm unfamiliar with ElementTree and the exact stru
Dirk Pranke 2016/11/08 21:55:07 Ah, good catch.
261 while len(toc_node):
262 del toc_node[0]
263
264 contents = ElementTree.SubElement(toc_node, 'h2')
265 contents.text = 'Contents'
266 contents.tail = '\n'
267 toc_aux = ElementTree.SubElement(toc_node, 'div',
268 attrib={'class': 'toc-aux'})
269 toc_aux.text = '\n'
270 toc_aux_ul = ElementTree.SubElement(toc_aux, 'ul')
271 toc_aux_ul.text = '\n'
272 toc_aux_ul.extend(children)
273 toc_aux_ul.tail = '\n'
274 toc_aux.tail = '\n'
275
276
202 if __name__ == '__main__': 277 if __name__ == '__main__':
203 sys.exit(main(sys.argv[1:])) 278 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698