Skip to content
This repository
Browse code

Allow converter to follow local conventions

Fix :
- Les titres sont désormais toujours reconnus
- Les blocs de code utilisent la syntaxe Pandoc
- Les blocs de code sont parfois reconnus et labellisés plus
précisément (http, php, xml, html, etc.)
- Certaines illustrations n'apparaissaient pas quand elles étaient
suivies par un élément XML contenant uniquement des espaces blancs
- Si use illustration set associée à un paragraphe complet et pas une
légende, elle suit désormais le paragraphe au lieu de s'y attacher
- Les codes ne contiennent plus de mise en forme (qui est alors perdue)
- Les notes en bas de page sont inscrite directement sous le paragraphe
et pas en fin de document
- Les listes numérotées qui ont une numérotation continue entre deux
listes successives gardent leur numérotation au lieu de recommencer à
zéro (peut ne pas être complet)
- Les citations sont reconnues
- Un message d'erreur (et une marque dans le code résultant) est
affichée en cas d'une image qui n'a pu être extraite (ou pour les
objets non image)
- Les apostrophes typographiques sont remplacées par des apostrophes
simples

Problèmes persistants :
- certains blocs de code de style "HTTP" ne sont pas reconnus comme code
- les détails de style de code ne sont pas importés (mais certains sont
reconnus à l'aide de la première ligne du code)
- les listes ont un espace blanc en trop en bas du dernier item
- certaines rares images ne peuvent être importées

Le résultat est probablement de qualité suffisante pour lancer la
génération
  • Loading branch information...
commit acb4bdf40bfd1c8f8976913cd135c7f6bbd35697 1 parent 46df45b
Éric D. authored

Showing 1 changed file with 80 additions and 32 deletions. Show diff stats Hide diff stats

  1. +80 32 util/odt2txt_py.py
112 util/odt2txt_py.py
@@ -13,6 +13,8 @@
13 13
14 14 Writteby by [Yuri Takhteyev](http://www.freewisdom.org).
15 15
  16 +*Modified* for this project
  17 +
16 18 Project website: http://www.freewisdom.org/projects/python-markdown/odt2txt
17 19 Contact: yuri [at] freewisdom.org
18 20
@@ -22,7 +24,7 @@
22 24 """
23 25
24 26
25   -import sys, os, zipfile, xml.dom.minidom, shutil
  27 +import sys, os, zipfile, xml.dom.minidom, shutil, re
26 28
27 29 IGNORED_TAGS = ["office:annotation"]
28 30
@@ -67,6 +69,9 @@ def __init__ (self):
67 69 self.hasImg = False
68 70 self.indented = 0
69 71
  72 + def setBlockquote(self, value) :
  73 + self.blockquote = value
  74 +
70 75 def setIndented (self, value) :
71 76 self.indented = value
72 77
@@ -111,6 +116,7 @@ def __init__ (self, filepath, img_prefix) :
111 116 self.hasTitle = 0
112 117 self.img_prefix = img_prefix
113 118 self.imgs_num = 0
  119 + self.previous_list_item = 0
114 120
115 121 self.load(filepath)
116 122
@@ -157,6 +163,9 @@ def extractParagraphProperties (self, style, parent=None) :
157 163 paraProps = ParagraphProps()
158 164
159 165 name = style.getAttribute("style:name")
  166 +
  167 + if name == "Quotations":
  168 + paraProps.setBlockquote(True)
160 169
161 170 if name.startswith("Heading_20_") :
162 171 level = name[11:]
@@ -273,14 +282,15 @@ def listToString (self, listElement) :
273 282
274 283 styleName = listElement.getAttribute("text:style-name")
275 284 props = self.listStyles.get(styleName, ListProperties())
  285 +
276 286
  287 + if listElement.getAttribute("text:continue-numbering") != "true" :
  288 + self.previous_list_item = 0
277 289
278   -
279   - i = 0
280 290 for item in listElement.childNodes :
281   - i += 1
  291 + self.previous_list_item += 1
282 292 if props.ordered :
283   - number = str(i)
  293 + number = str(self.previous_list_item)
284 294 number = number + "." + " "*(2-len(number))
285 295 buffer += number + self.paragraphToString(item.childNodes[0],
286 296 indent=3)
@@ -310,12 +320,10 @@ def toString (self) :
310 320 text = self.paragraphToString(paragraph)
311 321 if text :
312 322 buffer += text + "\n\n"
313   -
314   - if self.footnotes :
315   -
316   - buffer += "--------\n\n"
317   - for cite, body in self.footnotes :
318   - buffer += "[^%s]: %s\n\n" % (cite, body)
  323 + if self.footnotes :
  324 + for cite, body in self.footnotes :
  325 + buffer += " [^%s]: %s\n\n" % (cite, body)
  326 + self.footnotes = []
319 327
320 328
321 329 return self.compressCodeBlocks(buffer)
@@ -334,7 +342,7 @@ def slugify(self, value):
334 342 value = unicode(re.sub(' ', '-', value))
335 343 return value
336 344
337   - def textToString(self, element, props = None) :
  345 + def textToString(self, element, props = None, format = True) :
338 346
339 347 buffer = u""
340 348 img_in_buffer = None
@@ -352,16 +360,16 @@ def textToString(self, element, props = None) :
352 360 text = self.textToString(node)
353 361
354 362 if not text.strip() :
355   - return "" # don't apply styles to white space
  363 + continue # don't apply styles to white space
356 364
357 365 styleName = node.getAttribute("text:style-name")
358 366 style = self.textStyles.get(styleName, None)
359 367
360   - if style.fixed :
  368 + if format and style.fixed :
361 369 buffer += "`" + text + "`"
362 370 continue
363 371
364   - if style :
  372 + if format and style :
365 373 if style.italic and style.bold :
366 374 mark = "***"
367 375 elif style.italic :
@@ -371,7 +379,8 @@ def textToString(self, element, props = None) :
371 379 else :
372 380 mark = ""
373 381 else :
374   - mark = "<" + styleName + ">"
  382 + mark = ""
  383 + #mark = "<" + styleName + ">"
375 384
376 385 buffer += "%s%s%s" % (mark, text, mark)
377 386
@@ -403,8 +412,11 @@ def textToString(self, element, props = None) :
403 412 elif tag == "text:a" :
404 413
405 414 text = self.textToString(node)
406   - link = node.getAttribute("xlink:href")
407   - buffer += "[%s](%s)" % (text, link)
  415 + if format :
  416 + link = node.getAttribute("xlink:href")
  417 + buffer += "[%s](%s)" % (text, link)
  418 + else :
  419 + buffer += text
408 420
409 421 elif tag == "text:bookmark" or tag == "text:bookmark-end":
410 422 # YOAV - need to add an # link here
@@ -422,15 +434,30 @@ def textToString(self, element, props = None) :
422 434 else :
423 435 buffer += " {" + tag + "} "
424 436
425   - if img_in_buffer:
  437 + if format and img_in_buffer:
426 438 self.imgs_num += 1
427 439 extension = img_in_buffer.split('.')[-1]
428   - imgname = "img/" + self.img_prefix + "-" + str(self.imgs_num) + "-" + self.slugify(buffer) + "." + extension
429   - os.rename(img_in_buffer, imgname)
430   - buffer += "\n![" + buffer + "](../../../raw/master/content/" + imgname + ")"
  440 + legend = ""
  441 + prefix = ""
  442 + imgname = ""
  443 + if len(buffer) > 200 :
  444 + legend = ""
  445 + imgname = "img/" + self.img_prefix + self.slugify(buffer)[:50] + "." + extension
  446 + prefix = buffer + "\n\n"
  447 + else :
  448 + legend = buffer
  449 + imgname = "img/" + self.img_prefix + self.slugify(buffer) + "." + extension
  450 + prefix = ""
  451 + buffer = prefix + "![" + legend + "](" + imgname + ")"
  452 + if os.path.exists(img_in_buffer) and (img_in_buffer[:9] != "./Object ") :
  453 + # print >> sys.stderr, "Try : " + img_in_buffer + " -> " + imgname + "\n"
  454 + os.rename(img_in_buffer, imgname)
  455 + else :
  456 + buffer += "\n/!\\ MISSING IMAGE /!\\ "
  457 + print >> sys.stderr, "Warning: Missing image "+imgname+" ("+img_in_buffer+")\n"
431 458
432 459
433   - if(props):
  460 + if format and props:
434 461 props.setHasImg(img_in_buffer != None)
435 462
436 463 return buffer
@@ -440,6 +467,11 @@ def paragraphToString(self, paragraph, indent = 0) :
440 467
441 468 style_name = paragraph.getAttribute("text:style-name")
442 469 paraProps = self.paragraphStyles.get(style_name) #, None)
  470 + heading_level = paragraph.getAttribute("text:outline-level")
  471 + if len(heading_level) > 0:
  472 + heading_level = int(heading_level)
  473 + if heading_level > 0:
  474 + paraProps.setHeading(heading_level)
443 475 text = self.textToString(paragraph, paraProps)
444 476
445 477 #print >>sys.stderr, "TEXT:", text
@@ -466,21 +498,36 @@ def paragraphToString(self, paragraph, indent = 0) :
466 498 return "#" * level + " " + text
467 499
468 500 elif paraProps.code:
469   - lines = [" %s" % line for line in text.split("\n")]
  501 + #lines = [" %s" % line for line in text.split("\n")]
470 502 #print >>sys.stderr, "CODE"
471   - return "\n".join(lines)
  503 + text = self.textToString(paragraph, paraProps, False).strip()
  504 + classnames = [ ]
  505 + if text[:7] == "HTTP/1." :
  506 + classnames.append( ".http .response" )
  507 + elif re.match("^(GET|POST|DELETE|PUT|HEAD) /", text) :
  508 + classnames.append( ".http .request")
  509 + elif text[:5] == "<?php" :
  510 + classnames.append( ".php" )
  511 + elif text[:15] == "<!DOCTYPE HTML>" or text[:15] == "<!DOCTYPE html>" :
  512 + classnames.append( ".html")
  513 + elif text[:6] == "<?xml " :
  514 + classnames.append( ".xml")
  515 + if text.find("\n") == -1 :
  516 + classnames.append( ".oneline" )
  517 + prefix = ""
  518 + if len(classnames) :
  519 + prefix = " {" + " ".join(classnames) + "}"
  520 + return "~~~~~~~" + prefix + "\n" + text + "\n~~~~~~~"
472 521 elif paraProps.hasImg:
473 522 #print >>sys.stderr, "HAS_IMG"
474 523 return text
475   -
476   - """
477   - if paraProps.indented :
  524 +
  525 + if paraProps.blockquote :
478 526 return self.wrapParagraph(text, indent = indent, blockquote = True)
479 527
480 528 else :
481   - """
482   - #print >>sys.stderr, "WRAP"
483   - return self.wrapParagraph(text, indent = indent)
  529 + #print >>sys.stderr, "WRAP"
  530 + return self.wrapParagraph(text, indent = indent)
484 531
485 532
486 533 def wrapParagraph(self, text, indent = 0, blockquote=False) :
@@ -516,8 +563,9 @@ def wrapParagraph(self, text, indent = 0, blockquote=False) :
516 563
517 564 filename = sys.argv[1]
518 565
519   - odt = OpenDocumentTextFile(filename, img_prefix)
  566 + odt = OpenDocumentTextFile(filename, img_prefix )
520 567 unicode = odt.toString()
  568 + unicode = unicode.replace(u'\u2019', "'")
521 569 out_utf8 = unicode.encode("utf-8")
522 570 sys.stdout.write(out_utf8)
523 571 shutil.rmtree("Pictures")

0 comments on commit acb4bdf

Please sign in to comment.
Something went wrong with that request. Please try again.