asciidoctor 1.5.4 → 1.5.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of asciidoctor might be problematic. Click here for more details.

Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +72 -5
  3. data/CONTRIBUTING.adoc +3 -3
  4. data/Gemfile +23 -0
  5. data/README-fr.adoc +416 -0
  6. data/README-jp.adoc +395 -0
  7. data/README-zh_CN.adoc +414 -0
  8. data/README.adoc +134 -72
  9. data/asciidoctor.gemspec +49 -0
  10. data/data/locale/attributes.adoc +470 -0
  11. data/data/stylesheets/asciidoctor-default.css +6 -5
  12. data/lib/asciidoctor.rb +22 -19
  13. data/lib/asciidoctor/abstract_block.rb +20 -10
  14. data/lib/asciidoctor/abstract_node.rb +3 -14
  15. data/lib/asciidoctor/cli/invoker.rb +5 -4
  16. data/lib/asciidoctor/cli/options.rb +1 -1
  17. data/lib/asciidoctor/converter/docbook5.rb +1 -1
  18. data/lib/asciidoctor/converter/factory.rb +1 -5
  19. data/lib/asciidoctor/converter/html5.rb +36 -31
  20. data/lib/asciidoctor/converter/manpage.rb +14 -9
  21. data/lib/asciidoctor/converter/template.rb +8 -4
  22. data/lib/asciidoctor/core_ext.rb +7 -6
  23. data/lib/asciidoctor/core_ext/{string → 1.8.7/string}/chr.rb +1 -1
  24. data/lib/asciidoctor/core_ext/1.8.7/string/limit.rb +28 -0
  25. data/lib/asciidoctor/core_ext/{symbol → 1.8.7/symbol}/length.rb +1 -1
  26. data/lib/asciidoctor/core_ext/nil_or_empty.rb +23 -0
  27. data/lib/asciidoctor/core_ext/string/limit.rb +10 -0
  28. data/lib/asciidoctor/document.rb +33 -26
  29. data/lib/asciidoctor/extensions.rb +16 -16
  30. data/lib/asciidoctor/helpers.rb +1 -1
  31. data/lib/asciidoctor/list.rb +3 -0
  32. data/lib/asciidoctor/parser.rb +47 -43
  33. data/lib/asciidoctor/path_resolver.rb +3 -1
  34. data/lib/asciidoctor/reader.rb +15 -14
  35. data/lib/asciidoctor/section.rb +2 -2
  36. data/lib/asciidoctor/stylesheets.rb +2 -1
  37. data/lib/asciidoctor/substitutors.rb +44 -46
  38. data/lib/asciidoctor/table.rb +41 -38
  39. data/lib/asciidoctor/version.rb +1 -1
  40. data/man/asciidoctor.1 +11 -4
  41. data/man/asciidoctor.adoc +7 -1
  42. data/test/attributes_test.rb +52 -0
  43. data/test/blocks_test.rb +8 -8
  44. data/test/document_test.rb +13 -1
  45. data/test/extensions_test.rb +38 -0
  46. data/test/invoker_test.rb +15 -0
  47. data/test/lists_test.rb +78 -53
  48. data/test/manpage_test.rb +15 -0
  49. data/test/paths_test.rb +3 -0
  50. data/test/reader_test.rb +2 -2
  51. data/test/sections_test.rb +10 -0
  52. data/test/substitutions_test.rb +12 -6
  53. data/test/tables_test.rb +76 -2
  54. metadata +16 -45
  55. data/lib/asciidoctor/core_ext/object/nil_or_empty.rb +0 -23
  56. data/test/fixtures/asciidoc_index.txt +0 -521
  57. data/test/fixtures/basic-docinfo-footer.html +0 -6
  58. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  59. data/test/fixtures/basic-docinfo.html +0 -1
  60. data/test/fixtures/basic-docinfo.xml +0 -4
  61. data/test/fixtures/basic.asciidoc +0 -5
  62. data/test/fixtures/chapter-a.adoc +0 -3
  63. data/test/fixtures/child-include.adoc +0 -5
  64. data/test/fixtures/circle.svg +0 -8
  65. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  66. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  67. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  68. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  69. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  70. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  71. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  72. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  73. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  74. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  75. data/test/fixtures/docinfo-footer.html +0 -1
  76. data/test/fixtures/docinfo-footer.xml +0 -9
  77. data/test/fixtures/docinfo.html +0 -1
  78. data/test/fixtures/docinfo.xml +0 -3
  79. data/test/fixtures/dot.gif +0 -0
  80. data/test/fixtures/encoding.asciidoc +0 -13
  81. data/test/fixtures/grandchild-include.adoc +0 -3
  82. data/test/fixtures/hello-asciidoctor.pdf +0 -0
  83. data/test/fixtures/include-file.asciidoc +0 -24
  84. data/test/fixtures/include-file.xml +0 -5
  85. data/test/fixtures/master.adoc +0 -5
  86. data/test/fixtures/parent-include-restricted.adoc +0 -5
  87. data/test/fixtures/parent-include.adoc +0 -5
  88. data/test/fixtures/sample.asciidoc +0 -26
  89. data/test/fixtures/stylesheets/custom.css +0 -3
  90. data/test/fixtures/subs-docinfo.html +0 -2
  91. data/test/fixtures/subs.adoc +0 -7
  92. data/test/fixtures/tip.gif +0 -0
  93. data/test/test_helper.rb +0 -399
@@ -1,6 +0,0 @@
1
- <script>
2
- (function() {
3
- var p1 = document.createElement('script'); p1.async = true; p1.src = 'https://apis.google.com/js/plusone.js';
4
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(p1, s);
5
- })();
6
- </script>
@@ -1,8 +0,0 @@
1
- <revhistory>
2
- <revision>
3
- <revnumber>{revnumber}</revnumber>
4
- <date>01 Jan 2013</date>
5
- <authorinitials>abc</authorinitials>
6
- <revremark>Unleashed into the wild</revremark>
7
- </revision>
8
- </revhistory>
@@ -1 +0,0 @@
1
- <script src="modernizr.js"></script>
@@ -1,4 +0,0 @@
1
- <copyright><!-- don't remove the indent! -->
2
- <year>2013</year>
3
- <holder>Acme™, Inc.</holder>
4
- </copyright>
@@ -1,5 +0,0 @@
1
- = Document Title
2
- Doc Writer <doc.writer@asciidoc.org>
3
- v1.0, 2013-01-01
4
-
5
- Body content.
@@ -1,3 +0,0 @@
1
- = Chapter A
2
-
3
- content
@@ -1,5 +0,0 @@
1
- first line of child
2
-
3
- include::grandchild-include.adoc[]
4
-
5
- last line of child
@@ -1,8 +0,0 @@
1
- <?xml version="1.0"?>
2
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
- <!-- An SVG of a black circle -->
4
- <svg viewBox="0 0 120 120" version="1.1"
5
- xmlns="http://www.w3.org/2000/svg" style="width:500px;height:500px"
6
- width="500px" height="500px">
7
- <circle cx="60" cy="60" r="50"/>
8
- </svg>
@@ -1,6 +0,0 @@
1
- <%#encoding:UTF-8%><div<%= @id && %( id="#{@id}") %> class="<%= ['paragraph',role].compact * ' ' %>"><%
2
- if title? %>
3
- <div class="title"><%= title %></div><%
4
- end %>
5
- <p><%= content %></p>
6
- </div>
@@ -1,6 +0,0 @@
1
- - if title?
2
- %formalpara{:id=>@id, :role=>(attr :role), :xreflabel=>(attr :reftext)}
3
- %title=title
4
- %para=content
5
- - else
6
- %para{:id=>@id, :role=>(attr :role), :xreflabel=>(attr :reftext)}=content
@@ -1,3 +0,0 @@
1
- - if title?
2
- .title=title
3
- %p{:id=>@id, :class=>(attr 'role')}=content
@@ -1,5 +0,0 @@
1
- %aside{:id=>@id, :class=>(attr 'role')}
2
- - if title?
3
- %header
4
- %h1=title
5
- =content.chomp
@@ -1,6 +0,0 @@
1
- - if title?
2
- formalpara id=@id role=(attr :role) xreflabel=(attr :reftext)
3
- title=title
4
- para=content
5
- - else
6
- para id=@id role=(attr :role) xreflabel=(attr :reftext) =content
@@ -1,3 +0,0 @@
1
- - if title?
2
- .title=title
3
- p id=@id class=(attr 'role') =content
@@ -1,5 +0,0 @@
1
- aside id=@id class=(attr 'role')
2
- - if title?
3
- header
4
- h1=title
5
- =content
@@ -1 +0,0 @@
1
- <script src="bootstrap.js"></script>
@@ -1 +0,0 @@
1
- <meta name="robots" content="index,follow">
@@ -1 +0,0 @@
1
- <a id="top" href="#">Back to top</a>
@@ -1,9 +0,0 @@
1
- <glossary id="_glossary">
2
- <title>Glossary</title>
3
- <glossentry>
4
- <glossterm>term</glossterm>
5
- <glossdef>
6
- <simpara>definition</simpara>
7
- </glossdef>
8
- </glossentry>
9
- </glossary>
@@ -1 +0,0 @@
1
- <meta http-equiv="imagetoolbar" content="false">
@@ -1,3 +0,0 @@
1
- <productname>Asciidoctor™</productname>
2
- <productnumber>1.0.0</productnumber>
3
- <edition>{revnumber}</edition>
Binary file
@@ -1,13 +0,0 @@
1
- Gregory Romé has written an AsciiDoc plugin for the Redmine project management application.
2
-
3
- https://github.com/foo-users/foo
4
- へと `vicmd` キーマップを足してみている試み、
5
- アニメーションgifです。
6
-
7
- tag::romé[]
8
- Gregory Romé has written an AsciiDoc plugin for the Redmine project management application.
9
- end::romé[]
10
-
11
- == Überschrift
12
-
13
- * Codierungen sind verrückt auf älteren Versionen von Ruby
@@ -1,3 +0,0 @@
1
- first line of grandchild
2
-
3
- last line of grandchild
@@ -1,24 +0,0 @@
1
- first line of included content
2
- second line of included content
3
- third line of included content
4
- fourth line of included content
5
- fifth line of included content
6
- sixth line of included content
7
- seventh line of included content
8
- eighth line of included content
9
-
10
- // tag::snippet[]
11
- // tag::snippetA[]
12
- snippetA content
13
- // end::snippetA[]
14
-
15
- non-tagged content
16
-
17
- // tag::snippetB[]
18
- snippetB content
19
- // end::snippetB[]
20
- // end::snippet[]
21
-
22
- more non-tagged content
23
-
24
- last line of included content
@@ -1,5 +0,0 @@
1
- <root>
2
- <!-- tag::snippet[] -->
3
- <snippet>content</snippet>
4
- <!-- end::snippet[] -->
5
- </root>
@@ -1,5 +0,0 @@
1
- = Master Document
2
-
3
- preamble
4
-
5
- include::chapter-a.adoc[leveloffset=+1]
@@ -1,5 +0,0 @@
1
- first line of parent
2
-
3
- include::child-include.adoc[depth=1]
4
-
5
- last line of parent
@@ -1,5 +0,0 @@
1
- first line of parent
2
-
3
- include::child-include.adoc[]
4
-
5
- last line of parent
@@ -1,26 +0,0 @@
1
- Document Title
2
- ==============
3
- Doc Writer <thedoc@asciidoctor.org>
4
- :idprefix: id_
5
-
6
- Preamble paragraph.
7
-
8
- NOTE: This is test, only a test.
9
-
10
- == Section A
11
-
12
- *Section A* paragraph.
13
-
14
- === Section A Subsection
15
-
16
- *Section A* 'subsection' paragraph.
17
-
18
- == Section B
19
-
20
- *Section B* paragraph.
21
-
22
- .Section B list
23
- * Item 1
24
- * Item 2
25
- * Item 3
26
-
@@ -1,3 +0,0 @@
1
- body {
2
- color: red;
3
- }
@@ -1,2 +0,0 @@
1
- <meta name="copyright" content="(C) OpenDevise">
2
- <script src="bootstrap.{bootstrap-version}.min.js"></script>
@@ -1,7 +0,0 @@
1
- = Document Title
2
- Doc Writer <doc.writer@asciidoc.org>
3
- v1.0, 2013-01-01
4
- :bootstrap-version: 3.2.0
5
-
6
- Body content.
7
-
Binary file
@@ -1,399 +0,0 @@
1
- # encoding: UTF-8
2
- ASCIIDOCTOR_PROJECT_DIR = File.dirname File.dirname(__FILE__)
3
- Dir.chdir ASCIIDOCTOR_PROJECT_DIR
4
-
5
- if RUBY_VERSION < '1.9'
6
- require 'rubygems'
7
- end
8
-
9
- require 'simplecov' if ENV['COVERAGE'] == 'true'
10
-
11
- require File.join(ASCIIDOCTOR_PROJECT_DIR, 'lib', 'asciidoctor')
12
-
13
- require 'socket'
14
- require 'nokogiri'
15
- require 'tmpdir'
16
-
17
- autoload :FileUtils, 'fileutils'
18
- autoload :Pathname, 'pathname'
19
-
20
- RE_XMLNS_ATTRIBUTE = / xmlns="[^"]+"/
21
- RE_DOCTYPE = /\s*<!DOCTYPE (.*)/
22
-
23
- require 'minitest/autorun'
24
-
25
- # Minitest 4 doesn't have Minitest::Test
26
- Minitest::Test = MiniTest::Unit::TestCase unless defined? Minitest::Test
27
-
28
- class Minitest::Test
29
- def windows?
30
- RbConfig::CONFIG['host_os'] =~ /win|ming/
31
- end
32
-
33
- def disk_root
34
- "#{windows? ? File.expand_path(__FILE__).split('/').first : nil}/"
35
- end
36
-
37
- def empty_document options = {}
38
- if options[:parse]
39
- (Asciidoctor::Document.new [], options).parse
40
- else
41
- Asciidoctor::Document.new [], options
42
- end
43
- end
44
-
45
- def empty_safe_document options = {}
46
- options[:safe] = :safe
47
- Asciidoctor::Document.new [], options
48
- end
49
-
50
- def sample_doc_path(name)
51
- name = name.to_s
52
- unless name.include?('.')
53
- ['asciidoc', 'txt'].each do |ext|
54
- if File.exist?(fixture_path("#{name}.#{ext}"))
55
- name = "#{name}.#{ext}"
56
- break
57
- end
58
- end
59
- end
60
- fixture_path(name)
61
- end
62
-
63
- def fixture_path(name)
64
- File.join(File.expand_path(File.dirname(__FILE__)), 'fixtures', name)
65
- end
66
-
67
- def example_document(name, opts = {})
68
- document_from_string File.read(sample_doc_path(name)), opts
69
- end
70
-
71
- def assert_difference(expression, difference = 1, message = nil, &block)
72
- expressions = [expression]
73
-
74
- exps = expressions.map { |e|
75
- e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
76
- }
77
- before = exps.map { |e| e.call }
78
-
79
- yield
80
-
81
- expressions.zip(exps).each_with_index do |(code, e), i|
82
- error = "#{code.inspect} didn't change by #{difference}"
83
- error = "#{message}.\n#{error}" if message
84
- assert_equal(before[i] + difference, e.call, error)
85
- end
86
- end
87
-
88
- def xmlnodes_at_css(css, content, count = nil)
89
- xmlnodes_at_path(:css, css, content)
90
- end
91
-
92
- def xmlnodes_at_xpath(xpath, content, count = nil)
93
- xmlnodes_at_path(:xpath, xpath, content)
94
- end
95
-
96
- def xmlnodes_at_path(type, path, content, count = nil)
97
- doc = xmldoc_from_string content
98
- case type
99
- when :xpath
100
- namespaces = doc.respond_to?(:root) ? doc.root.namespaces : {}
101
- results = doc.xpath("#{path.sub('/', './')}", namespaces)
102
- when :css
103
- results = doc.css(path)
104
- end
105
- count == 1 ? results.first : results
106
- end
107
-
108
- # Generate an xpath attribute matcher that matches a name in the class attribute
109
- def contains_class(name)
110
- %(contains(concat(' ', normalize-space(@class), ' '), ' #{name} '))
111
- end
112
-
113
- def assert_css(css, content, count = nil)
114
- assert_path(:css, css, content, count)
115
- end
116
-
117
- def assert_xpath(xpath, content, count = nil)
118
- assert_path(:xpath, xpath, content, count)
119
- end
120
-
121
- def assert_path(type, path, content, count = nil)
122
- case type
123
- when :xpath
124
- type_name = 'XPath'
125
- when :css
126
- type_name = 'CSS'
127
- end
128
-
129
- results = xmlnodes_at_path type, path, content
130
-
131
- if (count == true || count == false)
132
- if (count != results)
133
- flunk "#{type_name} #{path} yielded #{results} rather than #{count} for:\n#{content}"
134
- else
135
- assert true
136
- end
137
- elsif (count && results.length != count)
138
- flunk "#{type_name} #{path} yielded #{results.length} elements rather than #{count} for:\n#{content}"
139
- elsif (count.nil? && results.empty?)
140
- flunk "#{type_name} #{path} not found in:\n#{content}"
141
- else
142
- assert true
143
- end
144
- end
145
-
146
- def xmldoc_from_string(content)
147
- if content.match(RE_XMLNS_ATTRIBUTE)
148
- doc = Nokogiri::XML::Document.parse(content)
149
- elsif !(doctype_match = content.match(RE_DOCTYPE))
150
- doc = Nokogiri::HTML::DocumentFragment.parse(content)
151
- elsif doctype_match[1].start_with? 'html'
152
- doc = Nokogiri::HTML::Document.parse(content)
153
- else
154
- doc = Nokogiri::XML::Document.parse(content)
155
- end
156
- end
157
-
158
- def document_from_string(src, opts = {})
159
- assign_default_test_options opts
160
- if opts[:parse]
161
- (Asciidoctor::Document.new src.lines.entries, opts).parse
162
- else
163
- Asciidoctor::Document.new src.lines.entries, opts
164
- end
165
- end
166
-
167
- def block_from_string(src, opts = {})
168
- opts[:header_footer] = false
169
- doc = document_from_string src, opts
170
- doc.blocks.first
171
- end
172
-
173
- def render_string(src, opts = {})
174
- keep_namespaces = opts.delete(:keep_namespaces)
175
- if keep_namespaces
176
- document_from_string(src, opts).render
177
- else
178
- # this is required because nokogiri is ignorant
179
- result = document_from_string(src, opts).render
180
- result = result.sub(RE_XMLNS_ATTRIBUTE, '') if result
181
- result
182
- end
183
- end
184
-
185
- def render_embedded_string(src, opts = {})
186
- opts[:header_footer] = false
187
- document_from_string(src, opts).render
188
- end
189
-
190
- def parse_header_metadata(source)
191
- reader = Asciidoctor::Reader.new source.split ::Asciidoctor::EOL
192
- [::Asciidoctor::Parser.parse_header_metadata(reader), reader]
193
- end
194
-
195
- def assign_default_test_options(opts)
196
- opts[:header_footer] = true unless opts.key? :header_footer
197
- opts[:parse] = true unless opts.key? :parse
198
- if opts[:header_footer]
199
- # don't embed stylesheet unless test requests the default behavior
200
- if opts.has_key? :linkcss_default
201
- opts.delete(:linkcss_default)
202
- else
203
- opts[:attributes] ||= {}
204
- opts[:attributes]['linkcss'] = ''
205
- end
206
- end
207
- if (template_dir = ENV['TEMPLATE_DIR'])
208
- opts[:template_dir] = template_dir unless opts.has_key? :template_dir
209
- #opts[:template_dir] = File.join(File.dirname(__FILE__), '..', '..', 'asciidoctor-backends', 'erb') unless opts.has_key? :template_dir
210
- end
211
- nil
212
- end
213
-
214
- # Expand the character for an entity such as &#8212; into a glyph
215
- # so it can be used to match in an XPath expression
216
- #
217
- # Examples
218
- #
219
- # expand_entity 60
220
- # # => "<"
221
- #
222
- # Returns the String entity expanded to its equivalent UTF-8 glyph
223
- def expand_entity(number)
224
- [number].pack('U*')
225
- end
226
- alias :entity :expand_entity
227
-
228
- def invoke_cli_with_filenames(argv = [], filenames = [], &block)
229
-
230
- filepaths = Array.new
231
-
232
- filenames.each { |filename|
233
- if filenames.nil?|| ::Pathname.new(filename).absolute?
234
- filepaths.push(filename)
235
- else
236
- filepaths.push(File.join(File.dirname(__FILE__), 'fixtures', filename))
237
- end
238
- }
239
-
240
- invoker = Asciidoctor::Cli::Invoker.new(argv + filepaths)
241
-
242
- invoker.invoke!(&block)
243
- invoker
244
- end
245
-
246
- def invoke_cli_to_buffer(argv = [], filename = 'sample.asciidoc', &block)
247
- invoke_cli(argv, filename, [StringIO.new, StringIO.new], &block)
248
- end
249
-
250
- def invoke_cli(argv = [], filename = 'sample.asciidoc', buffers = nil, &block)
251
- if filename.nil? || filename == '-' || ::Pathname.new(filename).absolute?
252
- filepath = filename
253
- else
254
- filepath = File.join(File.dirname(__FILE__), 'fixtures', filename)
255
- end
256
- invoker = Asciidoctor::Cli::Invoker.new(argv + [filepath])
257
- if buffers
258
- invoker.redirect_streams(*buffers)
259
- end
260
- invoker.invoke!(&block)
261
- invoker
262
- end
263
-
264
- def redirect_streams
265
- old_stdout, $stdout = $stdout, (tmp_stdout = ::StringIO.new)
266
- old_stderr, $stderr = $stderr, (tmp_stderr = ::StringIO.new)
267
- begin
268
- yield tmp_stdout, tmp_stderr
269
- ensure
270
- $stdout = old_stdout
271
- $stderr = old_stderr
272
- end
273
- end
274
-
275
- def resolve_localhost
276
- (RUBY_VERSION < '1.9' || RUBY_ENGINE == 'rbx') ? Socket.gethostname :
277
- Socket.ip_address_list.find {|addr| addr.ipv4? }.ip_address
278
- end
279
-
280
- def using_test_webserver host = resolve_localhost, port = 9876
281
- server = TCPServer.new host, port
282
- base_dir = File.expand_path File.dirname __FILE__
283
- t = Thread.new do
284
- while (session = server.accept)
285
- request = session.gets
286
- resource = nil
287
- if (m = /GET (\S+) HTTP\/1\.1$/.match(request.chomp))
288
- resource = (resource = m[1]) == '' ? '.' : resource
289
- else
290
- session.print %(HTTP/1.1 405 Method Not Allowed\r\nContent-Type: text/plain\r\n\r\n)
291
- session.print %(405 - Method not allowed\n)
292
- session.close
293
- break
294
- end
295
-
296
- if resource == '/name/asciidoctor'
297
- session.print %(HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n)
298
- session.print %({"name": "asciidoctor"}\n)
299
- elsif File.file?(resource_file = (File.join base_dir, resource))
300
- mimetype = if (ext = ::File.extname(resource_file)[1..-1])
301
- ext == 'adoc' ? 'text/plain' : %(image/#{ext})
302
- else
303
- 'text/plain'
304
- end
305
- session.print %(HTTP/1.1 200 OK\r\nContent-Type: #{mimetype}\r\n\r\n)
306
- File.open resource_file, 'rb' do |fd|
307
- until fd.eof? do
308
- buffer = fd.read 256
309
- session.write buffer
310
- end
311
- end
312
- else
313
- session.print %(HTTP/1.1 404 File Not Found\r\nContent-Type: text/plain\r\n\r\n)
314
- session.print %(404 - Resource not found.\n)
315
- end
316
- session.close
317
- end
318
- end
319
- begin
320
- yield
321
- ensure
322
- begin
323
- server.shutdown
324
- # "Errno::ENOTCONN: Socket is not connected' is reported on some platforms; call #close instead of #shutdown
325
- rescue Errno::ENOTCONN
326
- server.close
327
- end
328
- t.exit
329
- end
330
- end
331
- end
332
-
333
- ###
334
- #
335
- # Context goodness provided by @citrusbyte's contest.
336
- # See https://github.com/citrusbyte/contest
337
- #
338
- ###
339
-
340
- # Contest adds +teardown+, +test+ and +context+ as class methods, and the
341
- # instance methods +setup+ and +teardown+ now iterate on the corresponding
342
- # blocks. Note that all setup and teardown blocks must be defined with the
343
- # block syntax. Adding setup or teardown instance methods defeats the purpose
344
- # of this library.
345
- class Minitest::Test
346
- def self.setup(&block)
347
- define_method :setup do
348
- super(&block)
349
- instance_eval(&block)
350
- end
351
- end
352
-
353
- def self.teardown(&block)
354
- define_method :teardown do
355
- instance_eval(&block)
356
- super(&block)
357
- end
358
- end
359
-
360
- def self.context(*name, &block)
361
- subclass = Class.new(self)
362
- remove_tests(subclass)
363
- subclass.class_eval(&block) if block_given?
364
- const_set(context_name(name.join(" ")), subclass)
365
- end
366
-
367
- def self.test(name, &block)
368
- define_method(test_name(name), &block)
369
- end
370
-
371
- class << self
372
- alias_method :should, :test
373
- alias_method :describe, :context
374
- end
375
-
376
- private
377
-
378
- def self.context_name(name)
379
- "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
380
- end
381
-
382
- def self.test_name(name)
383
- "test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym
384
- end
385
-
386
- def self.sanitize_name(name)
387
- name.gsub(/\W+/, ' ').strip
388
- end
389
-
390
- def self.remove_tests(subclass)
391
- subclass.public_instance_methods.grep(/^test_/).each do |meth|
392
- subclass.send(:undef_method, meth.to_sym)
393
- end
394
- end
395
- end
396
-
397
- def context(*name, &block)
398
- Minitest::Test.context(name, &block)
399
- end