]>
Commit | Line | Data |
---|---|---|
c12bc4de RD |
1 | ############################################################################## |
2 | # | |
3 | # Zope Public License (ZPL) Version 1.0 | |
4 | # ------------------------------------- | |
5 | # | |
6 | # Copyright (c) Digital Creations. All rights reserved. | |
7 | # | |
8 | # This license has been certified as Open Source(tm). | |
9 | # | |
10 | # Redistribution and use in source and binary forms, with or without | |
11 | # modification, are permitted provided that the following conditions are | |
12 | # met: | |
13 | # | |
14 | # 1. Redistributions in source code must retain the above copyright | |
15 | # notice, this list of conditions, and the following disclaimer. | |
16 | # | |
17 | # 2. Redistributions in binary form must reproduce the above copyright | |
18 | # notice, this list of conditions, and the following disclaimer in | |
19 | # the documentation and/or other materials provided with the | |
20 | # distribution. | |
21 | # | |
22 | # 3. Digital Creations requests that attribution be given to Zope | |
23 | # in any manner possible. Zope includes a "Powered by Zope" | |
24 | # button that is installed by default. While it is not a license | |
25 | # violation to remove this button, it is requested that the | |
26 | # attribution remain. A significant investment has been put | |
27 | # into Zope, and this effort will continue if the Zope community | |
28 | # continues to grow. This is one way to assure that growth. | |
29 | # | |
30 | # 4. All advertising materials and documentation mentioning | |
31 | # features derived from or use of this software must display | |
32 | # the following acknowledgement: | |
33 | # | |
34 | # "This product includes software developed by Digital Creations | |
35 | # for use in the Z Object Publishing Environment | |
36 | # (http://www.zope.org/)." | |
37 | # | |
38 | # In the event that the product being advertised includes an | |
39 | # intact Zope distribution (with copyright and license included) | |
40 | # then this clause is waived. | |
41 | # | |
42 | # 5. Names associated with Zope or Digital Creations must not be used to | |
43 | # endorse or promote products derived from this software without | |
44 | # prior written permission from Digital Creations. | |
45 | # | |
46 | # 6. Modified redistributions of any form whatsoever must retain | |
47 | # the following acknowledgment: | |
48 | # | |
49 | # "This product includes software developed by Digital Creations | |
50 | # for use in the Z Object Publishing Environment | |
51 | # (http://www.zope.org/)." | |
52 | # | |
53 | # Intact (re-)distributions of any official Zope release do not | |
54 | # require an external acknowledgement. | |
55 | # | |
56 | # 7. Modifications are encouraged but must be packaged separately as | |
57 | # patches to official Zope releases. Distributions that do not | |
58 | # clearly separate the patches from the original work must be clearly | |
59 | # labeled as unofficial distributions. Modifications which do not | |
60 | # carry the name Zope may be packaged in any form, as long as they | |
61 | # conform to all of the clauses above. | |
62 | # | |
63 | # | |
64 | # Disclaimer | |
65 | # | |
66 | # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY | |
67 | # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
68 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
69 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS | |
70 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
71 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
72 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
73 | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
74 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
75 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
76 | # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
77 | # SUCH DAMAGE. | |
78 | # | |
79 | # | |
80 | # This software consists of contributions made by Digital Creations and | |
81 | # many individuals on behalf of Digital Creations. Specific | |
82 | # attributions are listed in the accompanying credits file. | |
83 | # | |
84 | ############################################################################## | |
85 | ||
86 | import string | |
87 | from string import join, split, find, lstrip | |
88 | ||
89 | class DocBookClass: | |
90 | ||
ddfc587a RD |
91 | element_types={ |
92 | '#text': '_text', | |
93 | 'StructuredTextDocument': 'document', | |
94 | 'StructuredTextParagraph': 'paragraph', | |
95 | 'StructuredTextExample': 'example', | |
96 | 'StructuredTextBullet': 'bullet', | |
97 | 'StructuredTextNumbered': 'numbered', | |
98 | 'StructuredTextDescription': 'description', | |
99 | 'StructuredTextDescriptionTitle': 'descriptionTitle', | |
100 | 'StructuredTextDescriptionBody': 'descriptionBody', | |
101 | 'StructuredTextSection': 'section', | |
102 | 'StructuredTextSectionTitle': 'sectionTitle', | |
103 | 'StructuredTextLiteral': 'literal', | |
104 | 'StructuredTextEmphasis': 'emphasis', | |
105 | 'StructuredTextStrong': 'strong', | |
106 | 'StructuredTextLink': 'link', | |
107 | 'StructuredTextXref': 'xref', | |
108 | 'StructuredTextSGML': 'sgml', | |
109 | } | |
110 | ||
111 | def dispatch(self, doc, level, output): | |
112 | getattr(self, self.element_types[doc.getNodeName()])(doc, level, output) | |
113 | ||
114 | def __call__(self, doc, level=1): | |
115 | r=[] | |
116 | self.dispatch(doc, level-1, r.append) | |
117 | return join(r,'') | |
118 | ||
119 | def _text(self, doc, level, output): | |
120 | if doc.getNodeName() == 'StructuredTextLiteral': | |
121 | output(doc.getNodeValue()) | |
122 | else: | |
123 | output(lstrip(doc.getNodeValue())) | |
124 | ||
125 | def document(self, doc, level, output): | |
126 | output('<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">\n') | |
127 | output('<book>\n') | |
128 | children=doc.getChildNodes() | |
129 | if (children and | |
130 | children[0].getNodeName() == 'StructuredTextSection'): | |
131 | output('<title>%s</title>' % children[0].getChildNodes()[0].getNodeValue()) | |
132 | for c in children: | |
133 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
134 | output('</book>\n') | |
135 | ||
136 | def section(self, doc, level, output): | |
137 | output('\n<section>\n') | |
138 | children=doc.getChildNodes() | |
139 | for c in children: | |
140 | getattr(self, self.element_types[c.getNodeName()])(c, level+1, output) | |
141 | output('\n</section>\n') | |
142 | ||
143 | def sectionTitle(self, doc, level, output): | |
144 | output('<title>') | |
145 | for c in doc.getChildNodes(): | |
146 | try: | |
c12bc4de | 147 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) |
ddfc587a RD |
148 | except: |
149 | print "failed", c.getNodeName(), c | |
150 | output('</title>\n') | |
151 | ||
152 | def description(self, doc, level, output): | |
153 | p=doc.getPreviousSibling() | |
154 | if p is None or p.getNodeName() is not doc.getNodeName(): | |
155 | output('<variablelist>\n') | |
156 | for c in doc.getChildNodes(): | |
157 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
158 | n=doc.getNextSibling() | |
159 | if n is None or n.getNodeName() is not doc.getNodeName(): | |
160 | output('</variablelist>\n') | |
161 | ||
162 | def descriptionTitle(self, doc, level, output): | |
163 | output('<varlistentry><term>\n') | |
164 | for c in doc.getChildNodes(): | |
165 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
166 | output('</term>\n') | |
167 | ||
168 | def descriptionBody(self, doc, level, output): | |
169 | output('<listitem><para>\n') | |
170 | for c in doc.getChildNodes(): | |
171 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
172 | output('</para></listitem>\n') | |
173 | output('</varlistentry>\n') | |
174 | ||
175 | def bullet(self, doc, level, output): | |
176 | p=doc.getPreviousSibling() | |
177 | if p is None or p.getNodeName() is not doc.getNodeName(): | |
178 | output('<itemizedlist>\n') | |
179 | output('<listitem><para>\n') | |
180 | ||
181 | for c in doc.getChildNodes(): | |
182 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
183 | n=doc.getNextSibling() | |
184 | output('</para></listitem>\n') | |
185 | if n is None or n.getNodeName() is not doc.getNodeName(): | |
186 | output('</itemizedlist>\n') | |
187 | ||
188 | def numbered(self, doc, level, output): | |
189 | p=doc.getPreviousSibling() | |
190 | if p is None or p.getNodeName() is not doc.getNodeName(): | |
191 | output('<orderedlist>\n') | |
192 | output('<listitem><para>\n') | |
193 | for c in doc.getChildNodes(): | |
194 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
195 | n=doc.getNextSibling() | |
196 | output('</para></listitem>\n') | |
197 | if n is None or n.getNodeName() is not doc.getNodeName(): | |
198 | output('</orderedlist>\n') | |
199 | ||
200 | def example(self, doc, level, output): | |
201 | i=0 | |
202 | for c in doc.getChildNodes(): | |
203 | if i==0: | |
204 | output('<programlisting>\n<![CDATA[\n') | |
205 | ## | |
206 | ## eek. A ']]>' in your body will break this... | |
207 | ## | |
208 | output(prestrip(c.getNodeValue())) | |
209 | output('\n]]></programlisting>\n') | |
210 | else: | |
211 | getattr(self, self.element_types[c.getNodeName()])( | |
212 | c, level, output) | |
213 | ||
214 | def paragraph(self, doc, level, output): | |
215 | output('<para>\n\n') | |
216 | for c in doc.getChildNodes(): | |
217 | getattr(self, self.element_types[c.getNodeName()])( | |
218 | c, level, output) | |
219 | output('</para>\n\n') | |
220 | ||
221 | def link(self, doc, level, output): | |
222 | output('<ulink url="%s">' % doc.href) | |
223 | for c in doc.getChildNodes(): | |
224 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
225 | output('</ulink>') | |
c12bc4de | 226 | |
ddfc587a RD |
227 | def emphasis(self, doc, level, output): |
228 | output('<emphasis>') | |
229 | for c in doc.getChildNodes(): | |
230 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
231 | output('</emphasis> ') | |
c12bc4de | 232 | |
ddfc587a RD |
233 | def literal(self, doc, level, output): |
234 | output('<literal>') | |
235 | for c in doc.getChildNodes(): | |
236 | output(c.getNodeValue()) | |
237 | output('</literal>') | |
c12bc4de | 238 | |
ddfc587a RD |
239 | def strong(self, doc, level, output): |
240 | output('<emphasis>') | |
241 | for c in doc.getChildNodes(): | |
242 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
243 | output('</emphasis>') | |
c12bc4de | 244 | |
ddfc587a RD |
245 | def xref(self, doc, level, output): |
246 | output('<xref linkend="%s"/>' % doc.getNodeValue()) | |
c12bc4de | 247 | |
ddfc587a RD |
248 | def sgml(self, doc, level, output): |
249 | output(doc.getNodeValue()) | |
c12bc4de | 250 | |
c12bc4de RD |
251 | |
252 | def prestrip(v): | |
ddfc587a RD |
253 | v=string.replace(v, '\r\n', '\n') |
254 | v=string.replace(v, '\r', '\n') | |
255 | v=string.replace(v, '\t', ' ') | |
256 | lines=string.split(v, '\n') | |
257 | indent=len(lines[0]) | |
258 | for line in lines: | |
259 | if not len(line): continue | |
260 | i=len(line)-len(string.lstrip(line)) | |
261 | if i < indent: | |
262 | indent=i | |
263 | nlines=[] | |
264 | for line in lines: | |
265 | nlines.append(line[indent:]) | |
266 | return string.join(nlines, '\n') | |
c12bc4de RD |
267 | |
268 | ||
269 | class DocBookChapter(DocBookClass): | |
270 | ||
ddfc587a RD |
271 | def document(self, doc, level, output): |
272 | output('<chapter>\n') | |
273 | children=doc.getChildNodes() | |
274 | if (children and | |
275 | children[0].getNodeName() == 'StructuredTextSection'): | |
276 | output('<title>%s</title>' % children[0].getChildNodes()[0].getNodeValue()) | |
277 | for c in children[0].getChildNodes()[1:]: | |
278 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
279 | output('</chapter>\n') | |
c12bc4de RD |
280 | |
281 | ets = DocBookClass.element_types | |
ddfc587a | 282 | ets.update({'StructuredTextImage': 'image'}) |
c12bc4de RD |
283 | |
284 | class DocBookChapterWithFigures(DocBookChapter): | |
285 | ||
ddfc587a | 286 | element_types = ets |
c12bc4de | 287 | |
ddfc587a RD |
288 | def image(self, doc, level, output): |
289 | if hasattr(doc, 'key'): | |
290 | output('<figure id="%s"><title>%s</title>\n' % (doc.key, doc.getNodeValue()) ) | |
291 | else: | |
292 | output('<figure><title>%s</title>\n' % doc.getNodeValue()) | |
293 | ## for c in doc.getChildNodes(): | |
294 | ## getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
295 | output('<graphic fileref="%s"></graphic>\n</figure>\n' % doc.href) | |
c12bc4de RD |
296 | |
297 | class DocBookArticle(DocBookClass): | |
298 | ||
ddfc587a RD |
299 | def document(self, doc, level, output): |
300 | output('<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">\n') | |
301 | output('<article>\n') | |
302 | children=doc.getChildNodes() | |
303 | if (children and | |
304 | children[0].getNodeName() == 'StructuredTextSection'): | |
305 | output('<articleinfo>\n<title>%s</title>\n</articleinfo>\n' % | |
306 | children[0].getChildNodes()[0].getNodeValue()) | |
307 | for c in children: | |
308 | getattr(self, self.element_types[c.getNodeName()])(c, level, output) | |
309 | output('</article>\n') | |
c12bc4de RD |
310 | |
311 | ||
312 | class DocBookBook: | |
313 | ||
ddfc587a RD |
314 | def __init__(self, title=''): |
315 | self.title = title | |
316 | self.chapters = [] | |
c12bc4de | 317 | |
ddfc587a RD |
318 | def addChapter(self, chapter): |
319 | self.chapters.append(chapter) | |
c12bc4de | 320 | |
ddfc587a RD |
321 | def read(self): |
322 | out = '<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">\n<book>\n' | |
323 | out = out + '<title>%s</title>\n' % self.title | |
324 | for chapter in self.chapters: | |
325 | out = out + chapter + '\n</book>\n' | |
c12bc4de | 326 | |
ddfc587a | 327 | return out |
c12bc4de | 328 | |
ddfc587a RD |
329 | def __str__(self): |
330 | return self.read() | |
331 | ||
c12bc4de | 332 |