diff options
| author | Dan Allen <dan.j.allen@gmail.com> | 2022-08-29 01:30:53 -0600 |
|---|---|---|
| committer | Dan Allen <dan.j.allen@gmail.com> | 2022-08-29 02:14:48 -0600 |
| commit | 25c630cb94041bca3892e4dec7f32b136aa99615 (patch) | |
| tree | 5f56bc6f69014306b250f6aaed9e8501df685e79 /lib | |
| parent | e951c44b3a0408a91c94de7790457c92477fe5ce (diff) | |
refactor formatted text transform to simplify how inner space is collapsed
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/asciidoctor/pdf/formatted_text/transform.rb | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/lib/asciidoctor/pdf/formatted_text/transform.rb b/lib/asciidoctor/pdf/formatted_text/transform.rb index f964f4e0..5ca7c1de 100644 --- a/lib/asciidoctor/pdf/formatted_text/transform.rb +++ b/lib/asciidoctor/pdf/formatted_text/transform.rb @@ -6,8 +6,9 @@ module Asciidoctor class Transform include TextTransformer - LF = ?\n + DummyText = ?\u0000 ZeroWidthSpace = ?\u200b + LF = ?\n + ZeroWidthSpace # without trailing character, use of fallback font can change line height CharEntityTable = { amp: '&', apos: ?', gt: '>', lt: '<', nbsp: ?\u00a0, quot: '"' } CharRefRx = /&(?:(#{CharEntityTable.keys.join '|'})|#(?:(\d\d\d{0,4})|x(\h\h\h{0,3})));/ HexColorRx = /^#\h\h\h\h{0,3}$/ @@ -153,6 +154,7 @@ module Asciidoctor def apply parsed, fragments = [], inherited = nil previous_fragment_is_text = false + previous_fragment_end_with_space = false # NOTE: we use each since using inject is slower than a manual loop parsed.each do |node| case node[:type] @@ -160,27 +162,23 @@ module Asciidoctor # case 1: non-void element if node.key? :pcdata # NOTE: skip element if it has no children - if (pcdata = node[:pcdata]).empty? - # QUESTION: should this be handled by the formatter after the transform is complete? - if previous_fragment_is_text && ((previous_fragment_text = fragments[-1][:text]).end_with? ' ') - fragments[-1][:text] = previous_fragment_text.chop - end - else + unless (pcdata = node[:pcdata]).empty? tag_name = node[:name] attributes = node[:attributes] - parent = clone_fragment inherited - fragment = build_fragment parent, tag_name, attributes - if tag_name == :a && fragment[:type] == :indexterm && !attributes[:visible] && - previous_fragment_is_text && ((previous_fragment_text = fragments[-1][:text]).end_with? ' ') - fragments[-1][:text] = previous_fragment_text.chop - end - if (text_transform = fragment.delete :text_transform) - text = (text_chunks = extract_text pcdata).join - text_io = StringIO.new transform_text text, text_transform - restore_text pcdata, text_chunks.each_with_object([]) {|chunk, accum| accum << (text_io.read chunk.length) } + fragment = build_fragment (clone_fragment inherited), tag_name, attributes + if tag_name == :a && pcdata[0][:value] == DummyText && pcdata.length == 1 + fragment[:text] = DummyText + fragments << fragment + else + if (text_transform = fragment.delete :text_transform) + text = (text_chunks = extract_text pcdata).join + text_io = StringIO.new transform_text text, text_transform + restore_text pcdata, text_chunks.each_with_object([]) {|chunk, accum| accum << (text_io.read chunk.length) } + end + # NOTE: decorate child fragments with inherited properties from this element + apply pcdata, fragments, fragment + previous_fragment_end_with_space = false end - # NOTE: decorate child fragments with inherited properties from this element - apply pcdata, fragments, fragment previous_fragment_is_text = false end # case 2: void element @@ -220,11 +218,11 @@ module Asciidoctor fragment[:image_fit] = img_fit end fragments << fragment - previous_fragment_is_text = false + previous_fragment_is_text = previous_fragment_end_with_space = false else # :br text = @merge_adjacent_text_nodes && previous_fragment_is_text ? %(#{fragments.pop[:text]}#{LF}) : LF fragments << (clone_fragment inherited, text: text) - previous_fragment_is_text = true + previous_fragment_is_text = previous_fragment_end_with_space = true end end when :charref @@ -240,10 +238,14 @@ module Asciidoctor text = %(#{fragments.pop[:text]}#{text}) if @merge_adjacent_text_nodes && previous_fragment_is_text fragments << (clone_fragment inherited, text: text) previous_fragment_is_text = true + previous_fragment_end_with_space = false else # :text - text = @merge_adjacent_text_nodes && previous_fragment_is_text ? %(#{fragments.pop[:text]}#{node[:value]}) : node[:value] - fragments << (clone_fragment inherited, text: text) - previous_fragment_is_text = true + unless (text = previous_fragment_end_with_space ? node[:value].lstrip : node[:value]).empty? + text = %(#{fragments.pop[:text]}#{text}) if @merge_adjacent_text_nodes && previous_fragment_is_text + fragments << (clone_fragment inherited, text: text) + previous_fragment_is_text = true + previous_fragment_end_with_space = text.end_with? ' ' + end end end fragments |
