aboutsummaryrefslogtreecommitdiff
path: root/mistletoe_rtf.py
blob: 88345b3ca00d94cb657aabd2e389b78abadf1598 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
1#  mistletoe-rtf: RTF output for the mistletoe Markdown parser
2#  Copyright © 2019  Lee Yingtong Li (RunasSudo)
3#
4#  This Source Code Form is subject to the terms of the Mozilla Public
5#  License, v. 2.0. If a copy of the MPL was not distributed with this
6#  file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8import mistletoe
9
10class RTFRenderer(mistletoe.base_renderer.BaseRenderer):
11	def __init__(self, *extras):
12		super().__init__(*extras)
13	
14	def render_strong(self, token):
15		return r'{{\b {}}}'.format(self.render_inner(token))
16	
17	def render_emphasis(self, token):
18		return r'{{\i {}}}'.format(self.render_inner(token))
19	
20	def render_inline_code(self, token):
21		return r'{{\f1 {}}}'.format(self.render_inner(token))
22	
23	def render_raw_text(self, token):
24		return token.content.replace('\\', '\\\\').replace('{', r'\{').replace('}', r'\}')
25	
26	def render_strikethrough(self, token):
27		return r'{{\strike {}}}'.format(self.render_inner(token))
28	
29	def render_image(self, token):
30		raise Exception('NYI')
31	
32	def render_link(self, token):
33		return r'{{\field{{\*\fldinst{{HYPERLINK "{target}"}}}}{{\fldrslt{{\ul\cf1 {inner}}}}}}}'.format(target=token.target, inner=self.render_inner(token))
34	
35	def render_auto_link(self, token):
36		raise Exception('NYI')
37	
38	def render_escape_sequence(self, token):
39		raise Exception('NYI')
40	
41	def render_heading(self, token):
42		template = r'{{\b\fs{fontsize}{inner}\par}}'
43		fontsize = {1: 32, 2: 28, 3: 24, 4: 24, 5: 24, 6: 24}[token.level]
44		return template.format(fontsize=fontsize, inner=self.render_inner(token))
45	
46	def render_quote(self, token):
47		return r'{{\li400 {}}}'.format(self.render_inner(token))
48	
49	def render_paragraph(self, token):
50		template = r'{{{}\par}}'
51		return template.format(self.render_inner(token))
52	
53	def render_block_code(self, token):
54		return r'{{\li400\f1 {}\par}}'.format(self.render_inner(token).rstrip('\n').replace('\n', r'\line '))
55	
56	def render_list(self, token):
57		raise Exception('NYI')
58	
59	def render_list_item(self, token):
60		raise Exception('NYI')
61	
62	def render_table(self, token):
63		template = r'{{\sa0\trowd{cellxs} {inner}}}'
64		
65		cell_width = (6*1440) / len(token.column_align) # 6 inches
66		
67		cellxs = [r'\cellx{}'.format(int(cell_width*(i+1))) for i in range(len(token.column_align))]
68		
69		if hasattr(token, 'header'):
70			head_rendered = self.render_table_row(token.header)
71		
72		inner = self.render_inner(token)
73		
74		return template.format(cellxs=''.join(cellxs), inner=head_rendered+inner)
75	
76	def render_table_row(self, token):
77		cells = [self.render(child) for child in token.children]
78		return ''.join(cells) + r'\row '
79	
80	def render_table_cell(self, token):
81		template = r'{{{inner}\intbl\cell}}'
82		return template.format(inner=self.render_inner(token))
83	
84	def render_thematic_break(self, token):
85		raise Exception('NYI')
86	
87	def render_line_break(self, token):
88		return r'\line '
89	
90	def render_document(self, token):
91		template = r'{{\rtf1\deff0{{\fonttbl{{\f0\froman Times;}}{{\f1\froman Courier;}}}}{{\colortbl;\red0\green0\blue0\;\red0\green0\blue255;}}\sa200\f0 {inner}}}'
92		
93		result_str = template.format(inner=self.render_inner(token))
94		
95		# Escape Unicode
96		result = []
97		for char in result_str:
98			if ord(char) <= 0x7f:
99				result.append(char)
100			else:
101				result.append(r'\u{}?'.format(ord(char)))
102		
103		return ''.join(result)
Contact (issues, pull requests, etc.) at git@yingtongli.me. Generated by cgit.