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.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +72 -5
- data/CONTRIBUTING.adoc +3 -3
- data/Gemfile +23 -0
- data/README-fr.adoc +416 -0
- data/README-jp.adoc +395 -0
- data/README-zh_CN.adoc +414 -0
- data/README.adoc +134 -72
- data/asciidoctor.gemspec +49 -0
- data/data/locale/attributes.adoc +470 -0
- data/data/stylesheets/asciidoctor-default.css +6 -5
- data/lib/asciidoctor.rb +22 -19
- data/lib/asciidoctor/abstract_block.rb +20 -10
- data/lib/asciidoctor/abstract_node.rb +3 -14
- data/lib/asciidoctor/cli/invoker.rb +5 -4
- data/lib/asciidoctor/cli/options.rb +1 -1
- data/lib/asciidoctor/converter/docbook5.rb +1 -1
- data/lib/asciidoctor/converter/factory.rb +1 -5
- data/lib/asciidoctor/converter/html5.rb +36 -31
- data/lib/asciidoctor/converter/manpage.rb +14 -9
- data/lib/asciidoctor/converter/template.rb +8 -4
- data/lib/asciidoctor/core_ext.rb +7 -6
- data/lib/asciidoctor/core_ext/{string → 1.8.7/string}/chr.rb +1 -1
- data/lib/asciidoctor/core_ext/1.8.7/string/limit.rb +28 -0
- data/lib/asciidoctor/core_ext/{symbol → 1.8.7/symbol}/length.rb +1 -1
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +23 -0
- data/lib/asciidoctor/core_ext/string/limit.rb +10 -0
- data/lib/asciidoctor/document.rb +33 -26
- data/lib/asciidoctor/extensions.rb +16 -16
- data/lib/asciidoctor/helpers.rb +1 -1
- data/lib/asciidoctor/list.rb +3 -0
- data/lib/asciidoctor/parser.rb +47 -43
- data/lib/asciidoctor/path_resolver.rb +3 -1
- data/lib/asciidoctor/reader.rb +15 -14
- data/lib/asciidoctor/section.rb +2 -2
- data/lib/asciidoctor/stylesheets.rb +2 -1
- data/lib/asciidoctor/substitutors.rb +44 -46
- data/lib/asciidoctor/table.rb +41 -38
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +11 -4
- data/man/asciidoctor.adoc +7 -1
- data/test/attributes_test.rb +52 -0
- data/test/blocks_test.rb +8 -8
- data/test/document_test.rb +13 -1
- data/test/extensions_test.rb +38 -0
- data/test/invoker_test.rb +15 -0
- data/test/lists_test.rb +78 -53
- data/test/manpage_test.rb +15 -0
- data/test/paths_test.rb +3 -0
- data/test/reader_test.rb +2 -2
- data/test/sections_test.rb +10 -0
- data/test/substitutions_test.rb +12 -6
- data/test/tables_test.rb +76 -2
- metadata +16 -45
- data/lib/asciidoctor/core_ext/object/nil_or_empty.rb +0 -23
- 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 -8
- 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/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -0
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/master.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 -26
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -7
- data/test/fixtures/tip.gif +0 -0
- data/test/test_helper.rb +0 -399
@@ -1 +0,0 @@
|
|
1
|
-
<script src="modernizr.js"></script>
|
data/test/fixtures/circle.svg
DELETED
@@ -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 +0,0 @@
|
|
1
|
-
%p=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>
|
data/test/fixtures/docinfo.html
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
<meta http-equiv="imagetoolbar" content="false">
|
data/test/fixtures/docinfo.xml
DELETED
data/test/fixtures/dot.gif
DELETED
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
|
Binary file
|
@@ -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
|
data/test/fixtures/master.adoc
DELETED
@@ -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
|
-
|
data/test/fixtures/subs.adoc
DELETED
data/test/fixtures/tip.gif
DELETED
Binary file
|
data/test/test_helper.rb
DELETED
@@ -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 — 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
|