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.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 131 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.
91 92 93 94 95 96 97 98 99 100 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 91 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. A section carrying the recursive option keeps its bar open across child boundaries; convert_section closes it after the whole section, children included, has rendered.
72 73 74 75 76 77 78 79 80 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 72 def node return unless @change_bar_attr @change_bar_section_stack.each do |ancestor| next if ancestor.option? 'recursive' 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
82 83 84 85 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 82 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.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 104 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
122 123 124 125 126 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 122 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
156 157 158 159 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 156 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.
151 152 153 154 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 151 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
163 164 165 166 |
# File 'lib/asciidoctor/rhrev/change_bars.rb', line 163 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 |