Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """Implements Gitiles' notification, aside and promotion blocks. | |
| 6 | |
| 7 This extention makes the Markdown parser recognize the Gitiles' extended | |
| 8 blocks notation. The syntax is explained at: | |
| 9 | |
| 10 https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md#Notif ication_aside_promotion-blocks | |
| 11 """ | |
| 12 | |
| 13 | |
| 14 from markdown.blockprocessors import BlockProcessor | |
| 15 from markdown.extensions import Extension | |
| 16 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
| |
| 17 import re | |
| 18 | |
| 19 | |
| 20 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.
| |
| 21 """Process Gitiles' notification, aside and promotion blocks.""" | |
| 22 | |
| 23 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.
| |
| 24 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.
| |
| 25 | |
| 26 def __init__(self, *args, **kwargs): | |
| 27 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
| |
| 28 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.
| |
| 29 | |
| 30 def test(self, parent, block): | |
| 31 return self.RE_START.search(block) or self.RE_END.search(block) | |
| 32 | |
| 33 def run(self, parent, blocks): | |
| 34 raw_block = blocks.pop(0) | |
| 35 match_start = self.RE_START.search(raw_block) | |
| 36 if match_start: | |
| 37 # Opening a new block. | |
| 38 rest = raw_block[match_start.end():] | |
| 39 | |
| 40 div = etree.SubElement(parent, 'div') | |
| 41 # Setting the class name is sufficient, because doc.css already has | |
| 42 # styles for these classes. | |
| 43 div.set('class', match_start.group(1)) | |
| 44 self.__last_parents.append(parent) | |
| 45 blocks.insert(0, rest) | |
| 46 self.parser.parseBlocks(div, blocks) | |
| 47 return | |
| 48 | |
| 49 match_end = self.RE_END.search(raw_block) | |
| 50 if match_end: | |
| 51 # Ending an existing block. | |
| 52 | |
| 53 # Process the text preceding the ending marker in the current context | |
| 54 # (i.e. within the div block). | |
| 55 rest = raw_block[:match_end.start()] | |
| 56 self.parser.parseBlocks(parent, [rest]) | |
| 57 | |
| 58 if not self.__last_parents: | |
| 59 # Inconsistent state (the ending marker is found but there is no | |
| 60 # matching starting marker). | |
| 61 # Let's continue as if we did not see the ending marker. | |
| 62 return | |
| 63 | |
| 64 self.parser.parseBlocks(self.__last_parents.pop(), blocks) | |
| 65 return | |
| 66 | |
| 67 | |
| 68 class GitilesExtBlockExtension(Extension): | |
| 69 """Add Gitiles' extended blocks to Markdown.""" | |
| 70 def extendMarkdown(self, md, md_globals): | |
| 71 md.parser.blockprocessors.add('gitilesextblocks', | |
| 72 GitilesExtBlockProcessor(md.parser), | |
| 73 '_begin') | |
| 74 | |
| 75 | |
| 76 def makeExtension(*args, **kwargs): | |
| 77 return GitilesExtBlockExtension(*args, **kwargs) | |
| OLD | NEW |