1 # -*- coding: utf-8 -*-
2 """ This is a docutils RTF Writer
4 We just need a few features so it shouldn't be too difficult
6 This was made possible by:
8 http://search.cpan.org/~sburke/RTF-Writer/lib/RTF/Cookbook.pod
12 Sean M. Burke, sburke@cpan.org
14 Author: BenoƮt Allard
15 Contact: benoit@aeteurope.nl
16 Copyright: This module has been placed in the public domain.
19 from docutils
import writers
, nodes
21 class Writer(writers
.Writer
):
27 writers
.Writer
.__init
__(self
)
28 self
._translator
_class
= RTFTranslator
31 visitor
= self
._translator
_class
(self
.document
)
32 self
.document
.walkabout(visitor
)
33 self
.output
= visitor
.astext()
36 """ Encode special characters """
48 out
+= r
"\'%x" % ord(char
)
57 1: 28, # first heading
58 2: 24, # second heading
64 def wrapper(self
, *args
, **kwargs
):
66 return fn(self
, *args
, **kwargs
)
71 def wrapper(self
, *args
, **kwargs
):
73 return fn(self
, *args
, **kwargs
)
76 class RTFTranslator(nodes
.NodeVisitor
):
78 def __init__(self
, document
):
79 nodes
.NodeVisitor
.__init
__(self
, document
)
81 self
.section_level
= 0
83 self
.bullets
= [] # stack of the currents bullets
84 self
.bullet
= None # next one to add to the next paragraph
87 return '\n'.join(self
.body
)
89 def visit_document(self
, node
):
90 self
.body
.append(r
'{\rtf1\ansi\deff0{\fonttbl{\f0 %s;}}' % FONT_NAME
)
91 self
.body
.append(r
'\deflang1033\widowctrl\fs%d' % FONT_SIZE
[-1])
93 def depart_document(self
, node
):
96 def visit_title(self
, node
):
97 if isinstance(node
.parent
, nodes
.document
):
99 self
.body
.append(r
'{\pard\par\qc\f0\fs%d\b' % FONT_SIZE
[0])
100 elif isinstance(node
.parent
, nodes
.section
):
101 level
= self
.section_level
102 self
.body
.append(r
'{\pard\par\f0\fs%d\b' % FONT_SIZE
[level
])
104 def depart_title(self
, node
):
105 self
.body
.append(r
'\par}')
107 def visit_Text(self
, node
):
108 if self
.bullet
is not None:
109 self
.body
.append(self
.bullet
+'\~')
111 self
.body
.append(toansi(node
.astext()))
113 def depart_Text(self
, node
):
116 def visit_strong(self
, node
):
117 self
.body
.append(r
'{\b')
119 def depart_strong(self
, node
):
120 self
.body
.append('}')
122 def visit_section(self
, node
):
123 self
.section_level
+= 1
125 def depart_section(self
, node
):
126 self
.section_level
-= 1
129 def visit_paragraph(self
, node
):
130 self
.body
.append(r
'{\pard\par\f0\qj\li%d' % (PAR_INDENT
* self
.par_level
))
131 if self
.bullet
is not None:
132 self
.body
.append(r
'\fi-%d' % (PAR_INDENT
/ 2))
135 def depart_paragraph(self
, node
):
136 self
.body
.append('\par}')
139 def visit_bullet_list(self
, node
):
140 self
.bullets
.append(node
['bullet'])
143 def depart_bullet_list(self
, node
):
146 def visit_list_item(self
, node
):
147 self
.bullet
= self
.bullets
[-1]
149 def depart_list_item(self
, node
):
153 def visit_block_quote(self
, node
):
157 def depart_block_quote(self
, node
):
160 def visit_reference(self
, node
):
162 self
.body
.append(r
'{\field{\*\fldinst{HYPERLINK "%s"}}{\fldrslt{\ul' % node
['refuri'])
164 # to balance parenthesis
165 self
.body
.append(r
'{{{')
167 def depart_reference(self
, node
):
168 self
.body
.append('}}}')
170 def visit_docinfo(self
, node
):
171 self
.body
.append(r
'{\info')
173 def depart_docinfo(self
, node
):
174 self
.body
.append('}')
176 def visit_author(self
, node
):
177 self
.body
.append(r
'{\author')
179 def depart_author(self
, node
):
180 self
.body
.append(r
'}')
182 if __name__
== "__main__":
183 """ To test the writer """
184 from docutils
.core
import publish_string
185 f_in
= open('test.rtf', 'rb')
186 rtf
= publish_string(f_in
.read(), writer
=Writer())
191 f_out
= open('a.out', 'wb')