summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.adoc1
-rw-r--r--docs/modules/ROOT/pages/breakable-and-unbreakable.adoc12
-rw-r--r--docs/modules/theme/pages/heading.adoc2
-rw-r--r--lib/asciidoctor/pdf/converter.rb10
-rw-r--r--spec/floating_title_spec.rb23
-rw-r--r--spec/section_spec.rb26
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