Skip to content

Commit

Permalink
resolves asciidoctor#236 expand tabs to spaces based on value of tabs…
Browse files Browse the repository at this point in the history
…ize attribute
  • Loading branch information
mojavelinux committed Jun 29, 2015
1 parent 0ca198f commit 675cd9a
Showing 1 changed file with 57 additions and 8 deletions.
65 changes: 57 additions & 8 deletions lib/asciidoctor-pdf/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def self.unicode_char number
# NOTE require_library doesn't support require_relative and we don't modify the load path for this gem
CodeRayRequirePath = ::File.join((::File.dirname __FILE__), 'prawn_ext/coderay_encoder')

AsciidoctorVersion = ::Gem::Version.create ::Asciidoctor::VERSION
AdmonitionIcons = {
caution: { key: 'fa-fire', color: 'BF3400' },
important: { key: 'fa-exclamation-circle', color: 'BF0000' },
Expand All @@ -42,8 +43,10 @@ def self.unicode_char number
warning: { key: 'fa-exclamation-triangle', color: 'BF6900' }
}
Alignments = [:left, :center, :right]
IndentationRx = /^ +/
TabSpaces = ' ' * 4
EOL = "\n"
TAB = "\t"
LeadingSpaceRx = /^ /
LeadingTabsRx = /^\t+/
NoBreakSpace = unicode_char 0x00a0
NarrowSpace = unicode_char 0x2009
NarrowNoBreakSpace = unicode_char 0x202f
Expand Down Expand Up @@ -78,6 +81,9 @@ def initialize backend, opts
#htmlsyntax 'xml'
@list_numbers = []
@list_bullets = []
@capabilities = {
explicit_tabsize: AsciidoctorVersion >= (::Gem::Version.create '1.5.3')
}
end

def convert node, name = nil, opts = {}
Expand Down Expand Up @@ -482,7 +488,8 @@ def convert_quote_or_verse node
if node.context == :quote
convert_content_for_block node
else # verse
layout_prose node.content, preserve: true, normalize: false, align: :left
content = preserve_space node.content, (node.attr 'tabsize')
layout_prose content, normalize: false, align: :left
end
end
theme_font :blockquote_cite do
Expand Down Expand Up @@ -881,7 +888,7 @@ def convert_listing_or_literal node
highlighter = nil
prev_subs = nil
end
source_string = preserve_indentation node.content
source_string = preserve_space node.content, (node.attr 'tabsize')
source_chunks = case highlighter
when 'coderay'
Helpers.require_library CodeRayRequirePath, 'coderay' unless defined? ::Asciidoctor::Prawn::CodeRayEncoder
Expand Down Expand Up @@ -1576,8 +1583,6 @@ def layout_prose string, opts = {}
string = %(<a anchor="#{anchor}">#{string}</a>)
end
end
# preserve leading space using non-breaking space chars
string = preserve_indentation string if opts.delete :preserve
margin_top top_margin
typeset_text string, calc_line_metrics((opts.delete :line_height) || @theme.base_line_height), {
color: @font_color,
Expand Down Expand Up @@ -2133,8 +2138,52 @@ def height_of_typeset_text string, opts = {}
(height_of string, leading: line_metrics.leading, final_gap: line_metrics.final_gap) + line_metrics.padding_top + line_metrics.padding_bottom
end

def preserve_indentation string
string.gsub(IndentationRx) { NoBreakSpace * $&.length }
def preserve_space string, tab_size = nil
# FIXME tab logic shouldn't be necessary once 1.5.3 is out
if string.include? TAB
# Asciidoctor <= 1.5.2 already does tab replacement in some cases, so be consistent about tab size
tab_size = tab_size && @capabilities[:explicit_tabsize] ? tab_size.to_i : 4
full_tab_space = ' ' * tab_size
# NOTE '+' operator is faster than interpolation in this case
lead_tab_space = NoBreakSpace + full_tab_space.chop
result = []
string.each_line {|line|
if line.start_with? TAB
# NOTE '+' operator is faster than interpolation in this case
line.sub!(LeadingTabsRx) { lead_tab_space + (full_tab_space * ($&.length - 1)) }
leading_space = false
elsif line == EOL
result << line
next
else
leading_space = line.start_with? ' '
end

if line.include? TAB
spaces_added = 0
line.gsub!(TAB) {
if (offset = ($~.begin 0) + spaces_added) % tab_size == 0
spaces_added += (tab_size - 1)
full_tab_space
else
unless (spaces = tab_size - offset % tab_size) == 1
spaces_added += (spaces - 1)
end
' ' * spaces
end
}
end

if leading_space
result << NoBreakSpace << line[1..-1]
else
result << line
end
}
result.join
else
string.gsub! LeadingSpaceRx, NoBreakSpace
end
end

# If an id is provided or the node passed as the first argument has an id,
Expand Down

0 comments on commit 675cd9a

Please sign in to comment.