Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about rst2pdf (old posts, page 11)

rst2pdf 0.90 is out

Yes, af­ter many moon­s, it's out. Here is the (as usu­al) in­com­plete changel­og:

  • Added raw HTML sup­­port, by Dim­itri Christodoulou

  • Fixed Is­­sue 422: Hav­ing no .afm files made font lookup slow.

  • Fixed Is­­sue 411: Some­­times the win­­dows reg­istry has the font's ab­s­path.

  • Fixed Is­­sue 430: Us­ing --­­con­­fig op­­tion caused oth­­er op­­tions to be ig­nored (by charles at cstan­hope dot com)

  • Fixed Is­­sue 436: Add pdf_style_­­path to sphinx (by tyler@­­datas­­tax.­­com)

  • Fixed Is­­sue 428: page num­bers logged as er­rors

  • Added sup­­port for many pyg­­ments op­­tions in code-block (by Joaquin So­ri­anel­lo)

  • Im­­ple­­men­t­ed Is­­sue 404: plan­­tuml sup­­port

  • Is­­sue 399: sup­­port sphinx's tem­­plate path op­­tion

  • Fixed Is­­sue 406: calls to the wrong log­ging func­­tion

  • Im­­ple­­men­t­ed Is­­sue 391: New --­sec­­tion-­­head­­er-depth op­­tion.

  • Fixed Is­­sue 390: the --­­con­­fig op­­tion was ig­nored.

  • Added sup­­port for many pyg­­ments op­­tions in code-block (by Joaquin So­ri­anel­lo)

  • Fixed Is­­sue 379: Wrong style ap­­plied to para­­graphs in de­f­i­ni­­tion­s.

  • Fixed Is­­sue 378: Mul­ti­­line :ad­­dress: were shown col­lapsed.

  • Im­­ple­­men­t­ed Is­­sue 11: Frame­Break (and con­di­­tion­al Frame­Break)

  • The de­scrip­­tion of frames in page tem­­plates was just wrong.

  • Fixed Is­­sue 374: in some cas­es, lit­er­al blocks were split in­­­side a page, or the page­break came too ear­­ly.

  • Fixed Is­­sue 370: warn­ing about sphinx.addnodes.high­­­light­lang not be­ing han­­dled re­­moved.

  • Fixed Is­­sue 369: crash in hy­phen­a­tor when spec­i­­fy­ing "en" as a lan­guage.

  • Com­­pat­i­­bil­i­­ty fix to Sphinx 0.6.x (For python 2.7 doc­s)

This re­lease did not fo­cus on Sphinx bugs, so those are prob­a­bly still there. Hope­ful­ly the next round is at­tack­ing those.

Abandonment issues: rst2pdf

Of all the corpses of my pro­ject­s, there is one thatI feel worse about, which is rst2pdf. I feel bad about aband­non­ing sev­er­al, but rst2pdf was ac­tu­al­ly a use­ful tool, used by a bunch of peo­ple, and that it has nev­er gath­ered enough mo­men­tum with oth­er de­vel­op­ers is sad.

So, I will pick it up. I will spend about 4 hours a week on it. The plan is to:

  1. Gath­­er some patch­es that are lin­ger­ing on the is­­sue track­­er

  2. Fix some sim­­ple-ish bugs

  3. Make an­oth­er re­lease with 1) and 2)

And of course:

  1. Not let it fall in dis­­re­­pair again

In the meantime, here is a nice thing I just heard about. Dimitri Christodoulou has hacked rst2pdf so that it can handle the raw:: html directive.

This, dear friends is com­plete­ly nut­s, ab­so­lute­ly out of scope for any giv­en do­cu­tils tool, and just too cool :-)

I will try to hi­jack his code (prop­er cred­it and so on), and in­cor­po­rate it in­to rst2pdf.

And Dim­itri, or any­one else who wants to do cool stuff with rst2pdf: let me know! I will give you com­mit rights im­me­di­ate­ly!

Rst2pdf 0.16 is out!

Fi­nal­ly, a new re­lease of rst2pdf!

You can get it at its site: http://rst2pdf.­google­code.­com

rst2pdf is a tool to con­vert re­struc­tured text (a light, cool markup lan­guage) to PDF us­ing re­port­lab in­stead of La­TeX.

It has been used for many things, from book­s, to mag­a­zi­nes, to brochures, to man­u­al­s, to web­sites and has lots of fea­tures:

  • Font em­bed­d­ing (T­TF or Type1 fonts)

  • Cas­­cad­ing Stylesheets

  • Ex­treme­­ly flex­i­ble plug­in ar­chi­tec­­ture (y­ou can do things like ren­der the head­­ings from ar­bi­­trary SVG files!)

  • Sphinx in­­te­­gra­­tion.

  • Con­­fig­urable page lay­outs

  • Cus­­tom cov­­er pages via tem­­plates

  • And much, much more...

The big­gest change in 0.16 is sure­ly the im­proved sup­port for Sphinx 1.0.x so if you are us­ing Sphinx, you re­al­ly want this ver­sion.

Al­so, it has a ton of bug­fix­es, and a few mi­nor but use­ful new fea­tures.

Here's the whole changel­og if you don't be­lieve me:

  • Fixed Is­­sue 343: Plugged mem­o­ry leak in the RSON pars­er.

  • Fix for Is­­sue 287: there is still a cor­n­er case if you have two sec­­tions with the same ti­tle, at the same lev­­el, in the same page, in dif­fer­­ent files where the links will break.

  • Fixed Is­­sue 367: ger­­man-lo­­cal­ized dates are MM. DD. YYYY so when used in sphinx's tem­­plate cov­­er they ap­­peared weird, like a list item. Fixed with a mi­nor work­around in the tem­­plate.

  • Fixed Is­­sue 366: links to "#" make no sense on a PDF file

  • Made de­f­i­ni­­tions from de­f­i­ni­­tion lists more sty­lable.

  • Moved de­f­i­ni­­tion lists to Split­­Ta­bles, so you can have very long de­f­i­ni­­tion­s.

  • Fixed Is­­sue 318: Im­­ple­­men­t­ed Do­­main spe­­cif­ic in­­dex­es for Sphinx 1.0.x

  • Fixed In­­dex links when us­ing Sphinx/pdf­builder.

  • Fixed Is­­sue 360: Set lit­er­al.­­word­Wrap to None by de­­fault so it does­n't in­­her­it word­Wrap CJK when you use the oth­­er­­wise cor­rect ja­­pa­­nese set­t­ings. In any case, lit­er­al blocks are not sup­­posed to wrap at al­l.

  • Switched pdf­builder to use Split­­Ta­bles by de­­fault (it made no sense not to do it)

  • Fixed Is­­sue 365: some TTF fonts don't val­i­­date but they work any­way.

  • Set a valid de­­fault baseurl for Sphinx (makes it much faster!)

  • New fea­­ture: --use-num­bered-links to show sec­­tion num­bers in links to sec­­tion­s, like "See sec­­tion 2.3 Ter­mi­­na­­tion"

  • Added stylesheets for land­s­cape pa­per sizes (i.e: a4-­­land­s­cape.style)

  • Fixed Is­­sue 364: Some op­­tions not re­spec­t­ed when passed in per-­­doc op­­tions in sphinx.

  • Fixed Is­­sue 361: mul­ti­­ple line­breaks in line blocks were col­lapsed.

  • Fixed Is­­sue 363: strange char­ac­ters in some cas­es in math di­rec­­tive.

  • Fixed Is­­sue 362: Smarter au­­to-en­­clos­ing of equa­­tions in $...$

  • Fixed Is­­sue 358: --re­al--­­foot­notes de­­faults to False, but help text in­­di­­cates de­­fault is True

  • Fixed Is­­sue 359: Wrong --­­fit-back­­­ground-­­mode help string

  • Fixed Is­­sue 356: mis­s­ing cells if a cell spawns rows and col­umn­s.

  • Fixed Is­­sue 349: Work cor­rec­t­­ly with lan­guages that are avail­able in form aa_bb and not aa (ex­am­­ple: zh_c­n)

  • Fixed Is­­sue 345: give file/­­line in­­­fo when there is an er­ror in a raw PDF di­rec­­tive.

  • Fixed Is­­sue 336: JPEG im­ages should work even with­­out PIL (but give a warn­ing be­­cause sizes will prob­a­bly be wrong)

  • Fixed Is­­sue 351: foot­note/c­i­­ta­­tion re­f­er­ences were gen­er­at­ed in­­­cor­rec­t­­ly, which caused prob­lems if there was a ci­­ta­­tion with the same text as a head­­ing.

  • Fixed Is­­sue 353: bet­ter han­dling of graphviz, so that it works with­­out vec­­tor­pdf but gives a warn­ing about it.

  • Fixed Is­­sue 354: make todo_n­ode from sphinx cus­­tom­iz­a­ble.

  • Fixed bug where nest­ed lists broke page lay­out if the page was smal­l.

  • Smarter --in­­line-links op­­tion

  • New ex­ten­­sion: fan­­cyti­tles, see //ral­si­­na.me/we­blog/­­post­s/B­B906.html

  • New fea­­ture: tab-width op­­tion in code-block di­rec­­tive (de­­faults to 8).

  • Fixed Is­­sue 340: end­notes/­­foot­notes were not styled.

  • Fixed Is­­sue 339: class names us­ing _ were not us­able.

  • Fixed Is­­sue 335: ug­­ly crash when us­ing im­ages in some spe­­cif­ic places (looks like a re­­port­lab bug)

  • Fixed Is­­sue 329: make the fig­ure align­­men­t/­­class at­tributes work more like La­­TeX than HT­M­L.

  • Fixed Is­­sue 328: list item styles were be­ing ig­nored.

  • Fixed Is­­sue 186: new --use-float­ing-im­ages makes im­ages with :align: set work like in HT­M­L, with the next flow­able flow­ing be­­side it.

  • Fixed Is­­sue 307: head­­er/­­foot­er from stylesheet now sup­­ports in­­­line rest markup and sub­­sti­­tu­­tions de­fined in the main doc­u­­men­t.

  • New pdf_­­toc_depth op­­tion for Sphinx/pdf­builder

  • New pdf_use_­­toc op­­tion for Sphinx/pdf­builder

  • Fixed Is­­sue 308: com­­pat­i­­bil­i­­ty with re­­port­lab from SVN

  • Fixed Is­­sue 323: er­rors in the con­­fig.sam­­ple made it work weird.

  • Fixed Is­­sue 322: Im­age sub­­sti­­tu­­tions did­n't work in doc­u­­ment ti­­tle.

  • Im­­ple­­men­t­ed Is­­sue 321: un­der­­line and strikethrough avail­able in stylesheet.

  • Fixed Is­­sue 317: Ug­­ly er­ror mes­sage when file does not ex­ist

Extending rst2pdf: easy and powerful

I do al­most all my busi­ness writ­ing (and my book) us­ing re­struc­tured tex­t. And when I want to pro­duce print­-qual­i­ty out­put, I tend to use my own tool, rst2pdf.

It's pop­u­lar, sure­ly my most pop­u­lar pro­gram, but very few know it's al­so ex­treme­ly easy to ex­tend (hat tip to Patrick Maupin, who wrote this part!). And not on­ly that, but you can make it do some amaz­ing stuff with a lit­tle ef­fort.

To show that, let's cre­ate the most daz­zling sec­tion head­ings known to man ( Let's see you do what this ba­by can do in La­TeX ;-).

First: de­fine the prob­lem.

The ti­tles rst2pdf can pro­duce are bor­ing. If you pull ev­ery lever and push ev­ery but­ton, you may end with the ti­tle tex­t, in a Com­ic San­s, right-aligned, in pink let­ter­ing, with av­o­cado-­green back­ground and a red bor­der.

And that's as far as the cus­tomiza­tion ca­pa­bil­i­ties go us­ing stylesheet­s. That's usu­al­ly enough, be­cause rst2pdf is not meant for brochures or some­thing like that (but I have done it).

The re­al prob­lem is that when you get all graph­ic-de­sign­er on rst2pdf, you lose doc­u­ment struc­ture, be­cause you are not be­ing se­man­tic.

Sec­ond: de­fine the goal.

So, imag­ine you want to make a head­ing that looks like this:

fancytitles1

The im­age is tak­en from the li­brary of con­gress with some light (and bad) gimp­ing by me to leave that emp­ty space at the left, and the ti­tle was added us­ing Inkscape.

Can you do that with rst2pdf? Hell no you can't. Not with­out cod­ing. So let's code an ex­ten­sion that lets you cre­ate any head­ing you like with­in the lim­its of Inkscape!

First, we cre­ate a SVG tem­plate for the head­ings (it's a bit big be­cause it has the bit­map em­bed­ded).

Three: the im­age-­head­ing flow­able

Suppose you have an image of the heading just like the one above. How would you draw that in a PDF? In reportlab, you do that using flowables which are elements that compose the story that is your document. These flowables are arranged in pages, and that's your PDF.

If you are do­ing a head­ing, there's a bit more, in that you need to add a book­mark, so it ap­pears on the PDF ta­ble of con­tents.

So, here's a flowable that does just that. It's cobbled from pieces inside rst2pdf, and is basically an unholy mix of Heading and MyImage:

class FancyHeading(MyImage):
  '''This is a cross between the Heading flowable, that adds outline
  entries so you have a PDF TOC, and MyImage, that draws images'''

  def __init__(self, *args, **kwargs):
      # The inicialization is taken from rst2pdf.flowables.Heading
      self.stext = kwargs.pop('text')
      # Cleanup title text
      self.stext = re.sub(r'<[^>]*?>', '', unescape(self.stext))
      self.stext = self.stext.strip()

      # Stuff needed for the outline entry
      self.snum = kwargs.pop('snum')
      self.level = kwargs.pop('level')
      self.parent_id= kwargs.pop('parent_id')


      MyImage.__init__(self, *args, **kwargs)

  def drawOn(self,canv,x,y,_sW):

      ## These two lines are magic.
      #if isinstance(self.parent_id, tuple):
          #self.parent_id=self.parent_id[0]

      # Add outline entry. This is copied from rst2pdf.flowables.heading
      canv.bookmarkHorizontal(self.parent_id,0,0+self.image.height)

      if canv.firstSect:
          canv.sectName = self.stext
          canv.firstSect=False
          if self.snum is not None:
              canv.sectNum = self.snum
          else:
              canv.sectNum = ""

      canv.addOutlineEntry(self.stext.encode('utf-8','replace'),
                                self.parent_id.encode('utf-8','replace'),
                                int(self.level), False)

      # And let MyImage do all the drawing
      MyImage.drawOn(self,canv,x,y,_sW)

And how do we tell rst2df to use that instead of a regular Heading? by overriding the TitleHandler class. Here's where the extension magic kicks in.

If you de­fine, in an ex­ten­sion, a class like this:

class FancyTitleHandler(genelements.HandleParagraph, docutils.nodes.title):

Then that class will handle all docutils nodes of class docutils.nodes.title. Here, I just took rst2pdf.genelements.HandleTitle and changed how it works for level-1 headings, making it generate a FancyHeading instead of a Heading... and that's all there is to it.

class FancyTitleHandler(genelements.HandleParagraph, docutils.nodes.title):
  '''
  This class will handle title nodes.

  It takes a "titletemplate.svg", replaces TITLEGOESHERE with
  the actual title text, and draws that using the FancyHeading flowable
  (see below).

  Since this class is defined in an extension, it
  effectively replaces rst2pdf.genelements.HandleTitle.
  '''

  def gather_elements(self, client, node, style):
      # This method is copied from the HandleTitle class
      # in rst2pdf.genelements.

      # Special cases: (Not sure this is right ;-)
      if isinstance(node.parent, docutils.nodes.document):
          #node.elements = [Paragraph(client.gen_pdftext(node),
                                      #client.styles['title'])]
          # The visible output is now done by the cover template
          node.elements = []
          client.doc_title = node.rawsource
          client.doc_title_clean = node.astext().strip()
      elif isinstance(node.parent, docutils.nodes.topic):
          node.elements = [Paragraph(client.gen_pdftext(node),
                                      client.styles['topic-title'])]
      elif isinstance(node.parent, docutils.nodes.Admonition):
          node.elements = [Paragraph(client.gen_pdftext(node),
                                      client.styles['admonition-title'])]
      elif isinstance(node.parent, docutils.nodes.table):
          node.elements = [Paragraph(client.gen_pdftext(node),
                                      client.styles['table-title'])]
      elif isinstance(node.parent, docutils.nodes.sidebar):
          node.elements = [Paragraph(client.gen_pdftext(node),
                                      client.styles['sidebar-title'])]
      else:
          # Section/Subsection/etc.
          text = client.gen_pdftext(node)
          fch = node.children[0]
          if isinstance(fch, docutils.nodes.generated) and \
              fch['classes'] == ['sectnum']:
              snum = fch.astext()
          else:
              snum = None
          key = node.get('refid')
          maxdepth=4
          if reportlab.Version > '2.1':
              maxdepth=6

          # The parent ID is the refid + an ID to make it unique for Sphinx
          parent_id=(node.parent.get('ids', [None]) or [None])[0]+u'-'+unicode(id(node))
          if client.depth > 1:
              node.elements = [ Heading(text,
                      client.styles['heading%d'%min(client.depth, maxdepth)],
                      level=client.depth-1,
                      parent_id=parent_id,
                      node=node,
                      )]
          else: # This is an important title, do our magic ;-)
              # Hack the title template SVG
              tfile = open('titletemplate.svg')
              tdata = tfile.read()
              tfile.close()
              tfile = tempfile.NamedTemporaryFile(dir='.', delete=False, suffix='.svg')
              tfname = tfile.name
              tfile.write(tdata.replace('TITLEGOESHERE', text))
              tfile.close()

              # Now tfname contains a SVG with the right title.
              # Make rst2pdf delete it later.
              client.to_unlink.append(tfname)

              e = FancyHeading(tfname, width=700, height=100,
                  client=client, snum=snum, parent_id=parent_id,
                  text=text, level=client.depth-1)

              node.elements = [e]

          if client.depth <= client.breaklevel:
              node.elements.insert(0, MyPageBreak(breakTo=client.breakside))
      return node.elements

The full ex­ten­sion is in SVN and you can try it this way:

[fancytitles]$ rst2pdf -e fancytitles -e inkscape demo.txt -b1

You need to en­able the Inkscape ex­ten­sion so the SVG will look nice. And here's the out­put:

fancytitles2

You can over­ride how any el­e­ment is han­dled. That's be­ing ex­ten­si­ble :-)

rst2pdf 0.14 released!

It's my plea­sure to an­nounce that I just up­load­ed rst2pdf 0.14 to the site at http://rst2pdf.­google­code.­com.

Rst2pdf is a pro­gram and a li­brary to con­vert re­struc­tured text di­rect­ly in­to PDF us­ing Re­port­lab.

It sup­ports True Type and Type 1 font em­bed­ding, most raster and vec­tor im­age for­mat­s, source code high­light­ing, ar­bi­trary text frames in a page, cas­cad­ing stylesheet­s, the full re­struc­tured text syn­tax and much, much more.

It al­so in­cludes a sphinx ex­ten­sion so you can use it to gen­er­ate PDFs from doc­u­ments built with Sphinx.

In case of prob­lem­s, please re­port them in the Is­sue track­er (http://­code.­google.­com/p/rst2pdf/is­sues/list) or the mail­ing list (http://­group­s.­google.­com/­group/rst2pdf-dis­cuss)

This re­lease fix­es sev­er­al bugs and adds some mi­nor fea­tures com­pared to 0.13.2. Here are some of the changes:

  • Fixed Is­­sue 197: Ta­ble bor­ders were con­­fus­ing.

  • Fixed Is­­sue 297: styles from de­­fault­­.j­­son leaked on­­to oth­­er syn­­tax high­­­light­ing stylesheet­s.

  • Fixed Is­­sue 295: key­­word re­­place­­ment in head­­er­s/­­foot­ers did­n't work if ###­­Page### and oth­­ers was in­­­side a ta­ble.

  • New fea­­ture: odd­­e­ven di­rec­­tive to dis­­­play al­ter­­na­­tive con­­tent on odd­­/even pages (good for head­­er­s/­­foot­er­s!)

  • Switched all stylesheets to more read­­able RSON for­­mat.

  • Fixed Is­­sue 294: Im­ages were de­­formed when on­­ly height was spec­i­­fied.

  • Fixed Is­­sue 293: Ac­­cept left­­/­­cen­ter/right as align­­ments in stylesheet­s.

  • Fixed Is­­sue 292: sep­a­rate style for line num­bers in code­blocks

  • Fixed Is­­sue 291: sup­­port class di­rec­­tive for code­blocks

  • Fixed Is­­sue 104: to­­tal num­ber of pages in head­­er/­­foot­er works in all cas­es now.

  • Fixed Is­­sue 168: linenos and linenothresh­old op­­tions in Sphinx now work cor­rec­t­­ly.

  • Fixed re­­gres­­sion in 0.12 (in­ter­ac­­tion be­tween rst2pdf and sphinx math)

  • Doc­u­­men­t­ed ex­ten­­sions in the man­u­al

  • Bet­ter styling of bul­let­s/items (Is­­sue 289)

  • Fixed Is­­sue 290: don't fail on bro­ken im­ages

  • Bet­ter font find­­ing in win­­dows (patch by tech­­tonik, Is­­sue 282).

  • Fixed Is­­sue 166: Im­­ple­­men­t­ed Sphinx's hlist (hor­i­­zon­­tal list­s)

  • Fixed Is­­sue 284: Im­­ple­­men­t­ed pro­­duc­­tion lists for sphinx

  • Fixed Is­­sue 165: De­f­i­ni­­tion lists not prop­er­­ly in­­­den­t­ed in­­­side ad­­mo­ni­­tions or ta­bles.

  • SVG Im­ages work in­­­line when us­ing the inkscape ex­ten­­sion.

  • Fixed Is­­sue 268: TOCs shift­ed to the left on RL 2.4

  • Fixed Is­­sue 281: sphinx test au­­to­­ma­­tion was bro­ken

  • Fixed Is­­sue 280: wrong page tem­­plates used in sphinx

En­joy!


Contents © 2000-2023 Roberto Alsina