Last week, I wrote about customizing an Asciidoctor PDF so it looks like an InfoQ Mini-Book. Shortly after writing that blog post, Dan Allen responded to my questions and showed me how to customize Asciidoctor's PDF generation. I ended up using both techniques he described: creating a custom theme and using Ruby to override methods. To recap, here are the changes I was hoping to make:
- The colophon is not aligned to the bottom of the page.
- The title page (first one after the cover) and colophon pages should be merged.
- The dedication and acknowledgement headers are not center-aligned and underlined like InfoQ's format.
- The main sections don't have whole-page delimiters.
- The table of contents comes right after the title page, rather than after the dedication and acknowledgement.
I'm happy to report that I was able to fix most these issues, except for the second one and last one. There is a pull request to allow changing the location of the table of contents, but I was unable to make it work. I spent a good hour building the asciidoctor-pdf gem and trying to modify AsciidoctorJ to use it. In the end, I decided to mark this as a bug in the JHipster book and we'll fix it when Asciidoctor supports moving the table of contents.
To customize the output, I created an src/main/ruby/asciidoctor-pdf-extensions.rb
file and added the following code to it:
require 'asciidoctor-pdf' unless defined? ::Asciidoctor::Pdf
module AsciidoctorPdfExtensions
def layout_title_page doc
# no title page
end
def layout_chapter_title node, title
if node.id == "dedication" || node.id == "acknowledgements"
layout_heading_custom title, align: :center
elsif node.id.include? "mini-book" # colophon
move_down 470
layout_heading title, size: @theme.base_font_size
elsif node.id.include? "jhipster" #chapters
puts 'Processing ' + node.id + '...'
move_down 120
# set Akkurat font for all custom headings
font 'Akkurat'
layout_heading 'PART', align: :right, size: 120, color: [91, 54, 8, 13], style: :normal
move_up 40
part_number = "ONE"
if node.id.include? "ui-components"
part_number = "TWO"
elsif node.id.include? "api"
part_number = "THREE"
end
layout_heading part_number, align: :right, size: 120, color: [42, 1, 83, 1], style: :bold
layout_heading title, align: :right, color: [42, 1, 83, 1], style: :normal, size: 30
move_up 30
start_new_page
else
# delegate to default implementation
super
end
end
def layout_heading_custom string, opts = {}
move_down 100
typeset_text string, calc_line_metrics((opts.delete :line_height) || @theme.heading_line_height), {
inline_format: true
}.merge(opts)
move_up 5
$i = 0
underline = ''
while $i < string.length do
if string == 'Dedication'
underline += '/////'
else
underline += '//////'
end
$i += 1
end
if string == 'Dedication'
underline += '////'
end
typeset_text underline, calc_line_metrics((opts.delete :line_height) || @theme.heading_line_height), {
inline_format: true, color: 'B0B0B0', size: 8, style: :italic
}.merge(opts)
move_down 20
end
end
Asciidoctor::Pdf::Converter.prepend AsciidoctorPdfExtensions
Then I modified build.gradle
to use this file.
asciidoctor {
backends 'html5', 'pdf', 'epub3'
attributes 'sourcedir': '../../../main/webapp',
'source-highlighter': 'coderay',
'imagesdir': './images',
toc: 'left',
icons: 'font',
linkattrs: true,
encoding: 'utf-8',
'setanchors': true,
'idprefix': '',
'idseparator': '-',
'docinfo1': 'true'
requires file('src/main/ruby/asciidoctor-pdf-extensions.rb')
}
After getting this to work, we're very close to publishing the JHipster Mini-Book! Thanks to Dan for creating Asciidoctor and supporting this great open source project. It's been a pleasure to write with it and the editing process with Git and pull requests has been wonderful.
Update: The JHipster Mini-Book has been released!