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
data/test/test_helper.rb
DELETED
@@ -1,447 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
ASCIIDOCTOR_TEST_DIR = File.expand_path File.dirname __FILE__
|
3
|
-
ASCIIDOCTOR_PROJECT_DIR = File.dirname ASCIIDOCTOR_TEST_DIR
|
4
|
-
ASCIIDOCTOR_LIB_DIR = ENV['ASCIIDOCTOR_LIB_DIR'] || File.join(ASCIIDOCTOR_PROJECT_DIR, 'lib')
|
5
|
-
Dir.chdir ASCIIDOCTOR_PROJECT_DIR
|
6
|
-
|
7
|
-
if RUBY_VERSION < '1.9'
|
8
|
-
require 'rubygems'
|
9
|
-
end
|
10
|
-
|
11
|
-
require 'simplecov' if ENV['COVERAGE'] == 'true'
|
12
|
-
|
13
|
-
require File.join(ASCIIDOCTOR_LIB_DIR, 'asciidoctor')
|
14
|
-
|
15
|
-
require 'socket'
|
16
|
-
require 'nokogiri'
|
17
|
-
require 'tempfile'
|
18
|
-
require 'tmpdir'
|
19
|
-
|
20
|
-
autoload :FileUtils, 'fileutils'
|
21
|
-
autoload :Pathname, 'pathname'
|
22
|
-
autoload :Open3, 'open3'
|
23
|
-
|
24
|
-
RE_XMLNS_ATTRIBUTE = / xmlns="[^"]+"/
|
25
|
-
RE_DOCTYPE = /\s*<!DOCTYPE (.*)/
|
26
|
-
|
27
|
-
require 'minitest/autorun'
|
28
|
-
|
29
|
-
# Minitest 4 doesn't have Minitest::Test
|
30
|
-
Minitest::Test = MiniTest::Unit::TestCase unless defined? Minitest::Test
|
31
|
-
|
32
|
-
class Minitest::Test
|
33
|
-
def windows?
|
34
|
-
RbConfig::CONFIG['host_os'] =~ /win|ming/
|
35
|
-
end
|
36
|
-
|
37
|
-
def disk_root
|
38
|
-
%(#{windows? ? ASCIIDOCTOR_PROJECT_DIR.split('/')[0] : ''}/)
|
39
|
-
end
|
40
|
-
|
41
|
-
def empty_document options = {}
|
42
|
-
if options[:parse]
|
43
|
-
(Asciidoctor::Document.new [], options).parse
|
44
|
-
else
|
45
|
-
Asciidoctor::Document.new [], options
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def empty_safe_document options = {}
|
50
|
-
options[:safe] = :safe
|
51
|
-
Asciidoctor::Document.new [], options
|
52
|
-
end
|
53
|
-
|
54
|
-
def sample_doc_path(name)
|
55
|
-
name = name.to_s
|
56
|
-
unless name.include?('.')
|
57
|
-
['asciidoc', 'txt'].each do |ext|
|
58
|
-
if File.exist?(fixture_path("#{name}.#{ext}"))
|
59
|
-
name = "#{name}.#{ext}"
|
60
|
-
break
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
fixture_path(name)
|
65
|
-
end
|
66
|
-
|
67
|
-
def testdir
|
68
|
-
ASCIIDOCTOR_TEST_DIR
|
69
|
-
end
|
70
|
-
|
71
|
-
def fixturedir
|
72
|
-
File.join testdir, 'fixtures'
|
73
|
-
end
|
74
|
-
|
75
|
-
def fixture_path name
|
76
|
-
File.join fixturedir, name
|
77
|
-
end
|
78
|
-
|
79
|
-
def example_document(name, opts = {})
|
80
|
-
document_from_string IO.read(sample_doc_path(name)), opts
|
81
|
-
end
|
82
|
-
|
83
|
-
def xmlnodes_at_css(css, content, count = nil)
|
84
|
-
xmlnodes_at_path(:css, css, content, count)
|
85
|
-
end
|
86
|
-
|
87
|
-
def xmlnodes_at_xpath(xpath, content, count = nil)
|
88
|
-
xmlnodes_at_path(:xpath, xpath, content, count)
|
89
|
-
end
|
90
|
-
|
91
|
-
def xmlnodes_at_path(type, path, content, count = nil)
|
92
|
-
doc = xmldoc_from_string content
|
93
|
-
case type
|
94
|
-
when :xpath
|
95
|
-
namespaces = doc.respond_to?(:root) ? doc.root.namespaces : {}
|
96
|
-
results = doc.xpath("#{path.sub('/', './')}", namespaces)
|
97
|
-
when :css
|
98
|
-
results = doc.css(path)
|
99
|
-
end
|
100
|
-
count == 1 ? results.first : results
|
101
|
-
end
|
102
|
-
|
103
|
-
# Generate an xpath attribute matcher that matches a name in the class attribute
|
104
|
-
def contains_class(name)
|
105
|
-
%(contains(concat(' ', normalize-space(@class), ' '), ' #{name} '))
|
106
|
-
end
|
107
|
-
|
108
|
-
def assert_css(css, content, count = nil)
|
109
|
-
assert_path(:css, css, content, count)
|
110
|
-
end
|
111
|
-
|
112
|
-
def assert_xpath(xpath, content, count = nil)
|
113
|
-
assert_path(:xpath, xpath, content, count)
|
114
|
-
end
|
115
|
-
|
116
|
-
def assert_path(type, path, content, count = nil)
|
117
|
-
case type
|
118
|
-
when :xpath
|
119
|
-
type_name = 'XPath'
|
120
|
-
when :css
|
121
|
-
type_name = 'CSS'
|
122
|
-
end
|
123
|
-
|
124
|
-
results = xmlnodes_at_path type, path, content
|
125
|
-
|
126
|
-
if (count == true || count == false)
|
127
|
-
if (count != results)
|
128
|
-
flunk "#{type_name} #{path} yielded #{results} rather than #{count} for:\n#{content}"
|
129
|
-
else
|
130
|
-
assert true
|
131
|
-
end
|
132
|
-
elsif (count && results.size != count)
|
133
|
-
flunk "#{type_name} #{path} yielded #{results.size} elements rather than #{count} for:\n#{content}"
|
134
|
-
elsif (count.nil? && results.empty?)
|
135
|
-
flunk "#{type_name} #{path} not found in:\n#{content}"
|
136
|
-
else
|
137
|
-
assert true
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def assert_message logger, severity, expected_message, kind = String, idx = nil
|
142
|
-
unless idx
|
143
|
-
assert_equal 1, logger.messages.size
|
144
|
-
idx = 0
|
145
|
-
end
|
146
|
-
message = logger.messages[idx]
|
147
|
-
assert_equal severity, message[:severity]
|
148
|
-
assert_kind_of kind, message[:message]
|
149
|
-
if kind == String
|
150
|
-
actual_message = message[:message]
|
151
|
-
else
|
152
|
-
refute_nil message[:message][:source_location]
|
153
|
-
actual_message = message[:message].inspect
|
154
|
-
end
|
155
|
-
if expected_message.start_with? '~'
|
156
|
-
assert_includes actual_message, expected_message[1..-1]
|
157
|
-
else
|
158
|
-
assert_equal expected_message, actual_message
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def assert_messages logger, expected_messages
|
163
|
-
assert_equal expected_messages.size, logger.messages.size
|
164
|
-
expected_messages.each_with_index do |expected_message_details, idx|
|
165
|
-
severity, expected_message, kind = expected_message_details
|
166
|
-
assert_message logger, severity, expected_message, (kind || String), idx
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def xmldoc_from_string(content)
|
171
|
-
if content.match(RE_XMLNS_ATTRIBUTE)
|
172
|
-
Nokogiri::XML::Document.parse(content)
|
173
|
-
elsif !(doctype_match = content.match(RE_DOCTYPE))
|
174
|
-
Nokogiri::HTML::DocumentFragment.parse(content)
|
175
|
-
elsif doctype_match[1].start_with? 'html'
|
176
|
-
Nokogiri::HTML::Document.parse(content)
|
177
|
-
else
|
178
|
-
Nokogiri::XML::Document.parse(content)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def document_from_string(src, opts = {})
|
183
|
-
assign_default_test_options opts
|
184
|
-
if opts[:parse]
|
185
|
-
(Asciidoctor::Document.new src.lines.entries, opts).parse
|
186
|
-
else
|
187
|
-
Asciidoctor::Document.new src.lines.entries, opts
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def block_from_string(src, opts = {})
|
192
|
-
opts[:header_footer] = false
|
193
|
-
doc = document_from_string src, opts
|
194
|
-
doc.blocks.first
|
195
|
-
end
|
196
|
-
|
197
|
-
def convert_string(src, opts = {})
|
198
|
-
keep_namespaces = opts.delete(:keep_namespaces)
|
199
|
-
if keep_namespaces
|
200
|
-
document_from_string(src, opts).convert
|
201
|
-
else
|
202
|
-
# this is required because nokogiri is ignorant
|
203
|
-
result = document_from_string(src, opts).convert
|
204
|
-
result = result.sub(RE_XMLNS_ATTRIBUTE, '') if result
|
205
|
-
result
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def convert_string_to_embedded(src, opts = {})
|
210
|
-
opts[:header_footer] = false
|
211
|
-
document_from_string(src, opts).convert
|
212
|
-
end
|
213
|
-
|
214
|
-
def convert_inline_string(src, opts = {})
|
215
|
-
opts[:doctype] = :inline
|
216
|
-
document_from_string(src, opts).convert
|
217
|
-
end
|
218
|
-
|
219
|
-
def parse_header_metadata(source, doc = nil)
|
220
|
-
reader = Asciidoctor::Reader.new source.split ::Asciidoctor::LF
|
221
|
-
[::Asciidoctor::Parser.parse_header_metadata(reader, doc), reader]
|
222
|
-
end
|
223
|
-
|
224
|
-
def assign_default_test_options(opts)
|
225
|
-
opts[:header_footer] = true unless opts.key? :header_footer
|
226
|
-
opts[:parse] = true unless opts.key? :parse
|
227
|
-
if opts[:header_footer]
|
228
|
-
# don't embed stylesheet unless test requests the default behavior
|
229
|
-
if opts.has_key? :linkcss_default
|
230
|
-
opts.delete(:linkcss_default)
|
231
|
-
else
|
232
|
-
opts[:attributes] ||= {}
|
233
|
-
opts[:attributes]['linkcss'] = ''
|
234
|
-
end
|
235
|
-
end
|
236
|
-
if (template_dir = ENV['TEMPLATE_DIR'])
|
237
|
-
opts[:template_dir] = template_dir unless opts.has_key? :template_dir
|
238
|
-
end
|
239
|
-
nil
|
240
|
-
end
|
241
|
-
|
242
|
-
# Decode the numeric character reference, such as 8212, to a Unicode glyph
|
243
|
-
# so it may be used in an XPath expression.
|
244
|
-
#
|
245
|
-
# Examples
|
246
|
-
#
|
247
|
-
# decode_char 60
|
248
|
-
# # => "<"
|
249
|
-
#
|
250
|
-
# Returns the decoded String that corresponds to the numeric character reference
|
251
|
-
def decode_char number
|
252
|
-
[number].pack 'U1'
|
253
|
-
end
|
254
|
-
|
255
|
-
def invoke_cli_with_filenames(argv = [], filenames = [], &block)
|
256
|
-
filepaths = Array.new
|
257
|
-
|
258
|
-
filenames.each {|filename|
|
259
|
-
if filenames.nil? || ::Pathname.new(filename).absolute?
|
260
|
-
filepaths << filename
|
261
|
-
else
|
262
|
-
filepaths << (fixture_path filename)
|
263
|
-
end
|
264
|
-
}
|
265
|
-
|
266
|
-
invoker = Asciidoctor::Cli::Invoker.new(argv + filepaths)
|
267
|
-
|
268
|
-
invoker.invoke!(&block)
|
269
|
-
invoker
|
270
|
-
end
|
271
|
-
|
272
|
-
def invoke_cli_to_buffer(argv = [], filename = 'sample.asciidoc', &block)
|
273
|
-
invoke_cli(argv, filename, [StringIO.new, StringIO.new], &block)
|
274
|
-
end
|
275
|
-
|
276
|
-
def invoke_cli(argv = [], filename = 'sample.asciidoc', buffers = nil, &block)
|
277
|
-
if filename.nil? || filename == '-' || ::Pathname.new(filename).absolute?
|
278
|
-
filepath = filename
|
279
|
-
else
|
280
|
-
filepath = fixture_path filename
|
281
|
-
end
|
282
|
-
invoker = Asciidoctor::Cli::Invoker.new(argv + [filepath])
|
283
|
-
if buffers
|
284
|
-
invoker.redirect_streams(*buffers)
|
285
|
-
end
|
286
|
-
invoker.invoke!(&block)
|
287
|
-
invoker
|
288
|
-
end
|
289
|
-
|
290
|
-
def redirect_streams
|
291
|
-
old_stdout, $stdout = $stdout, (tmp_stdout = ::StringIO.new)
|
292
|
-
old_stderr, $stderr = $stderr, (tmp_stderr = ::StringIO.new)
|
293
|
-
old_logger = Asciidoctor::LoggerManager.logger
|
294
|
-
old_logger_level = old_logger.level
|
295
|
-
new_logger = (Asciidoctor::LoggerManager.logger = Asciidoctor::Logger.new $stderr)
|
296
|
-
new_logger.level = old_logger_level
|
297
|
-
yield tmp_stdout, tmp_stderr
|
298
|
-
ensure
|
299
|
-
$stdout, $stderr = old_stdout, old_stderr
|
300
|
-
Asciidoctor::LoggerManager.logger = old_logger
|
301
|
-
end
|
302
|
-
|
303
|
-
def resolve_localhost
|
304
|
-
(RUBY_VERSION < '1.9' || RUBY_ENGINE == 'rbx') ? Socket.gethostname :
|
305
|
-
Socket.ip_address_list.find {|addr| addr.ipv4? }.ip_address
|
306
|
-
end
|
307
|
-
|
308
|
-
def using_memory_logger
|
309
|
-
old_logger = Asciidoctor::LoggerManager.logger
|
310
|
-
memory_logger = Asciidoctor::MemoryLogger.new
|
311
|
-
begin
|
312
|
-
Asciidoctor::LoggerManager.logger = memory_logger
|
313
|
-
yield memory_logger
|
314
|
-
ensure
|
315
|
-
Asciidoctor::LoggerManager.logger = old_logger
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
def in_verbose_mode
|
320
|
-
begin
|
321
|
-
old_verbose, $VERBOSE = $VERBOSE, true
|
322
|
-
yield
|
323
|
-
ensure
|
324
|
-
$VERBOSE = old_verbose
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
def using_test_webserver host = resolve_localhost, port = 9876
|
329
|
-
server = TCPServer.new host, port
|
330
|
-
base_dir = testdir
|
331
|
-
t = Thread.new do
|
332
|
-
while (session = server.accept)
|
333
|
-
request = session.gets
|
334
|
-
resource = nil
|
335
|
-
if (m = /GET (\S+) HTTP\/1\.1$/.match(request.chomp))
|
336
|
-
resource = (resource = m[1]) == '' ? '.' : resource
|
337
|
-
else
|
338
|
-
session.print %(HTTP/1.1 405 Method Not Allowed\r\nContent-Type: text/plain\r\n\r\n)
|
339
|
-
session.print %(405 - Method not allowed\n)
|
340
|
-
session.close
|
341
|
-
break
|
342
|
-
end
|
343
|
-
|
344
|
-
if resource == '/name/asciidoctor'
|
345
|
-
session.print %(HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n)
|
346
|
-
session.print %({"name": "asciidoctor"}\n)
|
347
|
-
elsif File.file?(resource_file = (File.join base_dir, resource))
|
348
|
-
mimetype = if (ext = ::File.extname(resource_file)[1..-1])
|
349
|
-
ext == 'adoc' ? 'text/plain' : %(image/#{ext})
|
350
|
-
else
|
351
|
-
'text/plain'
|
352
|
-
end
|
353
|
-
session.print %(HTTP/1.1 200 OK\r\nContent-Type: #{mimetype}\r\n\r\n)
|
354
|
-
File.open resource_file, 'rb' do |fd|
|
355
|
-
until fd.eof? do
|
356
|
-
buffer = fd.read 256
|
357
|
-
session.write buffer
|
358
|
-
end
|
359
|
-
end
|
360
|
-
else
|
361
|
-
session.print %(HTTP/1.1 404 File Not Found\r\nContent-Type: text/plain\r\n\r\n)
|
362
|
-
session.print %(404 - Resource not found.\n)
|
363
|
-
end
|
364
|
-
session.close
|
365
|
-
end
|
366
|
-
end
|
367
|
-
begin
|
368
|
-
yield
|
369
|
-
ensure
|
370
|
-
begin
|
371
|
-
server.shutdown
|
372
|
-
# "Errno::ENOTCONN: Socket is not connected' is reported on some platforms; call #close instead of #shutdown
|
373
|
-
rescue Errno::ENOTCONN
|
374
|
-
server.close
|
375
|
-
end
|
376
|
-
t.exit
|
377
|
-
end
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
###
|
382
|
-
#
|
383
|
-
# Context goodness provided by @citrusbyte's contest.
|
384
|
-
# See https://github.com/citrusbyte/contest
|
385
|
-
#
|
386
|
-
###
|
387
|
-
|
388
|
-
# Contest adds +teardown+, +test+ and +context+ as class methods, and the
|
389
|
-
# instance methods +setup+ and +teardown+ now iterate on the corresponding
|
390
|
-
# blocks. Note that all setup and teardown blocks must be defined with the
|
391
|
-
# block syntax. Adding setup or teardown instance methods defeats the purpose
|
392
|
-
# of this library.
|
393
|
-
class Minitest::Test
|
394
|
-
def self.setup(&block)
|
395
|
-
define_method :setup do
|
396
|
-
super(&block)
|
397
|
-
instance_eval(&block)
|
398
|
-
end
|
399
|
-
end
|
400
|
-
|
401
|
-
def self.teardown(&block)
|
402
|
-
define_method :teardown do
|
403
|
-
instance_eval(&block)
|
404
|
-
super(&block)
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
def self.context(*name, &block)
|
409
|
-
subclass = Class.new(self)
|
410
|
-
remove_tests(subclass)
|
411
|
-
subclass.class_eval(&block) if block_given?
|
412
|
-
const_set(context_name(name.join(" ")), subclass)
|
413
|
-
end
|
414
|
-
|
415
|
-
def self.test(name, &block)
|
416
|
-
define_method(test_name(name), &block)
|
417
|
-
end
|
418
|
-
|
419
|
-
class << self
|
420
|
-
alias_method :should, :test
|
421
|
-
alias_method :describe, :context
|
422
|
-
end
|
423
|
-
|
424
|
-
private
|
425
|
-
|
426
|
-
def self.context_name(name)
|
427
|
-
"Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
|
428
|
-
end
|
429
|
-
|
430
|
-
def self.test_name(name)
|
431
|
-
"test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym
|
432
|
-
end
|
433
|
-
|
434
|
-
def self.sanitize_name(name)
|
435
|
-
name.gsub(/\W+/, ' ').strip
|
436
|
-
end
|
437
|
-
|
438
|
-
def self.remove_tests(subclass)
|
439
|
-
subclass.public_instance_methods.grep(/^test_/).each do |meth|
|
440
|
-
subclass.send(:undef_method, meth.to_sym)
|
441
|
-
end
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
def context(*name, &block)
|
446
|
-
Minitest::Test.context(name, &block)
|
447
|
-
end
|
data/test/text_test.rb
DELETED
@@ -1,309 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
unless defined? ASCIIDOCTOR_PROJECT_DIR
|
3
|
-
$: << File.dirname(__FILE__); $:.uniq!
|
4
|
-
require 'test_helper'
|
5
|
-
end
|
6
|
-
|
7
|
-
context "Text" do
|
8
|
-
test "proper encoding to handle utf8 characters in document using html backend" do
|
9
|
-
output = example_document(:encoding).convert
|
10
|
-
assert_xpath '//p', output, 4
|
11
|
-
assert_xpath '//a', output, 1
|
12
|
-
end
|
13
|
-
|
14
|
-
test "proper encoding to handle utf8 characters in embedded document using html backend" do
|
15
|
-
output = example_document(:encoding, :header_footer => false).convert
|
16
|
-
assert_xpath '//p', output, 4
|
17
|
-
assert_xpath '//a', output, 1
|
18
|
-
end
|
19
|
-
|
20
|
-
test "proper encoding to handle utf8 characters in document using docbook45 backend" do
|
21
|
-
output = example_document(:encoding, :attributes => {'backend' => 'docbook45', 'xmlns' => ''}).convert
|
22
|
-
assert_xpath '//xmlns:simpara', output, 4
|
23
|
-
assert_xpath '//xmlns:ulink', output, 1
|
24
|
-
end
|
25
|
-
|
26
|
-
test "proper encoding to handle utf8 characters in embedded document using docbook45 backend" do
|
27
|
-
output = example_document(:encoding, :header_footer => false, :attributes => {'backend' => 'docbook45'}).convert
|
28
|
-
assert_xpath '//simpara', output, 4
|
29
|
-
assert_xpath '//ulink', output, 1
|
30
|
-
end
|
31
|
-
|
32
|
-
# NOTE this test ensures we have the encoding line on block templates too
|
33
|
-
test 'proper encoding to handle utf8 characters in arbitrary block' do
|
34
|
-
input = []
|
35
|
-
input << "[verse]\n"
|
36
|
-
input.concat(File.readlines(sample_doc_path(:encoding)))
|
37
|
-
doc = empty_document
|
38
|
-
reader = Asciidoctor::PreprocessorReader.new doc, input, nil, :normalize => true
|
39
|
-
block = Asciidoctor::Parser.next_block(reader, doc)
|
40
|
-
assert_xpath '//pre', block.convert.gsub(/^\s*\n/, ''), 1
|
41
|
-
end
|
42
|
-
|
43
|
-
test 'proper encoding to handle utf8 characters from included file' do
|
44
|
-
input = <<-EOS
|
45
|
-
include::fixtures/encoding.asciidoc[tags=romé]
|
46
|
-
EOS
|
47
|
-
doc = empty_safe_document :base_dir => testdir
|
48
|
-
reader = Asciidoctor::PreprocessorReader.new doc, input, nil, :normalize => true
|
49
|
-
block = Asciidoctor::Parser.next_block(reader, doc)
|
50
|
-
output = block.convert
|
51
|
-
assert_css '.paragraph', output, 1
|
52
|
-
end
|
53
|
-
|
54
|
-
test 'escaped text markup' do
|
55
|
-
assert_match(/All your <em>inline<\/em> markup belongs to <strong>us<\/strong>!/,
|
56
|
-
convert_string('All your <em>inline</em> markup belongs to <strong>us</strong>!'))
|
57
|
-
end
|
58
|
-
|
59
|
-
test "line breaks" do
|
60
|
-
assert_xpath "//br", convert_string("Well this is +\njust fine and dandy, isn't it?"), 1
|
61
|
-
end
|
62
|
-
|
63
|
-
test 'single- and double-quoted text' do
|
64
|
-
output = convert_string_to_embedded(%q(``Where?,'' she said, flipping through her copy of `The New Yorker.'), :attributes => {'compat-mode' => ''})
|
65
|
-
assert_match(/“Where\?,”/, output)
|
66
|
-
assert_match(/‘The New Yorker.’/, output)
|
67
|
-
|
68
|
-
output = convert_string_to_embedded(%q("`Where?,`" she said, flipping through her copy of '`The New Yorker.`'))
|
69
|
-
assert_match(/“Where\?,”/, output)
|
70
|
-
assert_match(/‘The New Yorker.’/, output)
|
71
|
-
end
|
72
|
-
|
73
|
-
test 'multiple double-quoted text on a single line' do
|
74
|
-
assert_equal '“Our business is constantly changing” or “We need faster time to market.”',
|
75
|
-
convert_inline_string(%q(``Our business is constantly changing'' or ``We need faster time to market.''), :attributes => {'compat-mode' => ''})
|
76
|
-
assert_equal '“Our business is constantly changing” or “We need faster time to market.”',
|
77
|
-
convert_inline_string(%q("`Our business is constantly changing`" or "`We need faster time to market.`"))
|
78
|
-
end
|
79
|
-
|
80
|
-
test 'horizontal rule' do
|
81
|
-
input = <<-EOS
|
82
|
-
This line is separated by a horizontal rule...
|
83
|
-
|
84
|
-
'''
|
85
|
-
|
86
|
-
...from this line.
|
87
|
-
EOS
|
88
|
-
output = convert_string_to_embedded input
|
89
|
-
assert_xpath "//hr", output, 1
|
90
|
-
assert_xpath "/*[@class='paragraph']", output, 2
|
91
|
-
assert_xpath "(/*[@class='paragraph'])[1]/following-sibling::hr", output, 1
|
92
|
-
assert_xpath "/hr/following-sibling::*[@class='paragraph']", output, 1
|
93
|
-
end
|
94
|
-
|
95
|
-
test 'markdown horizontal rules' do
|
96
|
-
variants = [
|
97
|
-
'---',
|
98
|
-
'- - -',
|
99
|
-
'***',
|
100
|
-
'* * *',
|
101
|
-
'___',
|
102
|
-
'_ _ _'
|
103
|
-
]
|
104
|
-
|
105
|
-
offsets = [
|
106
|
-
'',
|
107
|
-
' ',
|
108
|
-
' ',
|
109
|
-
' '
|
110
|
-
]
|
111
|
-
|
112
|
-
variants.each do |variant|
|
113
|
-
offsets.each do |offset|
|
114
|
-
input = <<-EOS
|
115
|
-
This line is separated by a horizontal rule...
|
116
|
-
|
117
|
-
#{offset}#{variant}
|
118
|
-
|
119
|
-
...from this line.
|
120
|
-
EOS
|
121
|
-
output = convert_string_to_embedded input
|
122
|
-
assert_xpath "//hr", output, 1
|
123
|
-
assert_xpath "/*[@class='paragraph']", output, 2
|
124
|
-
assert_xpath "(/*[@class='paragraph'])[1]/following-sibling::hr", output, 1
|
125
|
-
assert_xpath "/hr/following-sibling::*[@class='paragraph']", output, 1
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
test 'markdown horizontal rules negative case' do
|
131
|
-
|
132
|
-
bad_variants = [
|
133
|
-
'- - - -',
|
134
|
-
'* * * *',
|
135
|
-
'_ _ _ _'
|
136
|
-
]
|
137
|
-
|
138
|
-
good_offsets = [
|
139
|
-
'',
|
140
|
-
' ',
|
141
|
-
' ',
|
142
|
-
' '
|
143
|
-
]
|
144
|
-
|
145
|
-
bad_variants.each do |variant|
|
146
|
-
good_offsets.each do |offset|
|
147
|
-
input = <<-EOS
|
148
|
-
This line is separated by something that is not a horizontal rule...
|
149
|
-
|
150
|
-
#{offset}#{variant}
|
151
|
-
|
152
|
-
...from this line.
|
153
|
-
EOS
|
154
|
-
output = convert_string_to_embedded input
|
155
|
-
assert_xpath '//hr', output, 0
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
good_variants = [
|
160
|
-
'- - -',
|
161
|
-
'* * *',
|
162
|
-
'_ _ _'
|
163
|
-
]
|
164
|
-
|
165
|
-
bad_offsets = [
|
166
|
-
"\t",
|
167
|
-
' '
|
168
|
-
]
|
169
|
-
|
170
|
-
good_variants.each do |variant|
|
171
|
-
bad_offsets.each do |offset|
|
172
|
-
input = <<-EOS
|
173
|
-
This line is separated by something that is not a horizontal rule...
|
174
|
-
|
175
|
-
#{offset}#{variant}
|
176
|
-
|
177
|
-
...from this line.
|
178
|
-
EOS
|
179
|
-
output = convert_string_to_embedded input
|
180
|
-
assert_xpath '//hr', output, 0
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
test "emphasized text using underscore characters" do
|
186
|
-
assert_xpath "//em", convert_string("An _emphatic_ no")
|
187
|
-
end
|
188
|
-
|
189
|
-
test 'emphasized text with single quote using apostrophe characters' do
|
190
|
-
rsquo = decode_char 8217
|
191
|
-
assert_xpath %(//em[text()="Johnny#{rsquo}s"]), convert_string(%q(It's 'Johnny's' phone), :attributes => {'compat-mode' => ''})
|
192
|
-
assert_xpath %(//p[text()="It#{rsquo}s 'Johnny#{rsquo}s' phone"]), convert_string(%q(It's 'Johnny's' phone))
|
193
|
-
end
|
194
|
-
|
195
|
-
test 'emphasized text with escaped single quote using apostrophe characters' do
|
196
|
-
assert_xpath %(//em[text()="Johnny's"]), convert_string(%q(It's 'Johnny\\'s' phone), :attributes => {'compat-mode' => ''})
|
197
|
-
assert_xpath %(//p[text()="It's 'Johnny's' phone"]), convert_string(%q(It\\'s 'Johnny\\'s' phone))
|
198
|
-
end
|
199
|
-
|
200
|
-
test "escaped single quote is restored as single quote" do
|
201
|
-
assert_xpath "//p[contains(text(), \"Let's do it!\")]", convert_string("Let\\'s do it!")
|
202
|
-
end
|
203
|
-
|
204
|
-
test 'unescape escaped single quote emphasis in compat mode only' do
|
205
|
-
assert_xpath %(//p[text()="A 'single quoted string' example"]), convert_string_to_embedded(%(A \\'single quoted string' example), :attributes => {'compat-mode' => ''})
|
206
|
-
assert_xpath %(//p[text()="'single quoted string'"]), convert_string_to_embedded(%(\\'single quoted string'), :attributes => {'compat-mode' => ''})
|
207
|
-
|
208
|
-
assert_xpath %(//p[text()="A \\'single quoted string' example"]), convert_string_to_embedded(%(A \\'single quoted string' example))
|
209
|
-
assert_xpath %(//p[text()="\\'single quoted string'"]), convert_string_to_embedded(%(\\'single quoted string'))
|
210
|
-
end
|
211
|
-
|
212
|
-
test "emphasized text at end of line" do
|
213
|
-
assert_xpath "//em", convert_string("This library is _awesome_")
|
214
|
-
end
|
215
|
-
|
216
|
-
test "emphasized text at beginning of line" do
|
217
|
-
assert_xpath "//em", convert_string("_drop_ it")
|
218
|
-
end
|
219
|
-
|
220
|
-
test "emphasized text across line" do
|
221
|
-
assert_xpath "//em", convert_string("_check it_")
|
222
|
-
end
|
223
|
-
|
224
|
-
test "unquoted text" do
|
225
|
-
refute_match(/#/, convert_string("An #unquoted# word"))
|
226
|
-
end
|
227
|
-
|
228
|
-
test 'backticks and straight quotes in text' do
|
229
|
-
backslash = '\\'
|
230
|
-
assert_equal %q(run <code>foo</code> <em>dog</em>), convert_inline_string(%q(run `foo` 'dog'), :attributes => {'compat-mode' => ''})
|
231
|
-
assert_equal %q(run <code>foo</code> 'dog'), convert_inline_string(%q(run `foo` 'dog'))
|
232
|
-
assert_equal %q(run `foo` 'dog'), convert_inline_string(%(run #{backslash}`foo` 'dog'))
|
233
|
-
assert_equal %q(run ‘foo` 'dog’), convert_inline_string(%q(run '`foo` 'dog`'))
|
234
|
-
assert_equal %q(run '`foo` 'dog`'), convert_inline_string(%(run #{backslash}'`foo` 'dog#{backslash}`'))
|
235
|
-
end
|
236
|
-
|
237
|
-
test 'plus characters inside single plus passthrough' do
|
238
|
-
assert_xpath '//p[text()="+"]', convert_string_to_embedded('+++')
|
239
|
-
assert_xpath '//p[text()="+="]', convert_string_to_embedded('++=+')
|
240
|
-
end
|
241
|
-
|
242
|
-
test 'plus passthrough escapes entity reference' do
|
243
|
-
assert_match(/&#44;/, convert_string_to_embedded('+,+'))
|
244
|
-
assert_match(/one&#44;two/, convert_string_to_embedded('one++,++two'))
|
245
|
-
end
|
246
|
-
|
247
|
-
context "basic styling" do
|
248
|
-
setup do
|
249
|
-
@output = convert_string("A *BOLD* word. An _italic_ word. A `mono` word. ^superscript!^ and some ~subscript~.")
|
250
|
-
end
|
251
|
-
|
252
|
-
test "strong" do
|
253
|
-
assert_xpath "//strong", @output, 1
|
254
|
-
end
|
255
|
-
|
256
|
-
test "italic" do
|
257
|
-
assert_xpath "//em", @output, 1
|
258
|
-
end
|
259
|
-
|
260
|
-
test "monospaced" do
|
261
|
-
assert_xpath "//code", @output, 1
|
262
|
-
end
|
263
|
-
|
264
|
-
test "superscript" do
|
265
|
-
assert_xpath "//sup", @output, 1
|
266
|
-
end
|
267
|
-
|
268
|
-
test "subscript" do
|
269
|
-
assert_xpath "//sub", @output, 1
|
270
|
-
end
|
271
|
-
|
272
|
-
test "passthrough" do
|
273
|
-
assert_xpath "//code", convert_string("This is +passed through+."), 0
|
274
|
-
assert_xpath "//code", convert_string("This is +passed through and monospaced+.", :attributes => {'compat-mode' => ''}), 1
|
275
|
-
end
|
276
|
-
|
277
|
-
test "nested styles" do
|
278
|
-
output = convert_string("Winning *big _time_* in the +city *boyeeee*+.", :attributes => {'compat-mode' => ''})
|
279
|
-
|
280
|
-
assert_xpath "//strong/em", output
|
281
|
-
assert_xpath "//code/strong", output
|
282
|
-
|
283
|
-
output = convert_string("Winning *big _time_* in the `city *boyeeee*`.")
|
284
|
-
|
285
|
-
assert_xpath "//strong/em", output
|
286
|
-
assert_xpath "//code/strong", output
|
287
|
-
end
|
288
|
-
|
289
|
-
test 'unconstrained quotes' do
|
290
|
-
output = convert_string('**B**__I__++M++[role]++M++', :attributes => {'compat-mode' => ''})
|
291
|
-
assert_xpath '//strong', output, 1
|
292
|
-
assert_xpath '//em', output, 1
|
293
|
-
assert_xpath '//code[not(@class)]', output, 1
|
294
|
-
assert_xpath '//code[@class="role"]', output, 1
|
295
|
-
|
296
|
-
output = convert_string('**B**__I__``M``[role]``M``')
|
297
|
-
assert_xpath '//strong', output, 1
|
298
|
-
assert_xpath '//em', output, 1
|
299
|
-
assert_xpath '//code[not(@class)]', output, 1
|
300
|
-
assert_xpath '//code[@class="role"]', output, 1
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
test 'should format Asian characters as words' do
|
305
|
-
assert_xpath '//strong', (convert_string_to_embedded 'bold *要* bold')
|
306
|
-
assert_xpath '//strong', (convert_string_to_embedded 'bold *素* bold')
|
307
|
-
assert_xpath '//strong', (convert_string_to_embedded 'bold *要素* bold')
|
308
|
-
end
|
309
|
-
end
|