| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
1 |
#!/usr/bin/env python |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
2 |
# reStructuredText (RST) to GitHub-flavored Markdown converter |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
3 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
4 |
import re, sys |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
5 |
from docutils import core, nodes, writers |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
6 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
7 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
8 |
def is_github_ref(node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
9 |
return re.match('https://github.com/.*/(issues|pull)/.*', node['refuri']) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
10 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
11 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
12 |
class Translator(nodes.NodeVisitor): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
13 |
def __init__(self, document): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
14 |
nodes.NodeVisitor.__init__(self, document) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
15 |
self.output = '' |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
16 |
self.indent = 0 |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
17 |
self.preserve_newlines = False |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
18 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
19 |
def write(self, text): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
20 |
self.output += text.replace('\n', '\n' + ' ' * self.indent) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
21 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
22 |
def visit_document(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
23 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
24 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
25 |
def depart_document(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
26 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
27 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
28 |
def visit_section(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
29 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
30 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
31 |
def depart_section(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
32 |
# Skip all sections except the first one. |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
33 |
raise nodes.StopTraversal |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
34 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
35 |
def visit_title(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
36 |
self.version = re.match(r'(\d+\.\d+\.\d+).*', node.children[0]).group(1) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
37 |
raise nodes.SkipChildren |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
38 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
39 |
def visit_title_reference(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
40 |
raise Exception(node) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
41 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
42 |
def depart_title(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
43 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
44 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
45 |
def visit_Text(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
46 |
if not self.preserve_newlines: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
47 |
node = node.replace('\n', ' ') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
48 |
self.write(node) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
49 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
50 |
def depart_Text(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
51 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
52 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
53 |
def visit_bullet_list(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
54 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
55 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
56 |
def depart_bullet_list(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
57 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
58 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
59 |
def visit_list_item(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
60 |
self.write('* ') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
61 |
self.indent += 2 |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
62 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
63 |
def depart_list_item(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
64 |
self.indent -= 2 |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
65 |
self.write('\n\n') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
66 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
67 |
def visit_paragraph(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
68 |
self.write('\n\n') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
69 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
70 |
def depart_paragraph(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
71 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
72 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
73 |
def visit_reference(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
74 |
if not is_github_ref(node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
75 |
self.write('[') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
76 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
77 |
def depart_reference(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
78 |
if not is_github_ref(node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
79 |
self.write('](' + node['refuri'] + ')') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
80 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
81 |
def visit_target(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
82 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
83 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
84 |
def depart_target(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
85 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
86 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
87 |
def visit_literal(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
88 |
self.write('`') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
89 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
90 |
def depart_literal(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
91 |
self.write('`') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
92 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
93 |
def visit_literal_block(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
94 |
self.write('\n\n```') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
95 |
if 'c++' in node['classes']: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
96 |
self.write('c++') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
97 |
self.write('\n') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
98 |
self.preserve_newlines = True |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
99 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
100 |
def depart_literal_block(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
101 |
self.write('\n```\n') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
102 |
self.preserve_newlines = False |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
103 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
104 |
def visit_inline(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
105 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
106 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
107 |
def depart_inline(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
108 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
109 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
110 |
def visit_image(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
111 |
self.write('') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
112 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
113 |
def depart_image(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
114 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
115 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
116 |
def write_row(self, row, widths): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
117 |
for i, entry in enumerate(row): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
118 |
text = entry[0][0] if len(entry) > 0 else '' |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
119 |
if i != 0: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
120 |
self.write('|') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
121 |
self.write('{:{}}'.format(text, widths[i])) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
122 |
self.write('\n') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
123 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
124 |
def visit_table(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
125 |
table = node.children[0] |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
126 |
colspecs = table[:-2] |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
127 |
thead = table[-2] |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
128 |
tbody = table[-1] |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
129 |
widths = [int(cs['colwidth']) for cs in colspecs] |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
130 |
sep = '|'.join(['-' * w for w in widths]) + '\n' |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
131 |
self.write('\n\n') |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
132 |
self.write_row(thead[0], widths) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
133 |
self.write(sep) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
134 |
for row in tbody: |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
135 |
self.write_row(row, widths) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
136 |
raise nodes.SkipChildren |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
137 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
138 |
def depart_table(self, node): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
139 |
pass |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
140 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
141 |
class MDWriter(writers.Writer): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
142 |
"""GitHub-flavored markdown writer""" |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
143 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
144 |
supported = ('md',) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
145 |
"""Formats this writer supports.""" |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
146 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
147 |
def translate(self): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
148 |
translator = Translator(self.document) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
149 |
self.document.walkabout(translator) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
150 |
self.output = (translator.output, translator.version) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
151 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
152 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
153 |
def convert(rst_path): |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
154 |
"""Converts RST file to Markdown.""" |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
155 |
return core.publish_file(source_path=rst_path, writer=MDWriter()) |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
156 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
157 |
|
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
158 |
if __name__ == '__main__': |
| f8deb5b9 |
Poul Sander |
2022-01-15 13:55 |
159 |
convert(sys.argv[1]) |
|
|
1970-01-01 00:00 |
160 |
|