Skip to content

Commit

Permalink
resolves #2489 support toc start at value for page numbering and runn…
Browse files Browse the repository at this point in the history
…ing content when toc is added using macro (PR #2490)
  • Loading branch information
mojavelinux authored Feb 5, 2024
1 parent b6caa26 commit bf6e3b2
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 37 deletions.
25 changes: 15 additions & 10 deletions docs/modules/theme/pages/add-running-content.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,26 @@ running-content:

The `start-at` key accepts the following keywords or an integer:

after-toc:: The running content starts after the TOC, no matter where the TOC is placed in the document.
The `after-toc` value is only recognized if the title page is implicitly or explicitly enabled.
If `media=prepress`, this keyword refers to the first recto page after the last page of the TOC (it will skip an empty verso page).
after-toc:: The running content starts after the last page of the TOC, no matter where the TOC is placed in the document.
If `media=prepress`, this keyword refers to the next recto page after the last page of the TOC.
The `after-toc` value is primarily intended to be used with the book doctype, though it can be used with the article doctype if the title page is enabled.
If the TOC is not enabled, or the title page for an article is not enabled, this value reverts to `body`.

body:: This is the default value.
The running content starts on the first page of the document body, which is typically the first page after the TOC if the TOC is in its default location.
If `media=prepress`, this keyword refers to the first recto page after the last page of the TOC (it will skip an empty verso page).
The running content starts on the first page of the document body.
If the TOC is enabled in its default location, the first page of the document body is the next recto page after the TOC when `media=prepress` or the page that immediately follows the TOC otherwise.

title:: The running content starts on the title page.
The `title` value is only recognized if the title page is implicitly or explicitly enabled.
toc:: The running content starts on the first page of the TOC.
The `toc` value only applies if the TOC is in the default location (before the first page of the body).
If the value is `toc`, and the toc macro is used to position the TOC, the `start-at` behavior is the same as if the TOC is not enabled.
The `toc` value is only recognized if the title page is implicitly or explicitly enabled.

toc:: The running content starts on the first page of the TOC, no matter where the TOC is placed in the document.
The `toc` value is primarily intended to be used with the book doctype, though it can be used with the article doctype if the title page is enabled.
If the TOC is not enabled, or the title page for an article is not enabled, this value reverts to `body`.

[[page]]Integer:: The running content starts on the page that matches the number assigned to `start-at` (i.e., 1 is the first body page, 2 is the second body page).
Refer to the `body` value for an explanation of where the body starts.
For a prepress book (`doctype=book` and `media=prepress`), the running content starts on the empty verso page before the body if the value is `0`.
When an integer is assigned to `start-at`, the title page doesn't need to be enabled.
An integer value is recognized by all doctypes and the title page doesn't need to be enabled.

TIP: To turn off the running content on TOC pages inserted by the toc macro, set the `noheader` or `nofooter` options on the macro (e.g., `toc::[opts=nofooter]`).

Expand Down
24 changes: 15 additions & 9 deletions docs/modules/theme/pages/page-numbers.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,27 @@ page:
The `start-at` key accepts the following keywords or an integer:

after-toc:: The integer page numbering starts after the last page of the TOC, no matter where the TOC is placed in the document.
The `after-toc` value is only recognized if the title page is implicitly or explicitly enabled.
If `media=prepress`, this keyword refers to the first recto page after the last page of the TOC (it will skip an empty verso page).
If `media=prepress`, this keyword refers to the next recto page after the last page of the TOC.
The `after-toc` value is primarily intended to be used with the book doctype, though it can be used with the article doctype if the title page is enabled.
If the TOC is not enabled, or the title page for an article is not enabled, this value reverts to `body`.

body:: This is the default value.
The integer page numbering starts on the first page of the document body, which is typically the first page after the TOC if the TOC is in its default location.
If `media=prepress`, this keyword refers to the first recto page after the last page of the TOC (it will skip an empty verso page).
The integer page numbering starts on the first page of the document body.
If the TOC is enabled in its default location, the first page of the document body is the next recto page after the TOC when `media=prepress` or the page that immediately follows the TOC otherwise.

cover:: The integer page numbering starts on the front cover page of the document.
The `cover` value is only recognized if the document has a front cover page (i.e., `front-cover-image`).

title:: The integer page numbering starts on the title page.
The `title` value is only recognized if the title page is implicitly or explicitly enabled.
toc:: The integer page numbering starts on the first page of the TOC.
The `toc` value only applies if the TOC is in the default location (before the first page of the body).
If the value is `toc`, and the toc macro is used to position the TOC, the `start-at` behavior is the same as if the TOC is not enabled.
The `toc` value is only recognized if the title page is implicitly or explicitly enabled.

toc:: The integer page numbering starts on the first page of the TOC, no matter where the TOC is placed in the document.
The `toc` value is primarily intended to be used with the book doctype, though it can be used with the article doctype if the title page is enabled.
If the TOC is not enabled, or the title page for an article is not enabled, this value reverts to `body`.

Integer:: The page numbering starts at the specified page of the body (i.e., 1 is the first body page, 2 is the second body page).
For a prepress book (`doctype=book` and `media=prepress`), the page numbering starts on the empty verso page before the body if the value is `0`.
Refer to the `body` value for an explanation of where the body starts.
For a prepress book (`doctype=book` and `media=prepress`), the page numbering starts on the verso page before the body if the value is `0`.
An integer value is recognized by all doctypes and the title page doesn't need to be enabled.

Let's start the integer page number on the title page of a document.
Expand Down
49 changes: 31 additions & 18 deletions lib/asciidoctor/pdf/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def convert_document doc
ink_cover_page doc, :front
has_front_cover = page_number > marked_page_number
doctype = doc.doctype
if (has_title_page = (title_page_on = doctype == 'book' || (doc.attr? 'title-page')) && (start_title_page doc))
if (has_title_page = (title_as_page = doctype == 'book' || (doc.attr? 'title-page')) && (start_title_page doc))
# NOTE: the base font must be set before any content is written to the main or scratch document
font @theme.base_font_family, size: @root_font_size, style: @theme.base_font_style
if perform_on_single_page { ink_title_page doc }
Expand All @@ -184,7 +184,7 @@ def convert_document doc
font @theme.base_font_family, size: @root_font_size, style: @theme.base_font_style
end

unless title_page_on
unless title_as_page
body_start_page_number = page_number
theme_font :heading, level: 1 do
ink_general_heading doc, doc.doctitle, align: (@theme.heading_h1_text_align&.to_sym || :center), level: 1, role: :doctitle
Expand All @@ -195,10 +195,10 @@ def convert_document doc

indent_section do
toc_num_levels = (doc.attr 'toclevels', 2).to_i
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && !(get_entries_for_toc doc).empty?)
if (toc_at_top = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && !(get_entries_for_toc doc).empty?)
start_new_page if @ppbook && verso_page?
add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
@toc_extent = allocate_toc doc, toc_num_levels, cursor, (title_page_on && theme.toc_break_after != 'auto')
@toc_extent = allocate_toc doc, toc_num_levels, cursor, (title_as_page && theme.toc_break_after != 'auto')
else
@toc_extent = nil
end
Expand All @@ -210,7 +210,7 @@ def convert_document doc
min_start_at = 1
end

if title_page_on
if title_as_page
zero_page_offset = has_front_cover ? 1 : 0
first_page_offset = has_title_page ? zero_page_offset.next : zero_page_offset
body_offset = (body_start_page_number = page_number) - 1
Expand All @@ -223,8 +223,10 @@ def convert_document doc
when 'title'
running_content_start_at = 'toc' unless has_title_page
when 'toc'
running_content_start_at = 'body' unless insert_toc
uses_start_at_toc = true
running_content_start_at = 'body' unless toc_at_top
when 'after-toc'
uses_start_at_after_toc = true
running_content_start_at = 'body'
end
end
Expand All @@ -243,8 +245,10 @@ def convert_document doc
when 'title'
page_numbering_start_at = 'toc' unless has_title_page
when 'toc'
page_numbering_start_at = 'body' unless insert_toc
uses_start_at_toc = true
page_numbering_start_at = 'body' unless toc_at_top
when 'after-toc'
uses_start_at_after_toc = true
page_numbering_start_at = 'body'
end
end
Expand Down Expand Up @@ -298,12 +302,17 @@ def convert_document doc
end

if (toc_extent = @toc_extent)
if title_page_on && !insert_toc
if @theme.running_content_start_at == 'after-toc' || @theme.page_numbering_start_at == 'after-toc' # rubocop:disable Style/SoleNestedConditional
last_toc_page = toc_extent.to.page
last_toc_page += 1 if @ppbook && (recto_page? last_toc_page)
num_front_matter_pages[0] = last_toc_page if @theme.running_content_start_at == 'after-toc'
num_front_matter_pages[1] = last_toc_page if @theme.page_numbering_start_at == 'after-toc'
if title_as_page && !toc_at_top && (uses_start_at_toc || uses_start_at_after_toc)
if uses_start_at_toc
toc_offset = toc_extent.from.page - 1
num_front_matter_pages[0] = toc_offset if @theme.running_content_start_at == 'toc'
num_front_matter_pages[1] = toc_offset if @theme.page_numbering_start_at == 'toc'
end
if uses_start_at_after_toc
after_toc_offset = toc_extent.to.page
after_toc_offset += 1 if @ppbook && (recto_page? after_toc_offset)
num_front_matter_pages[0] = after_toc_offset if @theme.running_content_start_at == 'after-toc'
num_front_matter_pages[1] = after_toc_offset if @theme.page_numbering_start_at == 'after-toc'
end
end
toc_page_nums = ink_toc doc, toc_num_levels, toc_extent.from.page, toc_extent.from.cursor, num_front_matter_pages[1]
Expand Down Expand Up @@ -2384,11 +2393,15 @@ def convert_toc node, opts = {}
if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && !(get_entries_for_toc doc).empty?
start_toc_page node, placement if (is_book = doc.doctype == 'book')
add_dest_for_block node, id: (node.id || 'toc') if is_macro
toc_extent = @toc_extent = allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
if title_page_on && @theme.page_numbering_start_at == 'after-toc'
new_start_page_number = toc_extent.to.page + 1
new_start_page_number += 1 if @ppbook && (verso_page? new_start_page_number)
@index.start_page_number = new_start_page_number
toc_extent = @toc_extent = allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_as_page = is_book || (doc.attr? 'title-page'))
if title_as_page
if @theme.page_numbering_start_at == 'toc'
@index.start_page_number = toc_extent.from.page
elsif @theme.page_numbering_start_at == 'after-toc'
new_start_page_number = toc_extent.to.page + 1
new_start_page_number += 1 if @ppbook && (verso_page? new_start_page_number)
@index.start_page_number = new_start_page_number
end
end
if is_macro
@disable_running_content[:header] += toc_extent.page_range if node.option? 'noheader'
Expand Down
32 changes: 32 additions & 0 deletions spec/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,38 @@
(expect terms).to eql %w(anchor AsciiDoc Asciidoctor authoring)
end

it 'should adjust start page number for prepress book when page numbering starts at toc and toc macro is used' do
pdf = to_pdf <<~'END', pdf_theme: { page_numbering_start_at: 'toc' }, analyze: true
= Book Title
:doctype: book
:media: prepress
:toc: macro
[dedication]
= Dedication
Credit where credit is due.
toc::[]
== First Chapter
((apples))
== Second Chapter
((bananas))
[index]
== Index
END

index_title_text = (pdf.find_text 'Index')[-1]
(expect index_title_text[:page_number]).to be 11
index_lines = pdf.lines pdf.find_text page_number: 11
(expect index_lines).to eql ['Index', 'A', 'apples, 3', 'B', 'bananas, 5']
end

it 'should adjust start page number for prepress book when page numbering starts after-toc and toc macro is used' do
pdf = to_pdf <<~'END', pdf_theme: { page_numbering_start_at: 'after-toc' }, analyze: true
= Book Title
Expand Down
48 changes: 48 additions & 0 deletions spec/running_content_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,27 @@
(expect pgnum_labels).to eql [nil, nil, '1', '2', '3']
end

it 'should start running content at toc in body of book when start at is toc and macro toc is used' do
pdf = to_pdf <<~END, pdf_theme: { running_content_start_at: 'toc' }, enable_footer: true, analyze: true
= Document Title
:doctype: book
:toc: macro
== First Chapter
toc::[]
== Second Chapter
== Third Chapter
END

pgnum_labels = (1.upto pdf.pages.size).each_with_object [] do |page_number, accum|
accum << ((pdf.find_text page_number: page_number, y: 14.263)[-1] || {})[:string]
end
(expect pgnum_labels.slice 0, 5).to eql [nil, nil, '2', '3', '4']
end

it 'should start running content after toc in body of book when start at is after-toc and macro toc is used' do
filler = (1..20).map {|it| %(== #{['Filler'] * 20 * ' '} #{it}\n\ncontent) }.join %(\n\n)
pdf = to_pdf <<~END, pdf_theme: { running_content_start_at: 'after-toc' }, enable_footer: true, analyze: true
Expand Down Expand Up @@ -786,6 +807,33 @@
(expect pgnum_labels).to eql [nil, '1', '2', '3']
end

it 'should start page numbering at toc in body of book when start at is toc and toc macro is used' do
pdf = to_pdf <<~END, enable_footer: true, pdf_theme: { page_numbering_start_at: 'toc' }, analyze: true
= Book Title
:doctype: book
:toc: macro
== Dedication
To the only person who gets me.
toc::[]
== Acknowledgements
Thanks all to all who made this possible!
== Chapter One
content
END

pgnum_labels = (1.upto pdf.pages.size).each_with_object [] do |page_number, accum|
accum << ((pdf.find_text page_number: page_number, y: 14.263)[-1] || {})[:string]
end
(expect pgnum_labels.slice 0, 5).to eql [nil, 'ii', '1', '2', '3']
end

it 'should start page numbering after toc in body of book when start at is after-toc and toc macro is used' do
filler = (1..20).map {|it| %(== #{['Filler'] * 20 * ' '} #{it}\n\ncontent) }.join %(\n\n)
pdf = to_pdf <<~END, enable_footer: true, pdf_theme: { page_numbering_start_at: 'after-toc' }, analyze: true
Expand Down

0 comments on commit bf6e3b2

Please sign in to comment.