Module: Asciidoctor::PDF::Rhrev::ChangeBars
- Included in:
- Converter
- Defined in:
- lib/asciidoctor/rhrev/change_bars.rb
Overview
Inks a vertical change bar in the page margin next to blocks marked with the current revision (revnumber 1.2 => attribute rhrev1-2). Enabled by the rhrev-change-bars document attribute.
Styling comes from the PDF theme by default (rhrev_change_bars category: color, width, offset, side), overridable per document via the rhrev-change-bars-color/-width/-offset/-side attributes.
Instance Method Summary collapse
-
#arrange_block(node, &block) ⇒ Object
Examples and listings are arranged blocks: the extent yielded here is exact across page breaks.
- #change_bar?(node) ⇒ Boolean
-
#change_bar_settings ⇒ Object
Resolved lazily on first ink: the theme (and @media/@folio_placement) are not loaded yet when init_change_bars runs; upstream convert_document sets them up after rhrev's pre-super initialization.
-
#change_bar_x(pgnum, settings) ⇒ Object
The offset measures the gap between the text edge and the near edge of the bar.
-
#enter_change_bar_section(node) ⇒ Object
A section's bar covers only its own directly-owned content, not any nested child sections/chapters: as soon as a child section begins rendering, close out the bar of every still-open ancestor section right here, at the boundary between the parent's own content and its first child section.
- #exit_change_bar_section(node) ⇒ Object
- #init_change_bars(doc) ⇒ Object
-
#ink_change_bar(from, to) ⇒ Object
Paints the bar page by page; from/to are { page:, cursor: }.
- #ink_change_bar_for_extent(extent) ⇒ Object
- #ink_chapter_title(node, title, opts = {}) ⇒ Object
-
#ink_general_heading(node, title, opts = {}) ⇒ Object
The heading ink methods run after arrange_heading / start_new_chapter have settled the page, so this is the first accurate start position.
-
#ink_part_title(node, title, opts = {}) ⇒ Object
Upstream defines ink_part_title as an alias copy of ink_chapter_title, so it must be overridden separately.
- #record_change_bar_start(node) ⇒ Object
- #take_change_bar_start(node) ⇒ Object
Instance Method Details
#arrange_block(node, &block) ⇒ Object
Examples and listings are arranged blocks: the extent yielded here is exact across page breaks. Tables and images never reach this hook with their own node, so they are handled in the converter overrides instead.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 128 def arrange_block node, &block if @change_bar_attr && !scratch? && (node.context == :example || node.context == :listing) && ( node) super node do |extent| if scratch? # measurement pass: upstream instance_execs this wrapper on the scratch # document, so re-bind the original block to it the same way instance_exec(&block) else block.call extent extent end end else super end end |
#change_bar?(node) ⇒ Boolean
52 53 54 55 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 52 def node @change_bar_attr && node.respond_to?(:attributes) && node.attributes && (node.attributes.key? @change_bar_attr) end |
#change_bar_settings ⇒ Object
Resolved lazily on first ink: the theme (and @media/@folio_placement) are not loaded yet when init_change_bars runs; upstream convert_document sets them up after rhrev's pre-super initialization. Precedence: document attribute > theme key > built-in default.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 37 def @change_bar_settings ||= begin overrides = @change_bar_overrides || {} theme = @theme side = overrides[:side] || theme&. || (@media == 'prepress' ? 'outer' : 'right') { color: (overrides[:color] || theme&. || 'FF0000').to_s.delete_prefix('#').upcase, width: (overrides[:width] || theme&. || 2).to_f, offset: (overrides[:offset] || theme&. || 16).to_f, side: side.to_s, } end end |
#change_bar_x(pgnum, settings) ⇒ Object
The offset measures the gap between the text edge and the near edge of the bar. Sides recto/verso are determined by the physical page number (honoring pdf-folio-placement inversion), matching prepress physical folio placement.
88 89 90 91 92 93 94 95 96 97 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 88 def pgnum, settings case settings[:side] when 'right' on_right = true when 'outer', 'inner' recto = (page_side pgnum, @folio_placement && @folio_placement[:inverted]) == :recto on_right = settings[:side] == 'outer' ? recto : !recto end on_right ? bounds.right + settings[:offset] : bounds.left - settings[:offset] - settings[:width] end |
#enter_change_bar_section(node) ⇒ Object
A section's bar covers only its own directly-owned content, not any nested child sections/chapters: as soon as a child section begins rendering, close out the bar of every still-open ancestor section right here, at the boundary between the parent's own content and its first child section.
70 71 72 73 74 75 76 77 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 70 def node return unless @change_bar_attr @change_bar_section_stack.each do |ancestor| next unless (start_pos = ancestor) start_pos, { page: page_number, cursor: cursor } end @change_bar_section_stack.push node end |
#exit_change_bar_section(node) ⇒ Object
79 80 81 82 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 79 def node return unless @change_bar_attr @change_bar_section_stack.pop end |
#init_change_bars(doc) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 14 def doc @change_bar_attr = nil @change_bar_settings = nil return unless doc.attr? 'rhrev-change-bars' # Without a revnumber there is no "current" revision to match return unless (revnumber = doc.attr 'revnumber') @change_bar_attr = %(#{@revision_prefix}#{revnumber.to_s.tr '.', '-'}) # Capture attribute values only; holding the Document in an ivar here # would leak it into the scratch prototype, which must stay marshalable @change_bar_overrides = { color: (doc.attr 'rhrev-change-bars-color'), width: (doc.attr 'rhrev-change-bars-width'), offset: (doc.attr 'rhrev-change-bars-offset'), side: (doc.attr 'rhrev-change-bars-side'), } @change_bar_starts = {} @change_bar_section_stack = [] end |
#ink_change_bar(from, to) ⇒ Object
Paints the bar page by page; from/to are { page:, cursor: }. Called immediately after the block is rendered, so all spanned pages exist.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 101 def from, to return if scratch? || from.nil? || to.nil? return if to[:page] < from[:page] return if to[:page] == from[:page] && to[:cursor] >= from[:cursor] settings = float do (from[:page]..to[:page]).each do |pgnum| go_to_page pgnum unless page_number == pgnum top = pgnum == from[:page] ? from[:cursor] : bounds.top bottom = pgnum == to[:page] ? to[:cursor] : 0 next if (height = top - bottom) <= 0 bounding_box [( pgnum, settings), top], width: settings[:width], height: height do fill_bounds settings[:color] end end end end |
#ink_change_bar_for_extent(extent) ⇒ Object
119 120 121 122 123 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 119 def extent return unless extent ({ page: extent.from.page, cursor: extent.from.cursor }, { page: extent.to.page, cursor: extent.to.cursor }) end |
#ink_chapter_title(node, title, opts = {}) ⇒ Object
153 154 155 156 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 153 def ink_chapter_title node, title, opts = {} node if @change_bar_attr && !scratch? && ( node) super end |
#ink_general_heading(node, title, opts = {}) ⇒ Object
The heading ink methods run after arrange_heading / start_new_chapter have settled the page, so this is the first accurate start position.
148 149 150 151 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 148 def ink_general_heading node, title, opts = {} node if @change_bar_attr && !scratch? && ( node) super end |
#ink_part_title(node, title, opts = {}) ⇒ Object
Upstream defines ink_part_title as an alias copy of ink_chapter_title, so it must be overridden separately
160 161 162 163 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 160 def ink_part_title node, title, opts = {} node if @change_bar_attr && !scratch? && ( node) super end |
#record_change_bar_start(node) ⇒ Object
57 58 59 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 57 def node @change_bar_starts[node] = { page: page_number, cursor: cursor } end |
#take_change_bar_start(node) ⇒ Object
61 62 63 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 61 def node @change_bar_starts&.delete node end |