asciidoctor 1.5.8 → 2.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|