diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 8bd5ba7a7..fd9c0d14e 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -25,6 +25,7 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/master[ * include revremark on title page if specified (#1198) * align first block of list item with marker if primary text is blank (#1196) * apply correct margin to list item if primary text is blank (#1196) +* allow page break before and after part and before chapter to be configured by theme (#74) * allow page number of PDF to import to be specified using `page` attribute on image macro (#1202) * resolve variables in font catalog in theme file * if value of scripts attribute is cjk, break lines between any two CJK characters (except punctuation) (#1206) diff --git a/docs/theming-guide.adoc b/docs/theming-guide.adoc index 1b130edc8..4f9744285 100644 --- a/docs/theming-guide.adoc +++ b/docs/theming-guide.adoc @@ -1425,6 +1425,27 @@ The keys in this category control the style of most headings, including part tit |heading: margin-bottom: 9.6 +|chapter-break-before +|always {vbar} auto + +(default: always) +|heading: + chapter: + break-before: auto + +|part-break-before +|always {vbar} auto + +(default: always) +|heading: + part: + break-before: auto + +|part-break-after +|always {vbar} auto + +(default: auto) +|heading: + part: + break-after: always + 3+|[#key-prefix-heading-level]*Key Prefix:* <{zwsp}>>^[1]^ |align diff --git a/lib/asciidoctor-pdf/converter.rb b/lib/asciidoctor-pdf/converter.rb index b578d093e..3a3739586 100644 --- a/lib/asciidoctor-pdf/converter.rb +++ b/lib/asciidoctor-pdf/converter.rb @@ -520,15 +520,20 @@ def convert_section sect, opts = {} if sect.part_or_chapter? if sect.chapter? type = :chapter - start_new_chapter sect + if @theme.heading_chapter_break_before == 'auto' + start_new_chapter sect if @theme.heading_part_break_after == 'always' && sect == sect.parent.sections[0] + else + start_new_chapter sect + end else type = :part - start_new_part sect + start_new_part sect unless @theme.heading_part_break_before == 'auto' end - else - # FIXME smarter calculation here!! - start_new_page unless at_page_top? || cursor > (height_of title) + (@theme.heading_margin_top || 0) + (@theme.heading_margin_bottom || 0) + (@root_font_size * @theme.base_line_height * 1.5) end + # FIXME smarter calculation here!! + unless cursor > (height_of title) + (@theme.heading_margin_top || 0) + (@theme.heading_margin_bottom || 0) + (@root_font_size * @theme.base_line_height * 1.5) + start_new_page + end unless at_page_top? # QUESTION should we store pdf-page-start, pdf-anchor & pdf-destination in internal map? sect.set_attr 'pdf-page-start', (start_pgnum = page_number) # QUESTION should we just assign the section this generated id? diff --git a/spec/section_spec.rb b/spec/section_spec.rb index 9e7768572..6c857c055 100644 --- a/spec/section_spec.rb +++ b/spec/section_spec.rb @@ -245,4 +245,66 @@ (expect text[2][:string]).to eql 'anonymous preface' (expect text[2][:font_size]).to eql 10.5 end + + it 'should not add break before chapter if break-before key in theme is auto' do + pdf = to_pdf <<~'EOS', pdf_theme: { heading_chapter_break_before: 'auto' }, analyze: true + = Document Title + :doctype: book + + == Chapter A + + == Chapter B + EOS + + chapter_a_text = (pdf.find_text 'Chapter A')[0] + chapter_b_text = (pdf.find_text 'Chapter B')[0] + (expect chapter_a_text[:page_number]).to eql 2 + (expect chapter_b_text[:page_number]).to eql 2 + end + + it 'should not add break before part if break-before key in theme is auto' do + pdf = to_pdf <<~'EOS', pdf_theme: { heading_part_break_before: 'auto', heading_chapter_break_before: 'auto' }, analyze: true + = Document Title + :doctype: book + + = Part I + + == Chapter in Part I + + = Part II + + == Chapter in Part II + EOS + + part_1_text = (pdf.find_text 'Part I')[0] + part_2_text = (pdf.find_text 'Part II')[0] + (expect part_1_text[:page_number]).to eql 2 + (expect part_2_text[:page_number]).to eql 2 + end + + it 'should add break after part if break-after key in theme is always' do + pdf = to_pdf <<~'EOS', pdf_theme: { heading_part_break_after: 'always', heading_chapter_break_before: 'auto' }, analyze: true + = Document Title + :doctype: book + + = Part I + + == Chapter in Part I + + == Another Chapter in Part I + + = Part II + + == Chapter in Part II + EOS + + part_1_text = (pdf.find_text 'Part I')[0] + part_2_text = (pdf.find_text 'Part II')[0] + chapter_1_text = (pdf.find_text 'Chapter in Part I')[0] + chapter_2_text = (pdf.find_text 'Another Chapter in Part I')[0] + (expect part_1_text[:page_number]).to eql 2 + (expect chapter_1_text[:page_number]).to eql 3 + (expect chapter_2_text[:page_number]).to eql 3 + (expect part_2_text[:page_number]).to eql 4 + end end diff --git a/spec/xref_spec.rb b/spec/xref_spec.rb new file mode 100644 index 000000000..9777e72a6 --- /dev/null +++ b/spec/xref_spec.rb @@ -0,0 +1,19 @@ +require_relative 'spec_helper' + +describe 'Asciidoctor::PDF::Converter - Xref' do + context 'Interdocument' do + it 'should convert interdocument xrefs to internal references' do + input_file = Pathname.new fixture_file 'book.adoc' + pdf = to_pdf input_file + p2_annotations = get_annotations pdf, 2 + (expect p2_annotations).to have_size 1 + chapter_2_ref = p2_annotations[0] + (expect chapter_2_ref[:Subtype]).to eql :Link + (expect chapter_2_ref[:Dest]).to eql '_chapter_2' + p3_annotations = get_annotations pdf, 3 + first_steps_ref = p3_annotations[0] + (expect first_steps_ref[:Subtype]).to eql :Link + (expect first_steps_ref[:Dest]).to eql '_first_steps' + end + end +end