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.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +162 -17
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +12 -13
  5. data/README-fr.adoc +11 -12
  6. data/README-jp.adoc +11 -12
  7. data/README-zh_CN.adoc +12 -13
  8. data/README.adoc +6 -7
  9. data/asciidoctor.gemspec +19 -24
  10. data/bin/asciidoctor +5 -4
  11. data/data/reference/syntax.adoc +283 -0
  12. data/data/stylesheets/asciidoctor-default.css +56 -52
  13. data/data/stylesheets/coderay-asciidoctor.css +7 -9
  14. data/lib/asciidoctor.rb +171 -232
  15. data/lib/asciidoctor/abstract_block.rb +96 -105
  16. data/lib/asciidoctor/abstract_node.rb +118 -139
  17. data/lib/asciidoctor/attribute_list.rb +10 -14
  18. data/lib/asciidoctor/block.rb +20 -19
  19. data/lib/asciidoctor/callouts.rb +4 -2
  20. data/lib/asciidoctor/cli.rb +3 -2
  21. data/lib/asciidoctor/cli/invoker.rb +14 -21
  22. data/lib/asciidoctor/cli/options.rb +64 -54
  23. data/lib/asciidoctor/converter.rb +357 -185
  24. data/lib/asciidoctor/converter/composite.rb +40 -48
  25. data/lib/asciidoctor/converter/docbook5.rb +604 -640
  26. data/lib/asciidoctor/converter/html5.rb +949 -963
  27. data/lib/asciidoctor/converter/manpage.rb +569 -548
  28. data/lib/asciidoctor/converter/template.rb +231 -272
  29. data/lib/asciidoctor/core_ext.rb +5 -18
  30. data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
  31. data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
  32. data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
  33. data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
  34. data/lib/asciidoctor/document.rb +399 -377
  35. data/lib/asciidoctor/extensions.rb +72 -140
  36. data/lib/asciidoctor/helpers.rb +122 -83
  37. data/lib/asciidoctor/inline.rb +5 -1
  38. data/lib/asciidoctor/list.rb +13 -11
  39. data/lib/asciidoctor/logging.rb +17 -16
  40. data/lib/asciidoctor/parser.rb +390 -423
  41. data/lib/asciidoctor/path_resolver.rb +10 -5
  42. data/lib/asciidoctor/reader.rb +286 -263
  43. data/lib/asciidoctor/rouge_ext.rb +39 -0
  44. data/lib/asciidoctor/section.rb +9 -8
  45. data/lib/asciidoctor/stylesheets.rb +19 -37
  46. data/lib/asciidoctor/substitutors.rb +364 -509
  47. data/lib/asciidoctor/syntax_highlighter.rb +238 -0
  48. data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
  49. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
  50. data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
  51. data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
  52. data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
  53. data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
  54. data/lib/asciidoctor/table.rb +73 -66
  55. data/lib/asciidoctor/timings.rb +4 -2
  56. data/lib/asciidoctor/version.rb +2 -1
  57. data/lib/asciidoctor/writer.rb +30 -0
  58. data/man/asciidoctor.1 +19 -15
  59. data/man/asciidoctor.adoc +14 -12
  60. metadata +69 -216
  61. data/CONTRIBUTING.adoc +0 -185
  62. data/Gemfile +0 -60
  63. data/Rakefile +0 -129
  64. data/bin/asciidoctor-safe +0 -15
  65. data/features/open_block.feature +0 -92
  66. data/features/pass_block.feature +0 -66
  67. data/features/step_definitions.rb +0 -49
  68. data/features/text_formatting.feature +0 -57
  69. data/features/xref.feature +0 -1039
  70. data/lib/asciidoctor/converter/base.rb +0 -59
  71. data/lib/asciidoctor/converter/docbook45.rb +0 -93
  72. data/lib/asciidoctor/converter/factory.rb +0 -226
  73. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
  74. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
  75. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
  76. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
  77. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
  78. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
  79. data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
  80. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
  81. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
  82. data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
  83. data/test/api_test.rb +0 -1240
  84. data/test/attribute_list_test.rb +0 -242
  85. data/test/attributes_test.rb +0 -1623
  86. data/test/blocks_test.rb +0 -3870
  87. data/test/converter_test.rb +0 -470
  88. data/test/document_test.rb +0 -1853
  89. data/test/extensions_test.rb +0 -1560
  90. data/test/fixtures/asciidoc_index.txt +0 -521
  91. data/test/fixtures/basic-docinfo-footer.html +0 -6
  92. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  93. data/test/fixtures/basic-docinfo.html +0 -1
  94. data/test/fixtures/basic-docinfo.xml +0 -4
  95. data/test/fixtures/basic.asciidoc +0 -5
  96. data/test/fixtures/chapter-a.adoc +0 -3
  97. data/test/fixtures/child-include.adoc +0 -5
  98. data/test/fixtures/circle.svg +0 -9
  99. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  100. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  101. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  102. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  103. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  104. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  105. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  106. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  107. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  108. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  109. data/test/fixtures/docinfo-footer.html +0 -1
  110. data/test/fixtures/docinfo-footer.xml +0 -9
  111. data/test/fixtures/docinfo.html +0 -1
  112. data/test/fixtures/docinfo.xml +0 -3
  113. data/test/fixtures/doctime-localtime.adoc +0 -2
  114. data/test/fixtures/dot.gif +0 -0
  115. data/test/fixtures/encoding.asciidoc +0 -13
  116. data/test/fixtures/file-with-missing-include.adoc +0 -1
  117. data/test/fixtures/grandchild-include.adoc +0 -3
  118. data/test/fixtures/hello-asciidoctor.pdf +0 -69
  119. data/test/fixtures/include-file.asciidoc +0 -24
  120. data/test/fixtures/include-file.jsx +0 -8
  121. data/test/fixtures/include-file.ml +0 -3
  122. data/test/fixtures/include-file.xml +0 -5
  123. data/test/fixtures/lists.adoc +0 -96
  124. data/test/fixtures/master.adoc +0 -5
  125. data/test/fixtures/mismatched-end-tag.adoc +0 -7
  126. data/test/fixtures/other-chapters.adoc +0 -11
  127. data/test/fixtures/outer-include.adoc +0 -5
  128. data/test/fixtures/parent-include-restricted.adoc +0 -5
  129. data/test/fixtures/parent-include.adoc +0 -5
  130. data/test/fixtures/sample.asciidoc +0 -30
  131. data/test/fixtures/section-a.adoc +0 -4
  132. data/test/fixtures/stylesheets/custom.css +0 -3
  133. data/test/fixtures/subdir/index.adoc +0 -3
  134. data/test/fixtures/subdir/inner-include.adoc +0 -3
  135. data/test/fixtures/subdir/middle-include.adoc +0 -5
  136. data/test/fixtures/subs-docinfo.html +0 -2
  137. data/test/fixtures/subs.adoc +0 -6
  138. data/test/fixtures/tagged-class-enclosed.rb +0 -25
  139. data/test/fixtures/tagged-class.rb +0 -23
  140. data/test/fixtures/tip.gif +0 -0
  141. data/test/fixtures/unclosed-tag.adoc +0 -3
  142. data/test/fixtures/unexpected-end-tag.adoc +0 -4
  143. data/test/invoker_test.rb +0 -745
  144. data/test/links_test.rb +0 -855
  145. data/test/lists_test.rb +0 -5151
  146. data/test/logger_test.rb +0 -211
  147. data/test/manpage_test.rb +0 -660
  148. data/test/options_test.rb +0 -262
  149. data/test/paragraphs_test.rb +0 -562
  150. data/test/parser_test.rb +0 -742
  151. data/test/paths_test.rb +0 -395
  152. data/test/preamble_test.rb +0 -173
  153. data/test/reader_test.rb +0 -2161
  154. data/test/sections_test.rb +0 -3575
  155. data/test/substitutions_test.rb +0 -2066
  156. data/test/tables_test.rb +0 -2036
  157. data/test/test_helper.rb +0 -447
  158. data/test/text_test.rb +0 -309
@@ -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
@@ -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 &lt;em&gt;inline&lt;\/em&gt; markup belongs to &lt;strong&gt;us&lt;\/strong&gt;!/,
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(/&#8220;Where\?,&#8221;/, output)
66
- assert_match(/&#8216;The New Yorker.&#8217;/, output)
67
-
68
- output = convert_string_to_embedded(%q("`Where?,`" she said, flipping through her copy of '`The New Yorker.`'))
69
- assert_match(/&#8220;Where\?,&#8221;/, output)
70
- assert_match(/&#8216;The New Yorker.&#8217;/, output)
71
- end
72
-
73
- test 'multiple double-quoted text on a single line' do
74
- assert_equal '&#8220;Our business is constantly changing&#8221; or &#8220;We need faster time to market.&#8221;',
75
- convert_inline_string(%q(``Our business is constantly changing'' or ``We need faster time to market.''), :attributes => {'compat-mode' => ''})
76
- assert_equal '&#8220;Our business is constantly changing&#8221; or &#8220;We need faster time to market.&#8221;',
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 &#8216;foo` 'dog&#8217;), 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(/&amp;#44;/, convert_string_to_embedded('+&#44;+'))
244
- assert_match(/one&amp;#44;two/, convert_string_to_embedded('one++&#44;++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