directory_listing 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,166 @@
1
+ require 'sinatra/base'
2
+
3
+ require 'truncate'
4
+ require 'filesize'
5
+ require 'pathname'
6
+
7
+ # = Easy, CSS-styled, Apache-like directory listings for Sinatra.
8
+ #
9
+ # == Usage
10
+ #
11
+ # list() will return HTML, so the following is a complete Sinatra
12
+ # app that will provide a directory listing of whatever path you navigate to
13
+ # and let you view any file that is served directly:
14
+ #
15
+ # require 'sinatra'
16
+ # require 'sinatra/directory_listing'
17
+ #
18
+ # get '*' do |path|
19
+ # if File.exist?(File.join(settings.public_folder, path))
20
+ # if File.directory?(File.join(settings.public_folder, path))
21
+ # list()
22
+ # else
23
+ # send_file File.join(settings.public_folder, path)
24
+ # end
25
+ # else
26
+ # not_found
27
+ # end
28
+ # end
29
+ #
30
+ # not_found do
31
+ # 'Try again.'
32
+ # end
33
+ #
34
+ # == Options
35
+ #
36
+ # stylesheet # a stylesheet that will be added to the <head> of the generated directory listing
37
+ # readme # an HTML string that will be appended at the footer of the generated directory listing
38
+ # should_list_invisibles # whether the directory listing should include invisibles (dotfiles) - "yes" or "no"
39
+ # last_modified_format # format for last modified date (http://www.ruby-doc.org/core-2.0/Time.html) - defaults to "%Y-%m-%d %H:%M:%S"
40
+ # filename_truncate_length # (integer) length to truncate file names to - defaults to 40
41
+ #
42
+ # == Styling
43
+ #
44
+ # It's pretty easy to figure out how to style directory_listing by looking at the source, but here are some gotchas:
45
+ #
46
+ # Every item listed is a <td> element in a table. Directories will have a class of "dir" and regular files will have a class of "file".
47
+ #
48
+ # You can style the "File" column with this CSS:
49
+ #
50
+ # table tr > td:first-child {
51
+ # text-align: left;
52
+ # }
53
+ #
54
+ # Second column:
55
+ # table tr > td:first-child + td {
56
+ # text-align: left;
57
+ # }
58
+ #
59
+ # Third column:
60
+ # table tr > td:first-child + td + td {
61
+ # text-align: left;
62
+ # }
63
+
64
+
65
+ module Sinatra
66
+ module Directory_listing
67
+
68
+ private
69
+
70
+ def m_time(file)
71
+ file = File.join(settings.public_folder, request.fullpath)
72
+ time = "\t<td>#{File.mtime(file).strftime $last_modified_format}</td>"
73
+ end
74
+
75
+ def size(file)
76
+ dir = request.path
77
+ if File.directory?(File.join(dir, file))
78
+ "\t<td>-</td>"
79
+ else
80
+ file = File.join(settings.public_folder, request.fullpath)
81
+ size = Filesize.from("#{File.stat(file).size} B").pretty
82
+ "\t<td>#{size}</td>"
83
+ end
84
+ end
85
+
86
+ def name(file)
87
+ tfile = file.truncate($filename_truncate_length, '...')
88
+ if (Pathname.new(request.path).cleanpath).eql?((Pathname.new(settings.public_folder)).cleanpath)
89
+ link = file
90
+ else
91
+ link = File.join(request.fullpath, file)
92
+ end
93
+
94
+ html = ""
95
+ if File.directory?(File.join(settings.public_folder, link))
96
+ html << "\t<td class='dir'><a href='#{link}'>#{tfile}</a></td>"
97
+ else
98
+ html << "\t<td class='file'><a href='#{link}'>#{tfile}</a></td>"
99
+ end
100
+ "#{html}"
101
+ end
102
+
103
+ def wrap(file)
104
+ wrapped = ""
105
+ if $should_list_invisibles == "yes"
106
+ wrapped << "\n\t<tr>
107
+ #{name(file)}
108
+ #{m_time(file)}
109
+ #{size(file)}\n\t</tr>"
110
+ else
111
+ if file[0] != "."
112
+ wrapped << "\n\t<tr>
113
+ #{name(file)}
114
+ #{m_time(file)}
115
+ #{size(file)}\n\t</tr>"
116
+ end
117
+ end
118
+ "#{wrapped}"
119
+ end
120
+
121
+ def list(o={})
122
+ options = {
123
+ :should_list_invisibles => "no",
124
+ :last_modified_format => "%Y-%m-%d %H:%M:%S",
125
+ :filename_truncate_length => 40,
126
+ :stylesheet => "",
127
+ :readme => ""
128
+ }.merge(o)
129
+
130
+ $should_list_invisibles = options[:should_list_invisibles]
131
+ $last_modified_format = options[:last_modified_format]
132
+ $filename_truncate_length = options[:filename_truncate_length]
133
+
134
+ html = "<html>\n<head>\n"
135
+ html << "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
136
+ if options[:stylesheet]
137
+ html << "<link rel=\"stylesheet\" type=\"text/css\" href=\"/#{options[:stylesheet].sub(/^[\/]*/,"")}\">\n"
138
+ end
139
+ html << "</head>\n<body>\n"
140
+ html << "<h1>Index of #{request.path}</h1>\n"
141
+ if request.path != "/"
142
+ html << "<a href='#{Pathname.new(request.path).parent}'>&larr; Parent directory</a><br><br>"
143
+ else
144
+ html << "<a>Root directory</a><br><br>"
145
+ end
146
+ html << "<table>\n"
147
+ html << "\t<tr>\n\t\t<th>File</th>\n\t\t<th>Last modified</th>\n\t\t<th>Size</th>\n\t</tr>\n"
148
+ files = Array.new
149
+ Dir.foreach(File.join(settings.public_folder, request.path), &files.method(:push))
150
+ if files == [".", ".."]
151
+ html << "\t<tr>\n\t\t<th>No files.</th>\n\t\t<th>-</th>\n\t\t<th>-</th>\n\t</tr>"
152
+ else
153
+ files.sort.each do |file|
154
+ html << wrap(file)
155
+ end
156
+ end
157
+ html << "\n</table>\n"
158
+ html << "<br>\n#{options[:readme]}\n" if options[:readme]
159
+ html << "</body>\n</html>\n"
160
+ "#{html}"
161
+ end
162
+
163
+ end
164
+
165
+ helpers Directory_listing
166
+ end
metadata CHANGED
@@ -1,78 +1,75 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: directory_listing
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.7
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.1.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Richard Myers
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2013-06-27 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
15
16
  name: filesize
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 0.0.2
22
- type: :runtime
23
17
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
18
+ requirement: &id001 !ruby/object:Gem::Requirement
25
19
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
29
23
  version: 0.0.2
30
- - !ruby/object:Gem::Dependency
31
- name: truncate
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: 0.0.4
38
24
  type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: truncate
39
28
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
29
+ requirement: &id002 !ruby/object:Gem::Requirement
41
30
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
45
34
  version: 0.0.4
46
- description: A gem to use with Sinatra for generating easy, CSS-styled, Apache-like
47
- directory listings.
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ description: A Sinatra extension for generating easy, CSS-styled, Apache-like directory listings.
48
38
  email: rick.myers@me.com
49
39
  executables: []
40
+
50
41
  extensions: []
42
+
51
43
  extra_rdoc_files: []
52
- files:
53
- - lib/directory_listing.rb
44
+
45
+ files:
46
+ - lib/sinatra/directory_listing.rb
54
47
  homepage: https://rubygems.org/gems/directory_listing
55
48
  licenses: []
49
+
56
50
  post_install_message:
57
51
  rdoc_options: []
58
- require_paths:
52
+
53
+ require_paths:
59
54
  - lib
60
- required_ruby_version: !ruby/object:Gem::Requirement
55
+ required_ruby_version: !ruby/object:Gem::Requirement
61
56
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
66
- required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
62
  none: false
68
- requirements:
69
- - - ! '>='
70
- - !ruby/object:Gem::Version
71
- version: '0'
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
72
67
  requirements: []
68
+
73
69
  rubyforge_project:
74
- rubygems_version: 1.8.24
70
+ rubygems_version: 1.8.23
75
71
  signing_key:
76
72
  specification_version: 3
77
73
  summary: Easy, CSS-styled, Apache-like directory listings for Sinatra.
78
74
  test_files: []
75
+
@@ -1,181 +0,0 @@
1
- require 'truncate'
2
- require 'filesize'
3
- require 'pathname'
4
-
5
- # = Easy, CSS-styled, Apache-like directory listings for Sinatra.
6
- #
7
- # == Usage
8
- #
9
- # Directory_listing.list will return HTML, so the following is a complete Sinatra
10
- # app that will provide a directory listing of whatever path you navigate to
11
- # and let you view any file that is served directly:
12
- #
13
- # require 'directory_listing'
14
- #
15
- # get '*' do |path|
16
- # if File.exist?(File.join(settings.public_folder, path))
17
- # if File.directory?(File.join(settings.public_folder, path))
18
- # "#{Directory_listing.list(
19
- # :directory => path,
20
- # :sinatra_public => settings.public_folder
21
- # )}"
22
- # else
23
- # send_file File.join(settings.public_folder, path)
24
- # end
25
- # else
26
- # not_found
27
- # end
28
- # end
29
- #
30
- # not_found do
31
- # 'Try again.'
32
- # end
33
- #
34
- # Any option key may be omitted except for :directory and :sinatra_public. Explanations of options are below.
35
- #
36
- # == Options
37
- #
38
- # directory # the directory to list
39
- # sinatra_public # sinatra's public folder - your public folder (and the default) is likely "settings.public_folder"
40
- # stylesheet # a stylesheet that will be added to the <head> of the generated directory listing
41
- # readme # an HTML string that will be appended at the footer of the generated directory listing
42
- # should_list_invisibles # whether the directory listing should include invisibles (dotfiles) - "yes" or "no"
43
- # last_modified_format # format for last modified date (http://www.ruby-doc.org/core-2.0/Time.html) - defaults to "%Y-%m-%d %H:%M:%S"
44
- # filename_truncate_length # (integer) length to truncate file names to - defaults to 40
45
- #
46
- # == Styling
47
- #
48
- # It's pretty easy to figure out how to style directory_listing by looking at the source, but here are some gotchas:
49
- #
50
- # Every item listed is a <td> element in a table. Directories will have a class of "dir" and regular files will have a class of "file".
51
- #
52
- # You can style the "File" column with this CSS:
53
- #
54
- # table tr > td:first-child {
55
- # text-align: left;
56
- # }
57
- #
58
- # Second column:
59
- # table tr > td:first-child + td {
60
- # text-align: left;
61
- # }
62
- #
63
- # Third column:
64
- # table tr > td:first-child + td + td {
65
- # text-align: left;
66
- # }
67
-
68
- module Directory_listing
69
- @@options = {}
70
-
71
- def self.options=(value)
72
- @@options = value
73
- end
74
-
75
- def self.options()
76
- @@options
77
- end
78
-
79
- def self.list(options)
80
- options = @@options.merge options
81
- raise(ArgumentError, ":directory is required") unless options[:directory]
82
- raise(ArgumentError, ":sinatra_public is required") unless options[:sinatra_public]
83
- pub = options[:sinatra_public]
84
- dir = File.join(pub, options[:directory])
85
-
86
- if options[:should_list_invisibles]
87
- $should_list_invisibles = options[:should_list_invisibles]
88
- else
89
- $should_list_invisibles = "no"
90
- end
91
- if options[:last_modified_format]
92
- $last_modified_format = options[:last_modified_format]
93
- else
94
- $last_modified_format = "%Y-%m-%d %H:%M:%S"
95
- end
96
- if options[:filename_truncate_length]
97
- $filename_truncate_length = options[:filename_truncate_length]
98
- else
99
- $filename_truncate_length = 40
100
- end
101
-
102
- html = "<html>\n<head>\n"
103
- html << "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
104
- if options[:stylesheet]
105
- html << "<link rel=\"stylesheet\" type=\"text/css\" href=\"/#{options[:stylesheet].sub(/^[\/]*/,"")}\">\n"
106
- end
107
- html << "</head>\n<body>\n"
108
- html << "<h1>Index of #{options[:directory]}</h1>\n"
109
- if options[:directory] != "/"
110
- html << "<a href='#{Pathname.new(options[:directory]).parent}'>&larr; Parent directory</a><br><br>"
111
- else
112
- html << "<a>Root directory</a><br><br>"
113
- end
114
- html << "<table>\n"
115
- html << "\t<tr>\n\t\t<th>File</th>\n\t\t<th>Last modified</th>\n\t\t<th>Size</th>\n\t</tr>\n"
116
- files = Array.new
117
- Dir.foreach(dir, &files.method(:push))
118
- if files == [".", ".."]
119
- html << "\t<tr>\n\t\t<th>No files.</th>\n\t\t<th>-</th>\n\t\t<th>-</th>\n\t</tr>"
120
- else
121
- files.sort.each do |file|
122
- html << wrap(file, dir, pub)
123
- end
124
- end
125
- html << "\n</table>\n"
126
- html << "<br>\n#{options[:readme]}\n" if options[:readme]
127
- html << "</body>\n</html>\n"
128
- "#{html}"
129
- end
130
-
131
- private
132
-
133
- def self.m_time(file, dir)
134
- time = "\t<td>#{File.mtime(File.join(dir, file)).strftime $last_modified_format}</td>"
135
- end
136
-
137
- def self.size(file, dir)
138
- if File.directory?(File.join(dir, file))
139
- "\t<td>-</td>"
140
- else
141
- size = Filesize.from("#{File.stat(File.join(dir, file)).size} B").pretty
142
- "\t<td>#{size}</td>"
143
- end
144
- end
145
-
146
- def self.name(file, dir, pub)
147
- tfile = file.truncate($filename_truncate_length, '...')
148
- if (Pathname.new(dir).cleanpath).eql?((Pathname.new(pub)).cleanpath)
149
- link = file
150
- else
151
- link = File.join(dir.split("/").last, file)
152
- end
153
-
154
- html = ""
155
- if File.directory?(File.join(dir, file))
156
- html << "\t<td class='dir'><a href='#{link}'>#{tfile}</a></td>"
157
- else
158
- html << "\t<td class='file'><a href='#{link}'>#{tfile}</a></td>"
159
- end
160
- "#{html}"
161
- end
162
-
163
- def self.wrap(file, dir, pub)
164
- wrapped = ""
165
- if $should_list_invisibles == "yes"
166
- wrapped << "\n\t<tr>
167
- #{name(file, dir, pub)}
168
- #{m_time(file, dir)}
169
- #{size(file, dir)}\n\t</tr>"
170
- else
171
- if file[0] != "."
172
- wrapped << "\n\t<tr>
173
- #{name(file, dir, pub)}
174
- #{m_time(file, dir)}
175
- #{size(file, dir)}\n\t</tr>"
176
- end
177
- end
178
- "#{wrapped}"
179
- end
180
-
181
- end