Tuesday, August 16, 2011

Reviewing Git-Scribe PDF Changes

‹prev | My Chain | next›

Up today, I am going to review my PDF changes to git-scribe.

First up, in the do_pdf generator, are three options that I added for the XSLT processing of the docbook version of The SPDY Book:
def do_pdf
#...
do_docbook

strparams = {'callout.graphics' => 0,
'navig.graphics' => 0,
'admon.textlabel' => 1,
'admon.graphics' => 0,
                   'page.width' => '7.5in',
'page.height' => '9in',
'initial-page-number' => 'auto-odd'
}
param = strparams.map { |k, v| "--stringparam #{k} #{v}" }.join(' ')
cmd = "xsltproc  --nonet #{param} --output #{local('book.fo')} #{base('docbook-xsl/fo.xsl')} #{local('book.xml')}"
#...
end
The page.width and page.height options are fairly self-explanatory. I am using 7.5in x 9in to roughly conform to major computer book publisher requirements.

The initial-page-number option was one of many attempts that I made to get chapters to always start on the "recto" (right) page. That does not actually work, so I remove it and leave a TODO comment to hopefully solve that some day.

The remaining changes that I applied to get PDF generation in decent shape were to docbook-xsl/fo.xsl. I was quite worried about those changes. I know that the git-scribe source includes the docbook-xsl (not just this one file) and I was worried that I had been making changes directly to the docbook fo.xsl file. Happily that is stored in docbook-xsl/fo/fo.xsl. The docbook-xsl/fo.xsl file is explicitly called in do_pdf to load in local, git-scribe specific changes to the docbook defaults. I had been worried about those changes for almost a month now and it turns out that I made them in exactly the right place!

Anyhow, the first change that I made to docbook/fo.xsl was an ultimately failed attempt to get syntax highlighting working:
<!-- Include source syntax highlighting -->
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/highlighting/common.xsl"/>
<!-- This contains the default source highlight styling rules -->
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/highlight.xsl"/>
Sadly, that did not work (there is no syntax highlighting in the PDF version of The SPDY Book). So I remove that and add another TODO to the generator.

The next change that I added was:
<!-- Front cover -->
<xsl:template name="front.cover">
<xsl:call-template name="page.sequence">
<xsl:with-param name="master-reference">my-titlepage</xsl:with-param>
<xsl:with-param name="content">
<fo:block text-align="center">
<fo:external-graphic src="url(images/cover.jpg)" content-height="9in"/>
</fo:block>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
That overrides the default (empty) cover page XSL template with an actual image. In there, I follow the git-scribe convention of naming the image images/cover.jpg. This requires me to include the cover of my book in the images directory of my working git-scribe directory:
➜  spdybook git:(master) pwd
/home/cstrom/repos/spdybook
➜  spdybook git:(master) ls
bin  book  LICENSE  marketing.asc  notes  output  README.asciidoc  remaining.org  samples
➜  spdybook git:(master) ls book/images/cover.jpg 
book/images/cover.jpg
Of course, it wasn't as easy as adding 10 lines of XSLT "code" to get the cover image included. I also had to define my own "page master", which describes special page layout to be used for specific pages:
<xsl:template name="user.pagemasters">

<!-- my title page -->
<fo:simple-page-master master-name="my-titlepage"
page-width="{$page.width}"
page-height="{$page.height}"
margin-top="0"
margin-bottom="0"
margin-left="0"
margin-right="0">
<xsl:if test="$axf.extensions != 0">
<xsl:call-template name="axf-page-master-properties">
<xsl:with-param name="page.master">my-titlepage</xsl:with-param>
</xsl:call-template>
</xsl:if>
<fo:region-body margin-bottom="{$body.margin.bottom}"
margin-top="0"
column-gap="{$column.gap.titlepage}"
column-count="{$column.count.titlepage}">
</fo:region-body>
</fo:simple-page-master>

</xsl:template>
Amazingly, I believe that every one of those attributes was necessary in order to get the cover image to display properly (i.e. take up the entire first page, margins and all).

Even that was not enough to get XSLT to apply the cover template. I also had to override the template that selects user-defined pagemasters:
<xsl:template name="select.user.pagemaster">
<xsl:param name="element"/>
<xsl:param name="pageclass"/>
<xsl:param name="default-pagemaster"/>

<!-- Return my customized title page master name if for titlepage,
otherwise return the default -->

<xsl:choose>
    <xsl:when test="$default-pagemaster = 'titlepage-first'">
<xsl:value-of select="'my-titlepage'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$default-pagemaster"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
That's a crazy amount of work just to include the cover page:



Ultimately, however, it is worth the trouble. Without it, alt-tabbing displays a generic PDF icon and systray icons are similarly generic. With a cover image, the reader is treated to a visual feast:



So my remaining TODOs in git-scribe are to get source code highlighting working in PDF and to start all chapters on the recto page. Both are nice-to-haves, but I can live without them. My hope is that someone smarter than I can figure those out by the time I am ready for my next book.

For now, I think I am happy with the state of my git-scribe changes.

Day #113

2 comments:

  1. Thank you very much for this description! I followed it and now I have my book in PDF version with cover! Yabba-dabba-do! :)

    ReplyDelete
    Replies
    1. Awesome! Glad it helped! There really is something special about alt-tabbing through windows and seeing *your* book's cover among the list of items, isn't there? Congrats!

      Delete