diff options
| -rw-r--r-- | CHANGELOG.adoc | 1 | ||||
| -rw-r--r-- | docs/modules/ROOT/pages/breakable-and-unbreakable.adoc | 12 | ||||
| -rw-r--r-- | docs/modules/theme/pages/heading.adoc | 2 | ||||
| -rw-r--r-- | lib/asciidoctor/pdf/converter.rb | 10 | ||||
| -rw-r--r-- | spec/floating_title_spec.rb | 23 | ||||
| -rw-r--r-- | spec/section_spec.rb | 26 |
6 files changed, 64 insertions, 10 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 8e75fe3f..34d900c1 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -11,6 +11,7 @@ Enhancements:: * allow page background image to be specified per layout using `+{page-layout}+` attribute reference in path (#1739) * allow page margin for rotated page to be configured independently using `page-margin-rotated` theme key or `pdf-page-margin-rotated` document attribute (#1719) +* allow orphan detection to be enabled for all section titles and discrete headings by setting `heading-min-height-after` to `auto` in theme (#2268) * set `docimagesdir` attribute when attribute substitutions are applied to value from theme (#2278) * start page numbering and running content on empty verso page before first chapter of prepress book if `start-at` value is 0 (#2252) * don't force page break after TOC with automatic placement in article if `title-page` attribute is set and value of `toc-break-after` theme key is `auto` (#1768) diff --git a/docs/modules/ROOT/pages/breakable-and-unbreakable.adoc b/docs/modules/ROOT/pages/breakable-and-unbreakable.adoc index 6c9adad0..5cb8b0a3 100644 --- a/docs/modules/ROOT/pages/breakable-and-unbreakable.adoc +++ b/docs/modules/ROOT/pages/breakable-and-unbreakable.adoc @@ -70,7 +70,7 @@ This option can also be added to a discrete heading to ensure the heading is kep [,asciidoc] ---- -[%breakable] +[discrete%breakable] === Discrete heading Next block of content. @@ -81,6 +81,16 @@ In other words, the option prevents a page break immediately following the title Instead, the page break will come _before_ the title. This option does not make the converter attempt to keep an entire section on the same page. +If you want to enable this feature for all sections and discrete headings, you can set the `heading-min-height-after` theme key to `auto` instead. + +[,yaml] +---- +heading: + min-height-after: auto +---- + +Keep in mind that this does add extra processing to the conversion, which may impact conversion time. + === Other blocks You don't need to assign the `breakable` option any other block types because <<default,breakable is enabled by default>> and those other blocks already provide automatic orphan prevention. diff --git a/docs/modules/theme/pages/heading.adoc b/docs/modules/theme/pages/heading.adoc index aaaef929..9c45f912 100644 --- a/docs/modules/theme/pages/heading.adoc +++ b/docs/modules/theme/pages/heading.adoc @@ -69,7 +69,7 @@ heading: margin-top: 6 |min-height-after -|xref:measurement-units.adoc[Measurement] + +|xref:measurement-units.adoc[Measurement] {vbar} auto + (default: `20`) |[source] heading: diff --git a/lib/asciidoctor/pdf/converter.rb b/lib/asciidoctor/pdf/converter.rb index bc2b2e36..22d56635 100644 --- a/lib/asciidoctor/pdf/converter.rb +++ b/lib/asciidoctor/pdf/converter.rb @@ -2792,12 +2792,12 @@ module Asciidoctor # Position the cursor for where to ink the specified section title or discrete heading node. # - # This method computes whether there is enough room on the page to prevent the specified node - # from being orphaned. If there is not enough room, the method will advance the cursor to + # This method computes whether there's enough room on the page to prevent the specified node + # from being orphaned. If there's not enough room, the method will advance the cursor to # the next page. This method is not called if the cursor is already at the top of the page or # whether this node has no node that follows it in document order. def arrange_heading node, title, opts - if node.option? 'breakable' + if (min_height_after = @theme.heading_min_height_after) == 'auto' || (node.option? 'breakable') orphaned = nil dry_run single_page: true do start_page = page @@ -2824,9 +2824,7 @@ module Asciidoctor heading_h = (height_of_typeset_text title) + (@theme[%(heading_h#{hlevel}_margin_top)] || @theme.heading_margin_top) + (@theme[%(heading_h#{hlevel}_margin_bottom)] || @theme.heading_margin_bottom) + h_padding_t + h_padding_b - if (min_height_after = @theme.heading_min_height_after) && (node.context == :section ? node.blocks? : !node.last_child?) - heading_h += min_height_after - end + heading_h += min_height_after if min_height_after && (node.context == :section ? node.blocks? : !node.last_child?) cursor >= heading_h end advance_page unless h_fits diff --git a/spec/floating_title_spec.rb b/spec/floating_title_spec.rb index ce284d3e..8b169f47 100644 --- a/spec/floating_title_spec.rb +++ b/spec/floating_title_spec.rb @@ -76,7 +76,7 @@ describe 'Asciidoctor::PDF::Converter - Floating Title' do it 'should force discrete heading with breakable option to next page if no content is inked below it' do pdf = with_content_spacer 10, 675 do |spacer_path| - to_pdf <<~EOS + to_pdf <<~EOS, pdf_theme: { heading_min_height_after: nil } image::#{spacer_path}[] [discrete#buddy%breakable] @@ -95,6 +95,27 @@ describe 'Asciidoctor::PDF::Converter - Floating Title' do (expect (get_dest pdf, 'buddy')[:page_number]).to eql 2 end + it 'should force discrete heading to next page when heading_min_content_after is auto if no content is inked below it' do + pdf = with_content_spacer 10, 675 do |spacer_path| + to_pdf <<~EOS, pdf_theme: { heading_min_height_after: 'auto' } + image::#{spacer_path}[] + + [discrete#buddy] + == Discrete Heading + + ---- + Do it like this. + ---- + EOS + end + + (expect pdf.pages).to have_size 2 + p2_text = (pdf.page 2).text + (expect p2_text).to include 'Discrete Heading' + (expect get_names pdf).to have_key 'buddy' + (expect (get_dest pdf, 'buddy')[:page_number]).to eql 2 + end + it 'should allow arrange_heading to be reimplemented to always keep heading with content that follows it' do source_file = doc_file 'modules/extend/examples/pdf-converter-avoid-break-after-heading.rb' source_lines = (File.readlines source_file).select {|l| l == ?\n || (l.start_with? ' ') } diff --git a/spec/section_spec.rb b/spec/section_spec.rb index 332ea23d..cd768442 100644 --- a/spec/section_spec.rb +++ b/spec/section_spec.rb @@ -1099,7 +1099,7 @@ describe 'Asciidoctor::PDF::Converter - Section' do end it 'should keep section with first block of content if breakable option is set on section' do - pdf = to_pdf <<~EOS, analyze: true + pdf = to_pdf <<~EOS, pdf_theme: { heading_min_height_after: nil }, analyze: true == Section A image::tall.svg[pdfwidth=70mm] @@ -1123,6 +1123,30 @@ describe 'Asciidoctor::PDF::Converter - Section' do (expect content_text[:page_number]).to be 2 end + it 'should keep section with first block of content if heading_min_height_after key is auto' do + pdf = to_pdf <<~EOS, pdf_theme: { heading_min_height_after: 'auto' }, analyze: true + == Section A + + image::tall.svg[pdfwidth=70mm] + + == Section B + + [%unbreakable] + -- + keep + + this + + together + -- + EOS + + section_b_text = pdf.find_unique_text 'Section B' + (expect section_b_text[:page_number]).to be 2 + content_text = pdf.find_unique_text 'keep' + (expect content_text[:page_number]).to be 2 + end + it 'should not add break before chapter if heading-chapter-break-before key in theme is auto' do pdf = to_pdf <<~'EOS', pdf_theme: { heading_chapter_break_before: 'auto' }, analyze: true = Document Title |
