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