Chromium Code Reviews| Index: tools/md_browser/gitiles_ext_blocks.py |
| diff --git a/tools/md_browser/gitiles_ext_blocks.py b/tools/md_browser/gitiles_ext_blocks.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c474ba99edd76df03ea8dc96cdf140a3d137dbbd |
| --- /dev/null |
| +++ b/tools/md_browser/gitiles_ext_blocks.py |
| @@ -0,0 +1,77 @@ |
| +# 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. |
| + |
| +"""Implements Gitiles' notification, aside and promotion blocks. |
| + |
| +This extention makes the Markdown parser recognize the Gitiles' extended |
| +blocks notation. The syntax is explained at: |
| + |
| +https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md#Notification_aside_promotion-blocks |
| +""" |
| + |
| + |
| +from markdown.blockprocessors import BlockProcessor |
| +from markdown.extensions import Extension |
| +from markdown.util import etree |
|
nodir
2015/10/20 14:53:39
there are style inconsistencies in this file, such
Dirk Pranke
2015/10/20 22:42:16
I'm fine w/ importing classes directly.
Yuta Kitamura
2015/10/21 04:36:48
Thanks, I dropped one blank line from the blanks a
|
| +import re |
| + |
| + |
| +class GitilesExtBlockProcessor(BlockProcessor): |
|
Dirk Pranke
2015/10/20 22:42:16
Nit: I'd name this _GitilesExtBlockProcessor, sinc
Yuta Kitamura
2015/10/21 04:36:48
Done.
|
| + """Process Gitiles' notification, aside and promotion blocks.""" |
| + |
| + RE_START = re.compile(r'^\*\*\* (note|aside|promo)\n') |
|
nodir
2015/10/20 14:53:39
there may be trailing space
Yuta Kitamura
2015/10/21 04:36:48
Done.
|
| + RE_END = re.compile(r'\n\*\*\*(?:\n|$)') |
|
nodir
2015/10/20 14:53:39
here too
Yuta Kitamura
2015/10/21 04:36:48
Done.
|
| + |
| + def __init__(self, *args, **kwargs): |
| + self.__last_parents = [] |
|
Dirk Pranke
2015/10/20 22:42:16
why is this a list? it seems like having nested bl
Yuta Kitamura
2015/10/21 04:36:48
My first assumption was that these blocks were nes
|
| + BlockProcessor.__init__(self, *args, **kwargs) |
|
Dirk Pranke
2015/10/20 22:42:16
Nit: I'd probably do super(GitilesExtBlockProcesso
Yuta Kitamura
2015/10/21 04:36:48
I first did it that way but that didn't work, beca
Dirk Pranke
2015/10/21 19:12:51
ok.
|
| + |
| + def test(self, parent, block): |
| + return self.RE_START.search(block) or self.RE_END.search(block) |
| + |
| + def run(self, parent, blocks): |
| + raw_block = blocks.pop(0) |
| + match_start = self.RE_START.search(raw_block) |
| + if match_start: |
| + # Opening a new block. |
| + rest = raw_block[match_start.end():] |
| + |
| + div = etree.SubElement(parent, 'div') |
| + # Setting the class name is sufficient, because doc.css already has |
| + # styles for these classes. |
| + div.set('class', match_start.group(1)) |
| + self.__last_parents.append(parent) |
| + blocks.insert(0, rest) |
| + self.parser.parseBlocks(div, blocks) |
| + return |
| + |
| + match_end = self.RE_END.search(raw_block) |
| + if match_end: |
| + # Ending an existing block. |
| + |
| + # Process the text preceding the ending marker in the current context |
| + # (i.e. within the div block). |
| + rest = raw_block[:match_end.start()] |
| + self.parser.parseBlocks(parent, [rest]) |
| + |
| + if not self.__last_parents: |
| + # Inconsistent state (the ending marker is found but there is no |
| + # matching starting marker). |
| + # Let's continue as if we did not see the ending marker. |
| + return |
| + |
| + self.parser.parseBlocks(self.__last_parents.pop(), blocks) |
| + return |
| + |
| + |
| +class GitilesExtBlockExtension(Extension): |
| + """Add Gitiles' extended blocks to Markdown.""" |
| + def extendMarkdown(self, md, md_globals): |
| + md.parser.blockprocessors.add('gitilesextblocks', |
| + GitilesExtBlockProcessor(md.parser), |
| + '_begin') |
| + |
| + |
| +def makeExtension(*args, **kwargs): |
| + return GitilesExtBlockExtension(*args, **kwargs) |