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 |