html2fortitude 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec-local +4 -0
- data/.travis.yml +16 -0
- data/.yardopts +1 -0
- data/Gemfile +5 -0
- data/MIT-LICENSE +38 -0
- data/README.md +97 -0
- data/Rakefile +29 -0
- data/bin/html2fortitude +7 -0
- data/html2fortitude.gemspec +31 -0
- data/lib/html2fortitude.rb +6 -0
- data/lib/html2fortitude/html.rb +755 -0
- data/lib/html2fortitude/html/erb.rb +156 -0
- data/lib/html2fortitude/run.rb +103 -0
- data/lib/html2fortitude/source_template.rb +93 -0
- data/lib/html2fortitude/version.rb +3 -0
- data/spec/helpers/global_helper.rb +6 -0
- data/spec/helpers/html2fortitude_result.rb +71 -0
- data/spec/helpers/standard_helper.rb +70 -0
- data/spec/system/basic_system_spec.rb +13 -0
- data/spec/system/command_line_spec.rb +411 -0
- data/spec/system/erb_system_spec.rb +208 -0
- data/spec/system/needs_system_spec.rb +73 -0
- data/spec/system/options_system_spec.rb +43 -0
- data/spec/system/other_stuff_system_spec.rb +39 -0
- data/spec/system/rails_system_spec.rb +9 -0
- data/spec/system/tags_system_spec.rb +252 -0
- data/spec/system/text_system_spec.rb +106 -0
- data/test/erb_test.rb +546 -0
- data/test/html2fortitude_test.rb +424 -0
- data/test/jruby/erb_test.rb +39 -0
- data/test/jruby/html2fortitude_test.rb +72 -0
- data/test/test_helper.rb +22 -0
- metadata +238 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'erubis'
|
3
|
+
require 'ruby_parser'
|
4
|
+
|
5
|
+
module Html2fortitude
|
6
|
+
class HTML
|
7
|
+
# A class for converting ERB code into a format that's easier
|
8
|
+
# for the {Html2fortitude::HTML} Nokogiri-based parser to understand.
|
9
|
+
#
|
10
|
+
# Uses [Erubis](http://www.kuwata-lab.com/erubis)'s extensible parsing powers
|
11
|
+
# to parse the ERB in a reliable way,
|
12
|
+
# and [ruby_parser](http://parsetree.rubyforge.org/)'s Ruby knowledge
|
13
|
+
# to figure out whether a given chunk of Ruby code starts a block or not.
|
14
|
+
#
|
15
|
+
# The ERB tags are converted to HTML tags in the following way.
|
16
|
+
# `<% ... %>` is converted into `<fortitude_silent> ... </fortitude_silent>`.
|
17
|
+
# `<%= ... %>` is converted into `<fortitude_loud> ... </fortitude_loud>`.
|
18
|
+
# `<%== ... %>` is converted into `<fortitude_loud raw=raw> ... </fortitude_loud>`.
|
19
|
+
# Finally, if either of these opens a Ruby block,
|
20
|
+
# `<fortitude_block> ... </fortitude_block>` will wrap the entire contents of the block -
|
21
|
+
# that is, everything that should be indented beneath the previous silent or loud tag.
|
22
|
+
class ERB < Erubis::Basic::Engine
|
23
|
+
# Compiles an ERB template into a HTML document containing `fortitude_*` tags.
|
24
|
+
#
|
25
|
+
# @param template [String] The ERB template
|
26
|
+
# @return [String] The output document
|
27
|
+
# @see Html2fortitude::HTML::ERB
|
28
|
+
def self.compile(template)
|
29
|
+
new(template).src
|
30
|
+
end
|
31
|
+
|
32
|
+
# The ERB-to-Fortitudeized-HTML conversion has no preamble.
|
33
|
+
def add_preamble(src); end
|
34
|
+
|
35
|
+
# The ERB-to-Fortitudeized-HTML conversion has no postamble.
|
36
|
+
def add_postamble(src); end
|
37
|
+
|
38
|
+
# Concatenates the text onto the source buffer.
|
39
|
+
#
|
40
|
+
# @param src [String] The source buffer
|
41
|
+
# @param text [String] The raw text to add to the buffer
|
42
|
+
def add_text(src, text)
|
43
|
+
src << text
|
44
|
+
end
|
45
|
+
|
46
|
+
# Concatenates a silent Ruby statement onto the source buffer.
|
47
|
+
# This uses the `<fortitude_silent>` tag,
|
48
|
+
# and may close and/or open a Ruby block with the `<fortitude_block>` tag.
|
49
|
+
#
|
50
|
+
# In particular, a block is closed if this statement is some form of `end`,
|
51
|
+
# opened if it's a block opener like `do`, `if`, or `begin`,
|
52
|
+
# and both closed and opened if it's a mid-block keyword
|
53
|
+
# like `else` or `when`.
|
54
|
+
#
|
55
|
+
# @param src [String] The source buffer
|
56
|
+
# @param code [String] The Ruby statement to add to the buffer
|
57
|
+
def add_stmt(src, code)
|
58
|
+
src << '</fortitude_block>' if block_closer?(code) || mid_block?(code)
|
59
|
+
src << '<fortitude_silent>' << h(code) << '</fortitude_silent>' unless code.strip == "end"
|
60
|
+
src << '<fortitude_block>' if block_opener?(code) || mid_block?(code)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Concatenates a Ruby expression that's printed to the document
|
64
|
+
# onto the source buffer.
|
65
|
+
# This uses the `<fortitude:silent>` tag,
|
66
|
+
# and may open a Ruby block with the `<fortitude:block>` tag.
|
67
|
+
# An expression never closes a block.
|
68
|
+
#
|
69
|
+
# @param src [String] The source buffer
|
70
|
+
# @param code [String] The Ruby expression to add to the buffer
|
71
|
+
def add_expr_literal(src, code)
|
72
|
+
src << '<fortitude_loud>' << h(code) << '</fortitude_loud>'
|
73
|
+
src << '<fortitude_block>' if block_opener?(code)
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_expr_escaped(src, code)
|
77
|
+
src << "<fortitude_loud raw=raw>" << h(code) << "</fortitude_loud>"
|
78
|
+
end
|
79
|
+
|
80
|
+
# `html2fortitude` doesn't support debugging expressions.
|
81
|
+
def add_expr_debug(src, code)
|
82
|
+
# TODO ageweke
|
83
|
+
# raise Haml::Error.new("html2haml doesn't support debugging expressions.")
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# HTML-escaped some text (in practice, always Ruby code).
|
89
|
+
# A utility method.
|
90
|
+
#
|
91
|
+
# @param text [String] The text to escape
|
92
|
+
# @return [String] The escaped text
|
93
|
+
def h(text)
|
94
|
+
CGI.escapeHTML(text)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns whether the code is valid Ruby code on its own.
|
98
|
+
#
|
99
|
+
# @param code [String] Ruby code to check
|
100
|
+
# @return [Boolean]
|
101
|
+
def valid_ruby?(code)
|
102
|
+
RubyParser.new.parse(code)
|
103
|
+
rescue Racc::ParseError, RubyParser::SyntaxError
|
104
|
+
false
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns whether the code has any content
|
108
|
+
# This is used to test whether lines have been removed by erubis, such as comments
|
109
|
+
#
|
110
|
+
# @param code [String] Ruby code to check
|
111
|
+
# @return [Boolean]
|
112
|
+
def has_code?(code)
|
113
|
+
return false if code == "\n"
|
114
|
+
return false if valid_ruby?(code) == nil
|
115
|
+
true
|
116
|
+
end
|
117
|
+
|
118
|
+
# Checks if a string of Ruby code opens a block.
|
119
|
+
# This could either be something like `foo do |a|`
|
120
|
+
# or a keyword that requires a matching `end`
|
121
|
+
# like `if`, `begin`, or `case`.
|
122
|
+
#
|
123
|
+
# @param code [String] Ruby code to check
|
124
|
+
# @return [Boolean]
|
125
|
+
def block_opener?(code)
|
126
|
+
return unless has_code?(code)
|
127
|
+
valid_ruby?(code + "\nend") ||
|
128
|
+
valid_ruby?(code + "\nwhen foo\nend")
|
129
|
+
end
|
130
|
+
|
131
|
+
# Checks if a string of Ruby code closes a block.
|
132
|
+
# This is always `end` followed optionally by some method calls.
|
133
|
+
#
|
134
|
+
# @param code [String] Ruby code to check
|
135
|
+
# @return [Boolean]
|
136
|
+
def block_closer?(code)
|
137
|
+
return unless has_code?(code)
|
138
|
+
valid_ruby?("begin\n" + code)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Checks if a string of Ruby code comes in the middle of a block.
|
142
|
+
# This could be a keyword like `else`, `rescue`, or `when`,
|
143
|
+
# or even `end` with a method call that takes a block.
|
144
|
+
#
|
145
|
+
# @param code [String] Ruby code to check
|
146
|
+
# @return [Boolean]
|
147
|
+
def mid_block?(code)
|
148
|
+
return unless has_code?(code)
|
149
|
+
return if valid_ruby?(code)
|
150
|
+
valid_ruby?("if foo\n#{code}\nend") || # else, elsif
|
151
|
+
valid_ruby?("begin\n#{code}\nend") || # rescue, ensure
|
152
|
+
valid_ruby?("case foo\n#{code}\nend") # when
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
require 'find'
|
3
|
+
require 'html2fortitude/source_template'
|
4
|
+
|
5
|
+
module Html2fortitude
|
6
|
+
class Run
|
7
|
+
def initialize(argv)
|
8
|
+
@argv = argv
|
9
|
+
end
|
10
|
+
|
11
|
+
def run!
|
12
|
+
parse_arguments!
|
13
|
+
|
14
|
+
for_each_input_file do |name_and_block|
|
15
|
+
name = name_and_block[:name]
|
16
|
+
block = name_and_block[:block]
|
17
|
+
|
18
|
+
contents = nil
|
19
|
+
block.call { |io| contents = io.read }
|
20
|
+
|
21
|
+
effective_options = trollop_options.select do |key, value|
|
22
|
+
%w{output class_name class_base superclass method assigns do_end new_style_hashes}.include?(key.to_s)
|
23
|
+
end
|
24
|
+
|
25
|
+
source_template = Html2fortitude::SourceTemplate.new(name, contents, effective_options)
|
26
|
+
source_template.write_transformed_content!
|
27
|
+
|
28
|
+
unless @argv.include?("-")
|
29
|
+
puts "#{source_template.filename} -> #{source_template.output_filename} (#{source_template.line_count} lines)"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def for_each_input_file(&block)
|
36
|
+
@argv.each do |file_or_directory|
|
37
|
+
if file_or_directory == '-'
|
38
|
+
block.call({ :name => '-', :block => lambda { |&block| block.call($stdin) } })
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
file_or_directory = File.expand_path(file_or_directory)
|
43
|
+
raise Errno::ENOENT, "No such file or directory: #{file_or_directory}" unless File.exist?(file_or_directory)
|
44
|
+
|
45
|
+
files = [ ]
|
46
|
+
if File.directory?(file_or_directory)
|
47
|
+
Find.find(file_or_directory) do |f|
|
48
|
+
f = File.expand_path(f, file_or_directory)
|
49
|
+
files << f if File.file?(f) && f =~ /\.r?html/
|
50
|
+
end
|
51
|
+
else
|
52
|
+
files << file_or_directory
|
53
|
+
end
|
54
|
+
|
55
|
+
files.each do |file|
|
56
|
+
block.call(:name => file, :block => lambda { |&block| File.open(file, &block) })
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_arguments!
|
62
|
+
trollop_options
|
63
|
+
end
|
64
|
+
|
65
|
+
def trollop_options
|
66
|
+
@trollop_parser ||= Trollop::Parser.new do
|
67
|
+
version "html2fortitude version #{Html2fortitude::VERSION}"
|
68
|
+
banner <<-EOS
|
69
|
+
html2fortitude transforms HTML source files (with or without ERb embedded)
|
70
|
+
into Fortitude (https://github.com/ageweke/fortitude) source code.
|
71
|
+
|
72
|
+
Usage:
|
73
|
+
html2fortitude [options] file|directory [file|directory...]
|
74
|
+
where [options] are:
|
75
|
+
EOS
|
76
|
+
|
77
|
+
opt :output, "Output file or directory", :type => String
|
78
|
+
|
79
|
+
opt :class_name, "Class name for created Fortitude class", :type => String
|
80
|
+
opt :class_base, "Base directory for input files (e.g., my_rails_app/app) to use when --class-name is not specified", :type => String, :short => 'b'
|
81
|
+
opt :superclass, "Name of the class to inherit the output class from", :type => String, :default => 'Fortitude::Widget::Html5'
|
82
|
+
|
83
|
+
opt :method, "Name of method to write in widget (default 'content')", :type => String, :default => 'content'
|
84
|
+
opt :assigns, %{Method for using assigns passed to the widget:
|
85
|
+
needs_defaulted_to_nil: (default) standard Fortitude 'needs', but with a default of 'nil', so all needs are optional
|
86
|
+
required_needs: standard Fortitude 'needs', no default; widget will not render without all needs specified (dangerous)
|
87
|
+
instance_variables: Ruby instance variables; requires that a base class of the widget sets 'use_instance_variables_for_assigns true'
|
88
|
+
no_needs: Omit a 'needs' declaration entirely; requires that a base class sets 'extra_assigns :use'},
|
89
|
+
:type => String, :default => 'needs_defaulted_to_nil'
|
90
|
+
|
91
|
+
opt :do_end, "Use do ... end for blocks passed to tag methods, not { ... } (does not affect blocks from ERb)", :type => :boolean
|
92
|
+
opt :new_style_hashes, "Use hash_style: ruby19 instead of :hash_style => :ruby_18", :type => :boolean
|
93
|
+
end
|
94
|
+
|
95
|
+
@trollop_options ||= begin
|
96
|
+
Trollop::with_standard_exception_handling(@trollop_parser) do
|
97
|
+
raise Trollop::HelpNeeded if @argv.empty? # show help screen
|
98
|
+
@trollop_parser.parse @argv
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'html2fortitude/html'
|
2
|
+
|
3
|
+
module Html2fortitude
|
4
|
+
class SourceTemplate
|
5
|
+
attr_reader :filename, :line_count
|
6
|
+
|
7
|
+
def initialize(filename, contents, options)
|
8
|
+
options.assert_valid_keys(:output, :class_name, :class_base, :superclass, :method, :assigns,
|
9
|
+
:do_end, :new_style_hashes)
|
10
|
+
|
11
|
+
@filename = filename
|
12
|
+
@contents = contents
|
13
|
+
@options = options
|
14
|
+
@line_count = @contents.split(/(\r|\n|\r\n)/).length
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_transformed_content!
|
18
|
+
html_options = {
|
19
|
+
:class_name => output_class_name,
|
20
|
+
:superclass => options[:superclass],
|
21
|
+
:method => options[:method],
|
22
|
+
:assigns => options[:assigns],
|
23
|
+
:do_end => options[:do_end],
|
24
|
+
:new_style_hashes => options[:new_style_hashes]
|
25
|
+
}
|
26
|
+
|
27
|
+
html = HTML.new(contents, html_options).render
|
28
|
+
|
29
|
+
if output_filename == '-'
|
30
|
+
puts html
|
31
|
+
else
|
32
|
+
FileUtils.mkdir_p(File.dirname(output_filename))
|
33
|
+
File.open(output_filename, 'w') { |f| f << html }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def output_filename
|
38
|
+
if (! options[:output]) && (filename == "-")
|
39
|
+
"-"
|
40
|
+
elsif (! options[:output])
|
41
|
+
if filename =~ /^(.*)\.html\.erb$/i || filename =~ /^(.*)\.rhtml$/i
|
42
|
+
"#{$1}.rb"
|
43
|
+
else
|
44
|
+
"#{filename}.rb"
|
45
|
+
end
|
46
|
+
elsif File.directory?(options[:output])
|
47
|
+
File.join(File.expand_path(options[:output]), "#{output_class_name.underscore}.rb")
|
48
|
+
else
|
49
|
+
File.expand_path(options[:output])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
attr_reader :contents, :options
|
55
|
+
|
56
|
+
def output_class_name
|
57
|
+
if options[:class_name]
|
58
|
+
options[:class_name]
|
59
|
+
else
|
60
|
+
cb = class_base
|
61
|
+
if filename.start_with?("#{cb}/")
|
62
|
+
out = filename[(cb.length + 1)..-1].camelize
|
63
|
+
out = $1 if out =~ %r{^(.*?)\.[^/]+$}i
|
64
|
+
out
|
65
|
+
else
|
66
|
+
raise %{You specified a class base using the -b command-line option:
|
67
|
+
#{class_base}
|
68
|
+
but the file you asked to parse is not underneath that directory:
|
69
|
+
#{filename}}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def class_base
|
75
|
+
File.expand_path(options[:class_base] || infer_class_base)
|
76
|
+
end
|
77
|
+
|
78
|
+
def infer_class_base
|
79
|
+
if filename =~ %r{^(.*app)/views/.*$}
|
80
|
+
File.expand_path($1)
|
81
|
+
elsif filename == "-"
|
82
|
+
raise %{When converting standard input, you must specify a name for the output class
|
83
|
+
using the -c command-line option. (Otherwise, we have no way of knowing what to name this widget!)}
|
84
|
+
else
|
85
|
+
raise %{We can't figure out what the name of the widget class for this file should be:
|
86
|
+
#{filename}
|
87
|
+
You must either specify an explicit name for the class, using the -c command-line option, or
|
88
|
+
specify a base directory to infer the class name from, using the -b command-line option
|
89
|
+
(e.g., "-b my_rails_app/app").}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Html2FortitudeResult
|
2
|
+
attr_reader :needs, :class_name, :superclass, :method_name
|
3
|
+
|
4
|
+
def initialize(text)
|
5
|
+
lines = text.split(/[\r\n]/)
|
6
|
+
if lines.shift =~ /^\s*class\s*(\S+)\s+<\s+(\S+)\s*$/i
|
7
|
+
@class_name = $1
|
8
|
+
@superclass = $2
|
9
|
+
else
|
10
|
+
raise "Can't find 'class' declaration in: #{text}"
|
11
|
+
end
|
12
|
+
|
13
|
+
@needs = { }
|
14
|
+
|
15
|
+
lines.shift while lines[0] =~ /^\s*$/i
|
16
|
+
|
17
|
+
while lines[0] =~ /^\s*needs\s*(.*?)\s*$/i
|
18
|
+
need_name = $1
|
19
|
+
need_value = nil
|
20
|
+
|
21
|
+
if need_name =~ /^(.*?)\s*=>\s*(.*?)\s*$/i
|
22
|
+
need_name = $1
|
23
|
+
need_value = $2
|
24
|
+
end
|
25
|
+
|
26
|
+
@needs[need_name] = need_value
|
27
|
+
|
28
|
+
lines.shift
|
29
|
+
end
|
30
|
+
|
31
|
+
lines.shift while lines[0] =~ /^\s*$/i
|
32
|
+
|
33
|
+
if lines[0] =~ /^\s+def\s+(\S+)\s*$/i
|
34
|
+
@method_name = $1
|
35
|
+
lines.shift
|
36
|
+
else
|
37
|
+
raise "Can't find 'def' in: #{text}"
|
38
|
+
end
|
39
|
+
|
40
|
+
lines.pop while lines[-1] =~ /^\s*$/i
|
41
|
+
if lines[-1] =~ /^\s*end\s*$/i
|
42
|
+
lines.pop
|
43
|
+
else
|
44
|
+
raise "Can't find last 'end' in: #{text}"
|
45
|
+
end
|
46
|
+
|
47
|
+
lines.pop while lines[-1] =~ /^\s*$/i
|
48
|
+
if lines[-1] =~ /^\s*end\s*$/i
|
49
|
+
lines.pop
|
50
|
+
else
|
51
|
+
raise "Can't find last 'end' in: #{text}"
|
52
|
+
end
|
53
|
+
|
54
|
+
@content_lines = lines
|
55
|
+
@content_lines = @content_lines.map do |content_line|
|
56
|
+
content_line = content_line.rstrip
|
57
|
+
if content_line[0..3] == ' '
|
58
|
+
content_line[4..-1]
|
59
|
+
else
|
60
|
+
content_line
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def content_text
|
66
|
+
@content_lines.join("\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
attr_reader :text
|
71
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'helpers/html2fortitude_result'
|
2
|
+
require 'html2fortitude/html'
|
3
|
+
|
4
|
+
module StandardHelper
|
5
|
+
def default_html_options
|
6
|
+
{
|
7
|
+
:class_name => "SpecClass",
|
8
|
+
:superclass => "Fortitude::Widget::Html5",
|
9
|
+
:method => "content",
|
10
|
+
:assigns => :needs_defaulted_to_nil,
|
11
|
+
:do_end => false,
|
12
|
+
:new_style_hashes => false
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def h2f(input, options = { })
|
17
|
+
Html2FortitudeResult.new(Html2fortitude::HTML.new(input, default_html_options.merge(options)).render)
|
18
|
+
end
|
19
|
+
|
20
|
+
def h2f_content(input, options = { })
|
21
|
+
h2f(input, options).content_text
|
22
|
+
end
|
23
|
+
|
24
|
+
def h2f_from(filename)
|
25
|
+
Html2FortitudeResult.new(get(filename))
|
26
|
+
end
|
27
|
+
|
28
|
+
def invoke(*args)
|
29
|
+
cmd = "#{binary_path} #{args.join(" ")} 2>&1"
|
30
|
+
output = `#{cmd}`
|
31
|
+
unless $?.success?
|
32
|
+
raise "Invocation failed: ran: #{cmd}\nin: #{Dir.pwd}\nand got: #{$?.inspect}\nwith output:\n#{output}"
|
33
|
+
end
|
34
|
+
output
|
35
|
+
end
|
36
|
+
|
37
|
+
def splat!(filename, data)
|
38
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
39
|
+
File.open(filename, 'w') { |f| f << data }
|
40
|
+
end
|
41
|
+
|
42
|
+
def get(filename)
|
43
|
+
raise Errno::ENOENT, "No such file: #{filename.inspect}" unless File.file?(filename)
|
44
|
+
File.read(filename).strip
|
45
|
+
end
|
46
|
+
|
47
|
+
def with_temp_directory(name, &block)
|
48
|
+
directory = File.join(temp_directory_base, name)
|
49
|
+
FileUtils.rm_rf(directory) if File.exist?(directory)
|
50
|
+
FileUtils.mkdir_p(directory)
|
51
|
+
Dir.chdir(directory, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def temp_directory_base
|
56
|
+
@temp_directory_base ||= begin
|
57
|
+
out = File.join(gem_root, 'tmp', 'specs')
|
58
|
+
FileUtils.mkdir_p(out)
|
59
|
+
out
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def gem_root
|
64
|
+
@gem_root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
65
|
+
end
|
66
|
+
|
67
|
+
def binary_path
|
68
|
+
@binary_path ||= File.join(gem_root, 'bin', 'html2fortitude')
|
69
|
+
end
|
70
|
+
end
|