mokuji 0.2.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Mokuji.gemspec +2 -2
- data/README +0 -1
- data/Rakefile +6 -13
- data/bin/mokuji +24 -71
- data/lib/mokuji.rb +75 -8
- data/lib/mokuji/converter.rb +158 -171
- data/lib/mokuji/exporter.rb +42 -54
- data/lib/mokuji/scanner.rb +82 -130
- data/lib/mokuji/validators.rb +67 -0
- data/lib/mokuji/version.rb +3 -7
- data/spec/converter_spec.rb +31 -59
- data/spec/exporter_spec.rb +27 -44
- data/spec/scanner_spec.rb +31 -48
- metadata +5 -7
- data/lib/mokuji/initializer.rb +0 -95
- data/spec/initializer_spec.rb +0 -42
data/Mokuji.gemspec
CHANGED
@@ -11,8 +11,8 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.authors = ['Icid Asset']
|
12
12
|
s.email = ['icid.asset@gmail.com']
|
13
13
|
s.homepage = 'http://icidasset.heroku.com/'
|
14
|
-
s.summary = %q{Mokuji
|
15
|
-
s.description = %q{Make a list from
|
14
|
+
s.summary = %q{Mokuji recursively lists a directory by its path.}
|
15
|
+
s.description = %q{Make a recursive list from a directory its contents and export it in html, json or plain-text}
|
16
16
|
|
17
17
|
s.rubyforge_project = "mokuji"
|
18
18
|
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
|
-
|
4
3
|
unless ENV['NOBUNDLE']
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
rescue LoadError
|
12
|
-
|
13
|
-
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
14
|
-
|
15
|
-
end
|
16
|
-
|
4
|
+
begin
|
5
|
+
require 'bundler'
|
6
|
+
Bundler::GemHelper.install_tasks
|
7
|
+
rescue LoadError
|
8
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
9
|
+
end
|
17
10
|
end
|
data/bin/mokuji
CHANGED
@@ -5,78 +5,31 @@ require 'mokuji'
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'thor'
|
7
7
|
|
8
|
-
|
9
8
|
class Moki < Thor
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
exit
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
# Check if the directory isn't empty
|
40
|
-
if Dir.entries(path_to_scan).slice(2..-1).empty? then
|
41
|
-
|
42
|
-
say "The directory that you want to scan, is empty."
|
43
|
-
|
44
|
-
exit
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
# New Mokuji
|
49
|
-
moki = Mokuji::Initializer.new
|
50
|
-
moki.path_to_scan = path_to_scan
|
51
|
-
|
52
|
-
# Export path check if given
|
53
|
-
if export_path then
|
54
|
-
|
55
|
-
unless File.directory?(export_path) then
|
56
|
-
|
57
|
-
say "The directory that you want to export to, does not exist.", :red
|
58
|
-
|
59
|
-
exit
|
60
|
-
|
61
|
-
else
|
62
|
-
|
63
|
-
moki.export_path = export_path
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
# Please continue
|
70
|
-
moki.converting_method = output_type.to_sym
|
71
|
-
moki.execute
|
72
|
-
|
73
|
-
say "Directory list successfully created! =D", :green
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
|
9
|
+
desc "list PATH (EXPORT_PATH)", "Recursively list a directory by its path."
|
10
|
+
long_desc %Q{
|
11
|
+
Recursively list a directory by its path.
|
12
|
+
You can also set the export path for the file.
|
13
|
+
Both can be relative paths.
|
14
|
+
The default export path is the same as the first path.
|
15
|
+
}
|
16
|
+
|
17
|
+
method_options :show_dot_files => :boolean, :output_type => :string
|
18
|
+
|
19
|
+
def list import_path, export_path = nil
|
20
|
+
# Convert the paths to absolute paths
|
21
|
+
import_path = File.expand_path(import_path)
|
22
|
+
export_path = File.expand_path(export_path) if export_path
|
23
|
+
|
24
|
+
# New list
|
25
|
+
begin
|
26
|
+
Mokuji.configure options
|
27
|
+
Mokuji.make_list import_path, export_path
|
28
|
+
say "Your list has been cooked successfully!", :green
|
29
|
+
rescue RuntimeError => error_message
|
30
|
+
say error_message.to_s, :red
|
31
|
+
end
|
32
|
+
end
|
79
33
|
end
|
80
34
|
|
81
|
-
|
82
35
|
Moki.start
|
data/lib/mokuji.rb
CHANGED
@@ -1,11 +1,78 @@
|
|
1
|
-
require 'mokuji/
|
1
|
+
require 'mokuji/validators'
|
2
|
+
require 'mokuji/scanner'
|
3
|
+
require 'mokuji/converter'
|
4
|
+
require 'mokuji/exporter'
|
2
5
|
|
3
6
|
module Mokuji
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
#
|
8
|
+
# === Info
|
9
|
+
#
|
10
|
+
# Mokuji makes recursive lists of directories
|
11
|
+
# and outputs it in html, plain-html, json or plain-text files.
|
12
|
+
#
|
13
|
+
# === How to use
|
14
|
+
#
|
15
|
+
# require 'mokuji'
|
16
|
+
#
|
17
|
+
# Mokuji.make_list import_path, export_path # export path is optional
|
18
|
+
#
|
19
|
+
# === You could also
|
20
|
+
#
|
21
|
+
# Mokuji.configure :hide_dot_files => false
|
22
|
+
# Mokuji.make_list import_path # Make a list with the dot files included
|
23
|
+
# Mokuji.configure :output_type => 'json'
|
24
|
+
# Mokuji.make_list import_path # Make another list in the json format
|
25
|
+
#
|
26
|
+
# === Example with Thor
|
27
|
+
#
|
28
|
+
# begin
|
29
|
+
# Mokuji.configure options
|
30
|
+
# Mokuji.make_list import_path, export_path
|
31
|
+
# say "BOOM! DONE!", :green
|
32
|
+
# rescue RuntimeError => error_message
|
33
|
+
# say error_message.to_s, :red
|
34
|
+
# end
|
35
|
+
|
36
|
+
LIB_PATH = File.expand_path File.dirname(__FILE__)
|
37
|
+
|
38
|
+
DEFAULTS = {
|
39
|
+
'show_dot_files' => false, # Scanner options
|
40
|
+
'output_type' => 'html', # Converter options
|
41
|
+
'list_name' => nil # Global options
|
42
|
+
}
|
43
|
+
|
44
|
+
def self.configure options = {}
|
45
|
+
Mokuji::Validators.validate_options(options)
|
46
|
+
@config = unless @config
|
47
|
+
DEFAULTS.merge(options)
|
48
|
+
else
|
49
|
+
@config.merge(options)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.configuration
|
54
|
+
return @config ||= DEFAULTS.clone
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.make_list import_path, export_path = nil
|
58
|
+
scan_results = self.scan import_path
|
59
|
+
converter_results = self.convert(scan_results)
|
60
|
+
export_path ||= import_path
|
61
|
+
self.export converter_results, export_path
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.scanner; Mokuji::Scanner.new; end
|
65
|
+
def self.scan path
|
66
|
+
return self.scanner.scan(path)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.converter; Mokuji::Converter.new; end
|
70
|
+
def self.convert hash
|
71
|
+
return self.converter.convert(hash)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.exporter; Mokuji::Exporter.new; end
|
75
|
+
def self.export string, export_path
|
76
|
+
return self.exporter.export(string, export_path)
|
77
|
+
end
|
11
78
|
end
|
data/lib/mokuji/converter.rb
CHANGED
@@ -1,175 +1,162 @@
|
|
1
|
-
|
1
|
+
require 'mokuji/validators'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Mokuji
|
4
|
+
#
|
5
|
+
# { CONVERTER }
|
6
|
+
#
|
7
|
+
# === Info
|
8
|
+
#
|
9
|
+
# Converts the data from the scanner to JSON or HTML
|
10
|
+
#
|
11
|
+
# === Output example : String
|
12
|
+
#
|
13
|
+
# <html>
|
14
|
+
# ...
|
15
|
+
# <body>
|
16
|
+
# <h1>Icid</h1>
|
17
|
+
# <h2>19 April 2011 (03:47PM)</h2>
|
18
|
+
# <nav>
|
19
|
+
# <a id="expand_all">Expand all directories</a> ---
|
20
|
+
# <a id="close_all">Close all directories</a>
|
21
|
+
# </nav>
|
22
|
+
# <ul id="list"><li class="file">file.txt</li></ul>
|
23
|
+
# </body>
|
24
|
+
# ...
|
25
|
+
# </html>
|
26
|
+
#
|
27
|
+
# === How to use
|
28
|
+
#
|
29
|
+
# converter = Mokuji::Converter.new
|
30
|
+
# converter_results = converter.convert data_from_scanner
|
9
31
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
</body>
|
140
|
-
</html>
|
141
|
-
|
142
|
-
}.strip.gsub(/\t/, '')
|
143
|
-
|
144
|
-
end
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
def toHTML_readContentsFrom array
|
149
|
-
|
150
|
-
html = ''
|
151
|
-
|
152
|
-
array.each do |hash|
|
153
|
-
|
154
|
-
if hash['type'] == 'directory' then
|
155
|
-
|
156
|
-
html << '<li class="directory"><span>' + hash['name'] + '</span>'
|
157
|
-
html << '<ul>' + toHTML_readContentsFrom( hash['contents'] ) + '</ul></li>'
|
158
|
-
|
159
|
-
else
|
160
|
-
|
161
|
-
html << '<li class="file">' + hash['name'] + '</li>'
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
end
|
166
|
-
|
167
|
-
return html
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
end # </Converter>
|
32
|
+
class Converter
|
33
|
+
include Mokuji::Validators
|
34
|
+
|
35
|
+
attr_reader :data_from_scanner, :output_type, :list_name, :time
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
validate_configuration
|
39
|
+
end
|
40
|
+
|
41
|
+
def convert hash
|
42
|
+
validate_data_from_scanner hash
|
43
|
+
|
44
|
+
@data_from_scanner = hash
|
45
|
+
@output_type = Mokuji::configuration['output_type']
|
46
|
+
@list_name = (Mokuji::configuration['list_name'] ||= hash['name'])
|
47
|
+
@time = Time.now.strftime('%d %B %Y (%I:%M%p)')
|
48
|
+
|
49
|
+
return data = case output_type
|
50
|
+
when 'json' then to_json
|
51
|
+
when 'html' then to_html
|
52
|
+
when 'plain_html' then to_html_plain
|
53
|
+
when 'plain_text' then to_plain_text
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def to_json
|
60
|
+
require 'json'
|
61
|
+
|
62
|
+
hash = {
|
63
|
+
'list_name' => list_name,
|
64
|
+
'made_on' => time,
|
65
|
+
'contents' => data_from_scanner.to_json
|
66
|
+
}
|
67
|
+
|
68
|
+
return hash.to_json
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_html
|
72
|
+
# Convert the data from the scanner to html
|
73
|
+
html_data = to_html__read_directory data_from_scanner['contents']
|
74
|
+
|
75
|
+
# Loading some assets
|
76
|
+
assets_path = File.join Mokuji::LIB_PATH, '/mokuji/assets/'
|
77
|
+
|
78
|
+
minified_jquery = IO.read("#{assets_path}jquery-1.5.min.js")
|
79
|
+
javascript_code = IO.read("#{assets_path}code.js")
|
80
|
+
stylesheet = IO.read("#{assets_path}stylesheet.css")
|
81
|
+
|
82
|
+
# And push everything into the html template
|
83
|
+
return html_template = %Q{
|
84
|
+
<!doctype html>
|
85
|
+
<html>
|
86
|
+
<head>
|
87
|
+
<meta charset="utf-8">
|
88
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
89
|
+
<title>#{list_name}</title>
|
90
|
+
<style>#{stylesheet}</style>
|
91
|
+
</head>
|
92
|
+
<body>
|
93
|
+
<h1>#{list_name}</h1>
|
94
|
+
<h2>#{time}</h2>
|
95
|
+
<nav>
|
96
|
+
<a id="expand_all">Expand all directories</a> ---
|
97
|
+
<a id="close_all">Close all directories</a>
|
98
|
+
</nav>
|
99
|
+
<ul id="list">#{html_data}</ul>
|
100
|
+
<script>#{minified_jquery}</script>
|
101
|
+
<script>#{javascript_code}</script>
|
102
|
+
</body>
|
103
|
+
</html>
|
104
|
+
}.strip.gsub(/^(\s){8}/, '')
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_html_plain
|
108
|
+
# Convert the data from the scanner to plain html
|
109
|
+
html_data = to_html__read_directory data_from_scanner['contents']
|
110
|
+
|
111
|
+
# And push everything into the html template
|
112
|
+
return html_template = %Q{
|
113
|
+
<!doctype html>
|
114
|
+
<html>
|
115
|
+
<head>
|
116
|
+
<meta charset="utf-8">
|
117
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
118
|
+
<title>#{list_name}</title>
|
119
|
+
</head>
|
120
|
+
<body>
|
121
|
+
<h1>#{list_name}</h1>
|
122
|
+
<h2>#{time}</h2>
|
123
|
+
<ul id="list">#{html_data}</ul>
|
124
|
+
</body>
|
125
|
+
</html>
|
126
|
+
}.strip.gsub(/^(\s){8}/, '')
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_html__read_directory array
|
130
|
+
html = ''
|
131
|
+
|
132
|
+
array.each do |hash|
|
133
|
+
case hash['type']
|
134
|
+
when 'directory'
|
135
|
+
html << "<li class='directory'><span>#{hash['name']}</span>"
|
136
|
+
html << "<ul>#{to_html__read_directory(hash['contents'])}</ul></li>"
|
137
|
+
when 'file'
|
138
|
+
html << "<li class='file'>#{hash['name']}</li>"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
return html
|
143
|
+
end
|
144
|
+
|
145
|
+
def to_plain_text
|
146
|
+
# Convert the data from the scanner to plain text
|
147
|
+
return to_plain_text__read_directory '', data_from_scanner['contents']
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_plain_text__read_directory path, array
|
151
|
+
text = ''
|
152
|
+
|
153
|
+
array.each do |hash|
|
154
|
+
text << "#{path}#{hash['name']}\n"
|
155
|
+
text << to_plain_text__read_directory("#{path}#{hash['name']}/", hash['contents']) if hash['type'] === 'directory'
|
156
|
+
end
|
157
|
+
|
158
|
+
return text
|
159
|
+
end
|
160
|
+
end # </Converter>
|
174
161
|
|
175
162
|
end
|