asciidoctor 1.5.8 → 2.0.0.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +162 -17
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -12
- data/README-jp.adoc +11 -12
- data/README-zh_CN.adoc +12 -13
- data/README.adoc +6 -7
- data/asciidoctor.gemspec +19 -24
- data/bin/asciidoctor +5 -4
- data/data/reference/syntax.adoc +283 -0
- data/data/stylesheets/asciidoctor-default.css +56 -52
- data/data/stylesheets/coderay-asciidoctor.css +7 -9
- data/lib/asciidoctor.rb +171 -232
- data/lib/asciidoctor/abstract_block.rb +96 -105
- data/lib/asciidoctor/abstract_node.rb +118 -139
- data/lib/asciidoctor/attribute_list.rb +10 -14
- data/lib/asciidoctor/block.rb +20 -19
- data/lib/asciidoctor/callouts.rb +4 -2
- data/lib/asciidoctor/cli.rb +3 -2
- data/lib/asciidoctor/cli/invoker.rb +14 -21
- data/lib/asciidoctor/cli/options.rb +64 -54
- data/lib/asciidoctor/converter.rb +357 -185
- data/lib/asciidoctor/converter/composite.rb +40 -48
- data/lib/asciidoctor/converter/docbook5.rb +604 -640
- data/lib/asciidoctor/converter/html5.rb +949 -963
- data/lib/asciidoctor/converter/manpage.rb +569 -548
- data/lib/asciidoctor/converter/template.rb +231 -272
- data/lib/asciidoctor/core_ext.rb +5 -18
- data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
- data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
- data/lib/asciidoctor/document.rb +399 -377
- data/lib/asciidoctor/extensions.rb +72 -140
- data/lib/asciidoctor/helpers.rb +122 -83
- data/lib/asciidoctor/inline.rb +5 -1
- data/lib/asciidoctor/list.rb +13 -11
- data/lib/asciidoctor/logging.rb +17 -16
- data/lib/asciidoctor/parser.rb +390 -423
- data/lib/asciidoctor/path_resolver.rb +10 -5
- data/lib/asciidoctor/reader.rb +286 -263
- data/lib/asciidoctor/rouge_ext.rb +39 -0
- data/lib/asciidoctor/section.rb +9 -8
- data/lib/asciidoctor/stylesheets.rb +19 -37
- data/lib/asciidoctor/substitutors.rb +364 -509
- data/lib/asciidoctor/syntax_highlighter.rb +238 -0
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
- data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
- data/lib/asciidoctor/table.rb +73 -66
- data/lib/asciidoctor/timings.rb +4 -2
- data/lib/asciidoctor/version.rb +2 -1
- data/lib/asciidoctor/writer.rb +30 -0
- data/man/asciidoctor.1 +19 -15
- data/man/asciidoctor.adoc +14 -12
- metadata +69 -216
- data/CONTRIBUTING.adoc +0 -185
- data/Gemfile +0 -60
- data/Rakefile +0 -129
- data/bin/asciidoctor-safe +0 -15
- data/features/open_block.feature +0 -92
- data/features/pass_block.feature +0 -66
- data/features/step_definitions.rb +0 -49
- data/features/text_formatting.feature +0 -57
- data/features/xref.feature +0 -1039
- data/lib/asciidoctor/converter/base.rb +0 -59
- data/lib/asciidoctor/converter/docbook45.rb +0 -93
- data/lib/asciidoctor/converter/factory.rb +0 -226
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
- data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
- data/test/api_test.rb +0 -1240
- data/test/attribute_list_test.rb +0 -242
- data/test/attributes_test.rb +0 -1623
- data/test/blocks_test.rb +0 -3870
- data/test/converter_test.rb +0 -470
- data/test/document_test.rb +0 -1853
- data/test/extensions_test.rb +0 -1560
- data/test/fixtures/asciidoc_index.txt +0 -521
- data/test/fixtures/basic-docinfo-footer.html +0 -6
- data/test/fixtures/basic-docinfo-footer.xml +0 -8
- data/test/fixtures/basic-docinfo.html +0 -1
- data/test/fixtures/basic-docinfo.xml +0 -4
- data/test/fixtures/basic.asciidoc +0 -5
- data/test/fixtures/chapter-a.adoc +0 -3
- data/test/fixtures/child-include.adoc +0 -5
- data/test/fixtures/circle.svg +0 -9
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
- data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
- data/test/fixtures/docinfo-footer.html +0 -1
- data/test/fixtures/docinfo-footer.xml +0 -9
- data/test/fixtures/docinfo.html +0 -1
- data/test/fixtures/docinfo.xml +0 -3
- data/test/fixtures/doctime-localtime.adoc +0 -2
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/file-with-missing-include.adoc +0 -1
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -69
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.jsx +0 -8
- data/test/fixtures/include-file.ml +0 -3
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/lists.adoc +0 -96
- data/test/fixtures/master.adoc +0 -5
- data/test/fixtures/mismatched-end-tag.adoc +0 -7
- data/test/fixtures/other-chapters.adoc +0 -11
- data/test/fixtures/outer-include.adoc +0 -5
- data/test/fixtures/parent-include-restricted.adoc +0 -5
- data/test/fixtures/parent-include.adoc +0 -5
- data/test/fixtures/sample.asciidoc +0 -30
- data/test/fixtures/section-a.adoc +0 -4
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subdir/index.adoc +0 -3
- data/test/fixtures/subdir/inner-include.adoc +0 -3
- data/test/fixtures/subdir/middle-include.adoc +0 -5
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -6
- data/test/fixtures/tagged-class-enclosed.rb +0 -25
- data/test/fixtures/tagged-class.rb +0 -23
- data/test/fixtures/tip.gif +0 -0
- data/test/fixtures/unclosed-tag.adoc +0 -3
- data/test/fixtures/unexpected-end-tag.adoc +0 -4
- data/test/invoker_test.rb +0 -745
- data/test/links_test.rb +0 -855
- data/test/lists_test.rb +0 -5151
- data/test/logger_test.rb +0 -211
- data/test/manpage_test.rb +0 -660
- data/test/options_test.rb +0 -262
- data/test/paragraphs_test.rb +0 -562
- data/test/parser_test.rb +0 -742
- data/test/paths_test.rb +0 -395
- data/test/preamble_test.rb +0 -173
- data/test/reader_test.rb +0 -2161
- data/test/sections_test.rb +0 -3575
- data/test/substitutions_test.rb +0 -2066
- data/test/tables_test.rb +0 -2036
- data/test/test_helper.rb +0 -447
- data/test/text_test.rb +0 -309
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
class SyntaxHighlighter::RougeAdapter < SyntaxHighlighter::Base
|
4
|
+
register_for 'rouge'
|
5
|
+
|
6
|
+
def initialize *args
|
7
|
+
super
|
8
|
+
@requires_stylesheet = nil
|
9
|
+
@style = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def highlight?
|
13
|
+
library_available?
|
14
|
+
end
|
15
|
+
|
16
|
+
def highlight node, source, lang, opts
|
17
|
+
lexer = (::Rouge::Lexer.find_fancy lang) || ::Rouge::Lexers::PlainText
|
18
|
+
lexer_opts = lexer.tag == 'php' && !(node.option? 'mixed') ? { start_inline: true } : {}
|
19
|
+
@style ||= (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE
|
20
|
+
if opts[:css_mode] == :class
|
21
|
+
@requires_stylesheet = true
|
22
|
+
formatter = ::Rouge::Formatters::HTML.new @style
|
23
|
+
else
|
24
|
+
formatter = ::Rouge::Formatters::HTMLInline.new @style
|
25
|
+
end
|
26
|
+
if (highlight_lines = opts[:highlight_lines])
|
27
|
+
formatter = RougeExt::Formatters::HTMLLineHighlighter.new formatter, lines: highlight_lines
|
28
|
+
end
|
29
|
+
if opts[:number_lines]
|
30
|
+
formatter = RougeExt::Formatters::HTMLTable.new formatter, start_line: opts[:start_line_number]
|
31
|
+
if opts[:callouts]
|
32
|
+
return [(highlighted = formatter.format lexer.lex source, lexer_opts), (idx = highlighted.index CodeCellStartTagCs) ? idx + CodeCellStartTagCs.length : nil]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
formatter.format lexer.lex source, lexer_opts
|
36
|
+
end
|
37
|
+
|
38
|
+
def format node, lang, opts
|
39
|
+
if (query_idx = lang.index '?')
|
40
|
+
lang = lang.slice 0, query_idx
|
41
|
+
end
|
42
|
+
if opts[:css_mode] != :class && (@style = (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE) &&
|
43
|
+
(pre_style_attr_val = base_style @style)
|
44
|
+
opts[:transform] = proc {|pre| pre['style'] = pre_style_attr_val }
|
45
|
+
end
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def docinfo? location
|
50
|
+
@requires_stylesheet && location == :footer
|
51
|
+
end
|
52
|
+
|
53
|
+
def docinfo location, doc, opts
|
54
|
+
if opts[:linkcss]
|
55
|
+
%(<link rel="stylesheet" href="#{doc.normalize_web_path (stylesheet_basename @style), (doc.attr 'stylesdir', ''), false}"#{opts[:self_closing_tag_slash]}>)
|
56
|
+
else
|
57
|
+
%(<style>
|
58
|
+
#{read_stylesheet @style}
|
59
|
+
</style>)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def write_stylesheet? doc
|
64
|
+
@requires_stylesheet
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_stylesheet doc, to_dir
|
68
|
+
::File.write (::File.join to_dir, (stylesheet_basename @style)), (read_stylesheet @style), mode: FILE_WRITE_MODE
|
69
|
+
end
|
70
|
+
|
71
|
+
module Loader
|
72
|
+
private
|
73
|
+
|
74
|
+
def library_available?
|
75
|
+
(@@library_status ||= load_library) == :loaded ? true : nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_library
|
79
|
+
(defined? RougeExt) ? :loaded : (Helpers.require_library %(#{::File.dirname __dir__}/rouge_ext), 'rouge', :warn).nil? ? :unavailable : :loaded
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module Styles
|
84
|
+
include Loader
|
85
|
+
|
86
|
+
def read_stylesheet style
|
87
|
+
library_available? ? @@stylesheet_cache[style || DEFAULT_STYLE] : '/* Rouge CSS disabled because Rouge is not available. */'
|
88
|
+
end
|
89
|
+
|
90
|
+
def stylesheet_basename style
|
91
|
+
%(rouge-#{style || DEFAULT_STYLE}.css)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def base_style style
|
97
|
+
library_available? ? @@base_style_cache[style || DEFAULT_STYLE] : nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def style_available? style
|
101
|
+
(::Rouge::Theme.find style) && style
|
102
|
+
end
|
103
|
+
|
104
|
+
@@base_style_cache = ::Hash.new do |cache, key|
|
105
|
+
base_style = (theme = ::Rouge::Theme.find key).base_style
|
106
|
+
(val = base_style[:fg]) && ((style ||= []) << %(color: #{theme.palette val}))
|
107
|
+
(val = base_style[:bg]) && ((style ||= []) << %(background-color: #{theme.palette val}))
|
108
|
+
@@base_style_cache = cache.merge key => (resolved_base_style = style && (style.join ';'))
|
109
|
+
resolved_base_style
|
110
|
+
end
|
111
|
+
@@stylesheet_cache = ::Hash.new do |cache, key|
|
112
|
+
@@stylesheet_cache = cache.merge key => (stylesheet = ((::Rouge::Theme.find key).render scope: BASE_SELECTOR))
|
113
|
+
stylesheet
|
114
|
+
end
|
115
|
+
|
116
|
+
DEFAULT_STYLE = 'github'
|
117
|
+
BASE_SELECTOR = 'pre.rouge'
|
118
|
+
|
119
|
+
private_constant :BASE_SELECTOR
|
120
|
+
end
|
121
|
+
|
122
|
+
extend Styles # exports static methods
|
123
|
+
include Loader, Styles # adds methods to instance
|
124
|
+
|
125
|
+
CodeCellStartTagCs = '<td class="code">'
|
126
|
+
|
127
|
+
private_constant :CodeCellStartTagCs
|
128
|
+
end
|
129
|
+
end
|
data/lib/asciidoctor/table.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module Asciidoctor
|
3
3
|
# Public: Methods and constants for managing AsciiDoc table content in a document.
|
4
4
|
# It supports all three of AsciiDoc's table formats: psv, dsv and csv.
|
5
5
|
class Table < AbstractBlock
|
6
|
-
#
|
7
|
-
|
6
|
+
# precision of column widths
|
7
|
+
DEFAULT_PRECISION = 4
|
8
8
|
|
9
9
|
# Public: A data object that encapsulates the collection of rows (head, foot, body) for a table
|
10
10
|
class Rows
|
@@ -18,7 +18,7 @@ class Table < AbstractBlock
|
|
18
18
|
|
19
19
|
alias [] send
|
20
20
|
|
21
|
-
# Public:
|
21
|
+
# Public: Retrieve the rows grouped by section as a nested Array.
|
22
22
|
#
|
23
23
|
# Creates a 2-dimensional array of two element entries. The first element
|
24
24
|
# is the section name as a symbol. The second element is the Array of rows
|
@@ -28,6 +28,16 @@ class Table < AbstractBlock
|
|
28
28
|
def by_section
|
29
29
|
[[:head, @head], [:body, @body], [:foot, @foot]]
|
30
30
|
end
|
31
|
+
|
32
|
+
# Public: Retrieve the rows as a Hash.
|
33
|
+
#
|
34
|
+
# The keys are the names of the section groups and the values are the Array of rows in that section.
|
35
|
+
# The keys are in document order (head, foot, body).
|
36
|
+
#
|
37
|
+
# Returns a Hash of rows grouped by section.
|
38
|
+
def to_h
|
39
|
+
{ head: @head, body: @body, foot: @foot }
|
40
|
+
end
|
31
41
|
end
|
32
42
|
|
33
43
|
# Public: Get/Set the columns for this table
|
@@ -48,7 +58,7 @@ class Table < AbstractBlock
|
|
48
58
|
@rows = Rows.new
|
49
59
|
@columns = []
|
50
60
|
|
51
|
-
@has_header_option = attributes
|
61
|
+
@has_header_option = attributes['header-option'] ? true : false
|
52
62
|
|
53
63
|
# smells like we need a utility method here
|
54
64
|
# to resolve an integer width from potential bogus input
|
@@ -67,7 +77,7 @@ class Table < AbstractBlock
|
|
67
77
|
((@attributes['tablepcwidth'].to_f / 100) * @document.attributes['pagewidth']).round
|
68
78
|
end
|
69
79
|
|
70
|
-
attributes['orientation'] = 'landscape' if attributes
|
80
|
+
attributes['orientation'] = 'landscape' if attributes['rotate-option']
|
71
81
|
end
|
72
82
|
|
73
83
|
# Internal: Returns whether the current row being processed is
|
@@ -111,7 +121,7 @@ class Table < AbstractBlock
|
|
111
121
|
#
|
112
122
|
# returns nothing
|
113
123
|
def assign_column_widths width_base = nil, autowidth_cols = nil
|
114
|
-
|
124
|
+
precision = DEFAULT_PRECISION
|
115
125
|
total_width = col_pcwidth = 0
|
116
126
|
|
117
127
|
if width_base
|
@@ -120,32 +130,22 @@ class Table < AbstractBlock
|
|
120
130
|
autowidth = 0
|
121
131
|
logger.warn %(total column width must not exceed 100% when using autowidth columns; got #{width_base}%)
|
122
132
|
else
|
123
|
-
autowidth = ((100.0 - width_base) / autowidth_cols.size
|
133
|
+
autowidth = ((100.0 - width_base) / autowidth_cols.size).truncate precision
|
124
134
|
autowidth = autowidth.to_i if autowidth.to_i == autowidth
|
125
135
|
width_base = 100
|
126
136
|
end
|
127
137
|
autowidth_attrs = { 'width' => autowidth, 'autowidth-option' => '' }
|
128
138
|
autowidth_cols.each {|col| col.update_attributes autowidth_attrs }
|
129
139
|
end
|
130
|
-
@columns.each {|col| total_width += (col_pcwidth = col.assign_width nil, width_base,
|
140
|
+
@columns.each {|col| total_width += (col_pcwidth = col.assign_width nil, width_base, precision) }
|
131
141
|
else
|
132
|
-
col_pcwidth = (
|
133
|
-
# or...
|
134
|
-
#col_pcwidth = (100.0 / @columns.size).truncate 4
|
142
|
+
col_pcwidth = (100.0 / @columns.size).truncate precision
|
135
143
|
col_pcwidth = col_pcwidth.to_i if col_pcwidth.to_i == col_pcwidth
|
136
|
-
@columns.each {|col| total_width += col.assign_width col_pcwidth }
|
144
|
+
@columns.each {|col| total_width += col.assign_width col_pcwidth, nil, precision }
|
137
145
|
end
|
138
146
|
|
139
147
|
# donate balance, if any, to final column (using half up rounding)
|
140
|
-
unless total_width == 100
|
141
|
-
@columns[-1].assign_width(((100 - total_width + col_pcwidth) * pf).round / pf)
|
142
|
-
# or (manual half up rounding)...
|
143
|
-
#numerator = (raw_numerator = (100 - total_width + col_pcwidth) * pf).to_i
|
144
|
-
#numerator += 1 if raw_numerator >= numerator + 0.5
|
145
|
-
#@columns[-1].assign_width numerator / pf
|
146
|
-
# or...
|
147
|
-
#@columns[-1].assign_width((100 - total_width + col_pcwidth).round 4)
|
148
|
-
end
|
148
|
+
@columns[-1].assign_width(((100 - total_width + col_pcwidth).round precision), nil, precision) unless total_width == 100
|
149
149
|
|
150
150
|
nil
|
151
151
|
end
|
@@ -169,7 +169,7 @@ class Table < AbstractBlock
|
|
169
169
|
@rows.head = [head]
|
170
170
|
end
|
171
171
|
|
172
|
-
if num_body_rows > 0 && attrs
|
172
|
+
if num_body_rows > 0 && attrs['footer-option']
|
173
173
|
@rows.foot = [@rows.body.pop]
|
174
174
|
end
|
175
175
|
|
@@ -180,11 +180,11 @@ end
|
|
180
180
|
# Public: Methods to manage the columns of an AsciiDoc table. In particular, it
|
181
181
|
# keeps track of the column specs
|
182
182
|
class Table::Column < AbstractNode
|
183
|
-
# Public: Get/Set the Symbol
|
183
|
+
# Public: Get/Set the style Symbol for this column.
|
184
184
|
attr_accessor :style
|
185
185
|
|
186
186
|
def initialize table, index, attributes = {}
|
187
|
-
super table, :
|
187
|
+
super table, :table_column
|
188
188
|
@style = attributes['style']
|
189
189
|
attributes['colnumber'] = index + 1
|
190
190
|
attributes['width'] ||= 1
|
@@ -201,11 +201,9 @@ class Table::Column < AbstractNode
|
|
201
201
|
# This method assigns the colpcwidth and colabswidth attributes.
|
202
202
|
#
|
203
203
|
# returns the resolved colpcwidth value
|
204
|
-
def assign_width col_pcwidth, width_base
|
204
|
+
def assign_width col_pcwidth, width_base, precision
|
205
205
|
if width_base
|
206
|
-
col_pcwidth = (
|
207
|
-
# or...
|
208
|
-
#col_pcwidth = (@attributes['width'].to_f * 100.0 / width_base).truncate 4
|
206
|
+
col_pcwidth = (@attributes['width'].to_f * 100.0 / width_base).truncate precision
|
209
207
|
col_pcwidth = col_pcwidth.to_i if col_pcwidth.to_i == col_pcwidth
|
210
208
|
end
|
211
209
|
@attributes['colpcwidth'] = col_pcwidth
|
@@ -215,18 +213,19 @@ class Table::Column < AbstractNode
|
|
215
213
|
end
|
216
214
|
col_pcwidth
|
217
215
|
end
|
218
|
-
end
|
219
216
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
attr_reader :source_location
|
217
|
+
def block?
|
218
|
+
false
|
219
|
+
end
|
224
220
|
|
225
|
-
|
226
|
-
|
221
|
+
def inline?
|
222
|
+
false
|
223
|
+
end
|
224
|
+
end
|
227
225
|
|
228
|
-
|
229
|
-
|
226
|
+
# Public: Methods for managing the a cell in an AsciiDoc table.
|
227
|
+
class Table::Cell < AbstractBlock
|
228
|
+
DOUBLE_LF = LF * 2
|
230
229
|
|
231
230
|
# Public: An Integer of the number of columns this cell will span (default: nil)
|
232
231
|
attr_accessor :colspan
|
@@ -237,11 +236,11 @@ class Table::Cell < AbstractNode
|
|
237
236
|
# Public: An alias to the parent block (which is always a Column)
|
238
237
|
alias column parent
|
239
238
|
|
240
|
-
#
|
239
|
+
# Internal: Returns the nested Document in an AsciiDoc table cell (only set when style is :asciidoc)
|
241
240
|
attr_reader :inner_document
|
242
241
|
|
243
242
|
def initialize column, cell_text, attributes = {}, opts = {}
|
244
|
-
super column, :
|
243
|
+
super column, :table_cell
|
245
244
|
@source_location = opts[:cursor].dup if @document.sourcemap
|
246
245
|
if column
|
247
246
|
cell_style = column.attributes['style'] unless (in_header_row = column.table.header_row?)
|
@@ -269,7 +268,8 @@ class Table::Cell < AbstractNode
|
|
269
268
|
else
|
270
269
|
cell_text = cell_text.lstrip
|
271
270
|
end
|
272
|
-
elsif
|
271
|
+
elsif cell_style == :literal
|
272
|
+
literal = true
|
273
273
|
cell_text = cell_text.rstrip
|
274
274
|
# QUESTION should we use same logic as :asciidoc cell? strip leading space if text doesn't start with newline?
|
275
275
|
cell_text = cell_text.slice 1, cell_text.length while cell_text.start_with? LF
|
@@ -303,15 +303,17 @@ class Table::Cell < AbstractNode
|
|
303
303
|
inner_document_lines.unshift(*preprocessed_lines) unless preprocessed_lines.empty?
|
304
304
|
end
|
305
305
|
end unless inner_document_lines.empty?
|
306
|
-
@inner_document = Document.new(inner_document_lines, :
|
306
|
+
@inner_document = Document.new(inner_document_lines, header_footer: false, parent: @document, cursor: inner_document_cursor)
|
307
307
|
@document.attributes['doctitle'] = parent_doctitle unless parent_doctitle.nil?
|
308
308
|
@subs = nil
|
309
309
|
elsif literal
|
310
|
+
@content_model = :verbatim
|
310
311
|
@subs = BASIC_SUBS
|
311
312
|
else
|
312
313
|
if normal_psv && (cell_text.start_with? '[[') && LeadingInlineAnchorRx =~ cell_text
|
313
314
|
Parser.catalog_inline_anchor $1, $2, self, opts[:cursor], @document
|
314
315
|
end
|
316
|
+
@content_model = :simple
|
315
317
|
@subs = NORMAL_SUBS
|
316
318
|
end
|
317
319
|
@text = cell_text
|
@@ -345,12 +347,18 @@ class Table::Cell < AbstractNode
|
|
345
347
|
#
|
346
348
|
# Returns the converted String for this Cell
|
347
349
|
def content
|
348
|
-
if @style == :asciidoc
|
350
|
+
if (cell_style = @style) == :asciidoc
|
349
351
|
@inner_document.convert
|
350
|
-
|
351
|
-
text.split
|
352
|
-
|
352
|
+
elsif @text.include? DOUBLE_LF
|
353
|
+
(text.split BlankLineRx).map do |para|
|
354
|
+
cell_style && cell_style != :header ? (Inline.new parent, :quoted, para, type: cell_style).convert : para
|
353
355
|
end
|
356
|
+
elsif (subbed_text = text).empty?
|
357
|
+
[]
|
358
|
+
elsif cell_style && cell_style != :header
|
359
|
+
[(Inline.new parent, :quoted, subbed_text, type: cell_style).convert]
|
360
|
+
else
|
361
|
+
[subbed_text]
|
354
362
|
end
|
355
363
|
end
|
356
364
|
|
@@ -388,8 +396,8 @@ class Table::ParserContext
|
|
388
396
|
'psv' => ['|', /\|/],
|
389
397
|
'csv' => [',', /,/],
|
390
398
|
'dsv' => [':', /:/],
|
391
|
-
'tsv' => [
|
392
|
-
'!sv' => ['!', /!/]
|
399
|
+
'tsv' => [?\t, /\t/],
|
400
|
+
'!sv' => ['!', /!/],
|
393
401
|
}
|
394
402
|
|
395
403
|
# Public: The Table currently being parsed
|
@@ -427,7 +435,7 @@ class Table::ParserContext
|
|
427
435
|
xsv = '!sv'
|
428
436
|
end
|
429
437
|
else
|
430
|
-
logger.error message_with_context %(illegal table format: #{xsv}), :
|
438
|
+
logger.error message_with_context %(illegal table format: #{xsv}), source_location: reader.cursor_at_prev_line
|
431
439
|
@format, xsv = 'psv', (table.document.nested? ? '!sv' : 'psv')
|
432
440
|
end
|
433
441
|
else
|
@@ -436,15 +444,15 @@ class Table::ParserContext
|
|
436
444
|
|
437
445
|
if attributes.key? 'separator'
|
438
446
|
if (sep = attributes['separator']).nil_or_empty?
|
439
|
-
@delimiter, @
|
447
|
+
@delimiter, @delimiter_rx = DELIMITERS[xsv]
|
440
448
|
# QUESTION should we support any other escape codes or multiple tabs?
|
441
449
|
elsif sep == '\t'
|
442
|
-
@delimiter, @
|
450
|
+
@delimiter, @delimiter_rx = DELIMITERS['tsv']
|
443
451
|
else
|
444
|
-
@delimiter, @
|
452
|
+
@delimiter, @delimiter_rx = sep, /#{::Regexp.escape sep}/
|
445
453
|
end
|
446
454
|
else
|
447
|
-
@delimiter, @
|
455
|
+
@delimiter, @delimiter_rx = DELIMITERS[xsv]
|
448
456
|
end
|
449
457
|
|
450
458
|
@colcount = table.columns.empty? ? -1 : table.columns.size
|
@@ -470,7 +478,7 @@ class Table::ParserContext
|
|
470
478
|
#
|
471
479
|
# returns Regexp MatchData if the line contains the delimiter, false otherwise
|
472
480
|
def match_delimiter(line)
|
473
|
-
@
|
481
|
+
@delimiter_rx.match(line)
|
474
482
|
end
|
475
483
|
|
476
484
|
# Public: Skip past the matched delimiter because it's inside quoted text.
|
@@ -582,7 +590,7 @@ class Table::ParserContext
|
|
582
590
|
if (cellspec = take_cellspec)
|
583
591
|
repeat = cellspec.delete('repeatcol') || 1
|
584
592
|
else
|
585
|
-
logger.error message_with_context 'table missing leading separator; recovering automatically', :
|
593
|
+
logger.error message_with_context 'table missing leading separator; recovering automatically', source_location: Reader::Cursor.new(*@start_cursor_data)
|
586
594
|
cellspec = {}
|
587
595
|
repeat = 1
|
588
596
|
end
|
@@ -599,7 +607,7 @@ class Table::ParserContext
|
|
599
607
|
# trim whitespace and collapse escaped quotes
|
600
608
|
cell_text = cell_text.strip.squeeze('"')
|
601
609
|
else
|
602
|
-
logger.error message_with_context 'unclosed quote in CSV data; setting cell to empty', :
|
610
|
+
logger.error message_with_context 'unclosed quote in CSV data; setting cell to empty', source_location: @reader.cursor_at_prev_line
|
603
611
|
cell_text = ''
|
604
612
|
end
|
605
613
|
else
|
@@ -622,12 +630,12 @@ class Table::ParserContext
|
|
622
630
|
else
|
623
631
|
# QUESTION is this right for cells that span columns?
|
624
632
|
unless (column = @table.columns[@current_row.size])
|
625
|
-
logger.error message_with_context 'dropping cell because it exceeds specified number of columns', :
|
633
|
+
logger.error message_with_context 'dropping cell because it exceeds specified number of columns', source_location: @reader.cursor_before_mark
|
626
634
|
return
|
627
635
|
end
|
628
636
|
end
|
629
637
|
|
630
|
-
cell = Table::Cell.new(column, cell_text, cellspec, :
|
638
|
+
cell = Table::Cell.new(column, cell_text, cellspec, cursor: @reader.cursor_before_mark)
|
631
639
|
@reader.mark
|
632
640
|
unless !cell.rowspan || cell.rowspan == 1
|
633
641
|
activate_rowspan(cell.rowspan, (cell.colspan || 1))
|
@@ -642,7 +650,9 @@ class Table::ParserContext
|
|
642
650
|
nil
|
643
651
|
end
|
644
652
|
|
645
|
-
|
653
|
+
private
|
654
|
+
|
655
|
+
# Internal: Close the row by adding it to the Table and resetting the row
|
646
656
|
# Array and counter variables.
|
647
657
|
#
|
648
658
|
# returns nothing
|
@@ -658,24 +668,21 @@ class Table::ParserContext
|
|
658
668
|
nil
|
659
669
|
end
|
660
670
|
|
661
|
-
#
|
671
|
+
# Internal: Activate a rowspan. The rowspan Array is consulted when
|
662
672
|
# determining the effective number of cells in the current row.
|
663
673
|
#
|
664
674
|
# returns nothing
|
665
675
|
def activate_rowspan(rowspan, colspan)
|
666
|
-
1.upto(rowspan - 1)
|
667
|
-
# longhand assignment used for Opal compatibility
|
668
|
-
@active_rowspans[i] = (@active_rowspans[i] || 0) + colspan
|
669
|
-
}
|
676
|
+
1.upto(rowspan - 1) {|i| @active_rowspans[i] = (@active_rowspans[i] || 0) + colspan }
|
670
677
|
nil
|
671
678
|
end
|
672
679
|
|
673
|
-
#
|
680
|
+
# Internal: Check whether we've met the number of effective columns for the current row.
|
674
681
|
def end_of_row?
|
675
682
|
@colcount == -1 || effective_column_visits == @colcount
|
676
683
|
end
|
677
684
|
|
678
|
-
#
|
685
|
+
# Internal: Calculate the effective column visits, which consists of the number of
|
679
686
|
# cells plus any active rowspans.
|
680
687
|
def effective_column_visits
|
681
688
|
@column_visits + @active_rowspans[0]
|