httpit 0.3.4 → 0.4
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/.gitignore +1 -0
- data/README.md +10 -6
- data/bin/httpit +59 -82
- data/example/index.haml +4 -4
- data/example/readme.md +1 -1
- data/httpit.gemspec +6 -21
- data/lib/search.rb +34 -0
- data/lib/search/dystopia.rb +65 -0
- data/lib/search/find.rb +16 -0
- data/views/listing.haml +93 -0
- data/views/not_found.haml +11 -0
- data/views/search.haml +12 -0
- data/views/search.js +59 -0
- data/views/view.haml +25 -0
- metadata +66 -80
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.sass-cache/
|
data/README.md
CHANGED
@@ -4,16 +4,20 @@ Build on sinatra, useful for developing JS applications and doing "psd => xhtml"
|
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
```bash
|
8
|
+
gem install httpit
|
9
|
+
cd /folder/for/server
|
10
|
+
httpit
|
11
|
+
# or you can set port
|
12
|
+
httpit 9081
|
13
|
+
```
|
12
14
|
|
13
15
|
## Features
|
14
16
|
|
15
17
|
* Haml support
|
16
|
-
* Sass support
|
18
|
+
* Sass support
|
17
19
|
* MarkDown support
|
18
20
|
|
21
|
+
To complile `sass` file make request for `style.sass.css`
|
22
|
+
|
19
23
|
See example
|
data/bin/httpit
CHANGED
@@ -4,11 +4,29 @@ require 'rubygems'
|
|
4
4
|
require 'sinatra'
|
5
5
|
require 'haml'
|
6
6
|
require 'redcloth'
|
7
|
+
require "pathname"
|
7
8
|
|
8
|
-
|
9
|
+
GEM_ROOT = Pathname.new(__FILE__).dirname.join("..").expand_path
|
10
|
+
|
11
|
+
require GEM_ROOT + "lib/search"
|
12
|
+
|
13
|
+
ROOT = Pathname.pwd
|
14
|
+
|
15
|
+
# this hack allow
|
16
|
+
# /some/folder/with/content + /subfolder => /some/folder/with/content/subfolder
|
17
|
+
|
18
|
+
class <<ROOT
|
19
|
+
def join(*args)
|
20
|
+
super *args.map{|a| a.is_a?(String) && a[0] == ?/ ? a[1 .. a.size] : a }
|
21
|
+
end
|
22
|
+
|
23
|
+
def +(a)
|
24
|
+
super(a.is_a?(String) && a[0] == ?/ ? a[1 .. a.size] : a)
|
25
|
+
end
|
26
|
+
end
|
9
27
|
|
10
28
|
set :views, ROOT
|
11
|
-
set :
|
29
|
+
set :public_folder, ROOT
|
12
30
|
set :app_file, $0
|
13
31
|
|
14
32
|
set :static, false
|
@@ -20,41 +38,54 @@ end
|
|
20
38
|
|
21
39
|
|
22
40
|
# build array of contents and theris type for specified folder
|
23
|
-
def get_content
|
24
|
-
|
25
|
-
abs_path = folder ? File.join(ROOT, folder) : ROOT
|
41
|
+
def get_content(folder = nil, sort = nil)
|
42
|
+
abs_path = folder ? ROOT + folder : ROOT
|
26
43
|
|
27
|
-
# build array if pairs: [filename, :type]
|
28
|
-
|
44
|
+
# build array if pairs: [filename, :type, is_textfile]
|
45
|
+
sorter = case sort
|
46
|
+
when 'name' then '| sort -f'
|
47
|
+
when 'ctime' then '-c'
|
48
|
+
when 'mtime' then '--sort=time'
|
49
|
+
when 'size' then '--sort=size'
|
50
|
+
else ''
|
51
|
+
end
|
52
|
+
|
53
|
+
`cd "#{abs_path.to_s.gsub(?", '\"')}" && ls -A #{sorter}`.split("\n").map do |obj|
|
54
|
+
file_path = abs_path + obj
|
29
55
|
[obj,
|
30
|
-
if
|
31
|
-
|
32
|
-
elsif
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
56
|
+
if file_path.file?; :file
|
57
|
+
elsif file_path.directory?; :dir
|
58
|
+
elsif file_path.symlink?; :link
|
59
|
+
end,
|
60
|
+
|
61
|
+
!!`file "#{file_path.to_s.gsub(?", '\"')}"`.sub(file_path.to_s, '').index(/text/i)
|
37
62
|
]
|
38
63
|
end
|
39
64
|
end
|
40
65
|
|
66
|
+
def view(tpl)
|
67
|
+
(Pathname.new(__FILE__).dirname + "../views/#{tpl}.haml").read
|
68
|
+
end
|
69
|
+
|
70
|
+
include Search
|
71
|
+
|
41
72
|
# shows index.html or folder contents if index.html does not exists
|
42
73
|
get '/' do
|
43
74
|
if File.file?('./index.html')
|
44
75
|
File.open('./index.html') {|f| f.read }
|
45
76
|
elsif File.file?('./index.haml')
|
46
|
-
haml :index
|
77
|
+
haml view(:index)
|
47
78
|
else
|
48
79
|
@path = ''
|
49
|
-
@files = get_content.select {|f| f[0] != '.' && f[0] != '..' }
|
50
|
-
haml :listing
|
80
|
+
@files = get_content(nil, params[:sort]).select {|f| f[0] != '.' && f[0] != '..' }
|
81
|
+
haml view(:listing)
|
51
82
|
end
|
52
83
|
end
|
53
84
|
|
54
85
|
get '/__img_preview' do
|
55
|
-
params[:file] = params[:file].gsub
|
86
|
+
params[:file] = params[:file].gsub(' ', '\ ')
|
56
87
|
tmppath = "/tmp/httpit_preview_#{Time.now.to_i}.jpeg"
|
57
|
-
`convert #{
|
88
|
+
`convert #{ROOT + params[:file]} -resize 1024 -quality 100% #{tmppath}`
|
58
89
|
content_type "image/jpeg"
|
59
90
|
content = File.open(tmppath, 'rb') { |f| f.read }
|
60
91
|
File.delete(tmppath)
|
@@ -64,21 +95,21 @@ end
|
|
64
95
|
# shows folder contents
|
65
96
|
get %r{.+} do
|
66
97
|
return nil if request.path == '/favicon.ico'
|
67
|
-
@path = request.path
|
98
|
+
@path = URI.unescape(request.path)
|
68
99
|
|
69
|
-
abs_path =
|
100
|
+
abs_path = ROOT + @path
|
70
101
|
|
71
102
|
if @path =~ /.+\.sass\.css/
|
103
|
+
return halt(404) unless File.file?(abs_path.to_s.chomp('.css'))
|
72
104
|
content_type :css
|
73
105
|
sass @path.chomp('.sass.css').to_sym
|
74
106
|
|
75
|
-
elsif !
|
107
|
+
elsif !abs_path.file? && !abs_path.directory?
|
76
108
|
halt 404
|
77
109
|
|
78
110
|
elsif @path =~ /.+\.md/
|
79
111
|
content_type :html
|
80
|
-
|
81
|
-
return RedCloth.new(content).to_html
|
112
|
+
return RedCloth.new(abs_path.read).to_html
|
82
113
|
|
83
114
|
elsif @path =~ /.+\.haml/
|
84
115
|
haml @path.chomp('.haml').to_sym
|
@@ -87,66 +118,12 @@ get %r{.+} do
|
|
87
118
|
send_file(abs_path)
|
88
119
|
|
89
120
|
else
|
90
|
-
@files = get_content(@path)
|
91
|
-
haml :listing
|
121
|
+
@files = get_content(@path, params[:sort])
|
122
|
+
haml view(:listing)
|
92
123
|
end
|
93
124
|
end
|
94
125
|
|
95
126
|
error 404 do
|
96
127
|
@path = request.path
|
97
|
-
haml :not_found
|
98
|
-
end
|
99
|
-
|
100
|
-
__END__
|
101
|
-
|
102
|
-
@@ listing
|
103
|
-
<style type="text/css">
|
104
|
-
:sass
|
105
|
-
#wrap
|
106
|
-
:width 800px
|
107
|
-
:margin 50 auto
|
108
|
-
|
109
|
-
span
|
110
|
-
:color #777
|
111
|
-
|
112
|
-
ul, li
|
113
|
-
:list-style-type none
|
114
|
-
|
115
|
-
.preview_link
|
116
|
-
:color #55a075
|
117
|
-
:margin-left 20px
|
118
|
-
</style>
|
119
|
-
#wrap
|
120
|
-
= @path
|
121
|
-
%h1
|
122
|
-
%span Folder:
|
123
|
-
= @path == '' ? '/' : @path
|
124
|
-
- if @path != ''
|
125
|
-
%a{:href => "#{@path}/.."} ←
|
126
|
-
|
127
|
-
%ul
|
128
|
-
- for file in @files
|
129
|
-
%li
|
130
|
-
- if file[1] == :file
|
131
|
-
%span= "–"
|
132
|
-
- elsif file[1] == :dir
|
133
|
-
%span= "+"
|
134
|
-
- elsif file[1] == :link
|
135
|
-
%span= "→"
|
136
|
-
|
137
|
-
%a{:href => "#{@path}/#{file[0]}"}= file[0]
|
138
|
-
|
139
|
-
- if %w{.jpg .jpeg .png .gif}.include?(File.extname(file[0]).downcase)
|
140
|
-
%a{:href => "/__img_preview?file=#{@path}/#{file[0]}", :class => "preview_link"} #1024
|
141
|
-
|
142
|
-
@@ not_found
|
143
|
-
<style type="text/css">
|
144
|
-
:sass
|
145
|
-
#wrap
|
146
|
-
:width 800px
|
147
|
-
:margin 50 auto
|
148
|
-
</style>
|
149
|
-
#wrap
|
150
|
-
%h1 File not found
|
151
|
-
|
152
|
-
%h3= "You requested <i>#{@path}</i>"
|
128
|
+
haml view(:not_found)
|
129
|
+
end
|
data/example/index.haml
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
%title HttpIt !!!
|
7
7
|
|
8
|
-
%link{ :rel => "stylesheet", :type => "text/css", :href => "
|
8
|
+
%link{ :rel => "stylesheet", :type => "text/css", :href => "main.sass.css" }
|
9
9
|
|
10
10
|
%body
|
11
11
|
#wrap
|
@@ -20,10 +20,10 @@
|
|
20
20
|
$ httpit <port number>
|
21
21
|
|
22
22
|
%p
|
23
|
-
%a{ :href => "
|
23
|
+
%a{ :href => "images/bird.jpg" } Static file
|
24
24
|
|
25
25
|
%p
|
26
|
-
%a{ :href => "
|
26
|
+
%a{ :href => "readme.md" } MarkDown example
|
27
27
|
|
28
28
|
%p
|
29
|
-
%a{ :href => "
|
29
|
+
%a{ :href => "images" } Gallery folder
|
data/example/readme.md
CHANGED
data/httpit.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "httpit"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.4"
|
4
4
|
s.summary = "Web server for static files"
|
5
5
|
s.description = "Just go to folder and run `httpit`"
|
6
6
|
s.author = "Pavel Evstigneev"
|
@@ -9,25 +9,10 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.has_rdoc = false
|
10
10
|
s.executables = ["httpit"]
|
11
11
|
s.rubyforge_project = "httpit"
|
12
|
-
s.files =
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
19
|
-
s.add_runtime_dependency(%q<sinatra>, [">= 1.0"])
|
20
|
-
s.add_runtime_dependency(%q<haml>, [">= 3.0.10"])
|
21
|
-
s.add_runtime_dependency(%q<RedCloth>, [">= 4.2.3"])
|
22
|
-
|
23
|
-
else
|
24
|
-
s.add_dependency(%q<sinatra>, [">= 1.0"])
|
25
|
-
s.add_dependency(%q<haml>, [">= 3.0.10"])
|
26
|
-
s.add_dependency(%q<RedCloth>, [">= 4.2.3"])
|
27
|
-
end
|
28
|
-
else
|
29
|
-
s.add_dependency(%q<sinatra>, [">= 1.0"])
|
30
|
-
s.add_dependency(%q<haml>, [">= 3.0.10"])
|
31
|
-
s.add_dependency(%q<RedCloth>, [">= 4.2.3"])
|
32
|
-
end
|
14
|
+
s.add_runtime_dependency 'sinatra', ">= 1.0"
|
15
|
+
s.add_runtime_dependency 'haml', '>= 3.0.10'
|
16
|
+
s.add_runtime_dependency 'RedCloth', ">= 4.2.3"
|
17
|
+
s.add_runtime_dependency 'rufus-tokyo', ">= 1.0.7"
|
33
18
|
end
|
data/lib/search.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Search
|
2
|
+
def engine=(value)
|
3
|
+
@engine = value
|
4
|
+
end
|
5
|
+
|
6
|
+
def engine; @engine; end
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
Search.engine = Search::Find #Dystopia
|
11
|
+
|
12
|
+
get '/__search' do
|
13
|
+
@path = ROOT + params[:path].to_s
|
14
|
+
s_time = Time.now.to_f
|
15
|
+
@found = Search.engine.find_in_folder(ROOT, @path, params[:q])
|
16
|
+
@total_time = Time.now.to_f - s_time
|
17
|
+
|
18
|
+
haml view(:search)
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/__view' do
|
22
|
+
if !`file "#{ROOT.join(params[:file])}"`.index('text')
|
23
|
+
redirect params[:file]
|
24
|
+
return
|
25
|
+
end
|
26
|
+
@content = ROOT.join(params[:file]).read
|
27
|
+
haml view(:view)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
require GEM_ROOT + "lib/search/find"
|
34
|
+
require GEM_ROOT + "lib/search/dystopia"
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'rufus/tokyo/dystopia'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
=begin
|
7
|
+
A B : searches for records including the two tokens.
|
8
|
+
A && B : searches for records including the two tokens.
|
9
|
+
A || B : searches for records including the one or both of the two tokens.
|
10
|
+
"A B..." : searches for records including the phrase.
|
11
|
+
[[A]] : searches for records including words exactly matching the token.
|
12
|
+
[[A*]] : searches for records including words beginning with the token.
|
13
|
+
[[*A]] : searches for records including words ending with the token.
|
14
|
+
[[[[A : searches for records beginning with the token.
|
15
|
+
A]]]] : searches for records ending with the token.
|
16
|
+
Note that the priority of "||" is higher than the one of "&&".
|
17
|
+
=end
|
18
|
+
|
19
|
+
module Search::Dystopia
|
20
|
+
extend self
|
21
|
+
|
22
|
+
CMD = "find . -type d \\( -name '*.git*' \\) -prune -o -print"
|
23
|
+
|
24
|
+
def find_in_folder(root, path, needle)
|
25
|
+
files = inst.search(needle).map do |id|
|
26
|
+
doc = inst.fetch(id)
|
27
|
+
doc[0, doc.index("\n")]
|
28
|
+
end
|
29
|
+
|
30
|
+
if path != root
|
31
|
+
subdir = path.to_s.sub(root.to_s + '/', '')
|
32
|
+
files.select {|f| f[0, subdir.size] == subdir }.map {|f| f.sub(subdir + '/', '') }
|
33
|
+
else
|
34
|
+
files
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# return instance of searcher. and make indexing on first search
|
39
|
+
def inst
|
40
|
+
return @inst if @inst
|
41
|
+
db_file = "/tmp/httpit_index_#{Digest::MD5.hexdigest ROOT.to_s}"
|
42
|
+
@inst ||= Rufus::Tokyo::Dystopia::Core.new(db_file)
|
43
|
+
at_exit{ puts("removing #{db_file}"); `rm -r "#{db_file}"` }
|
44
|
+
index_dir()
|
45
|
+
@inst
|
46
|
+
end
|
47
|
+
|
48
|
+
def index_dir()
|
49
|
+
files = `cd #{ROOT.to_s} && #{CMD}`.split("\n")
|
50
|
+
inst.clear
|
51
|
+
|
52
|
+
puts "Indexing #{files.size} files"
|
53
|
+
files.each_with_index do |file, i|
|
54
|
+
next if file[0, 3] == './.'
|
55
|
+
|
56
|
+
# if its a text file store its content
|
57
|
+
content = if `file "#{ROOT.join(file).to_s}"`.index('text')
|
58
|
+
(ROOT + file).read
|
59
|
+
else ""; end
|
60
|
+
inst.store(i, file.sub('./', '') + "\n" + content)
|
61
|
+
end
|
62
|
+
|
63
|
+
inst
|
64
|
+
end
|
65
|
+
end
|
data/lib/search/find.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Search::Find
|
2
|
+
extend self
|
3
|
+
CMD = "find . -type d \\( -name '*.git*' \\) -prune -o -exec file -F '&' {} \\; | grep text | cut -d\\& -f1 | sed 's/./\\\\&/g' | xargs -n 1 grep -i -l '###'"
|
4
|
+
CMD_LIST = "find . -type d \\( -name '*.git*' \\) -prune -o -print | grep -i '###'"
|
5
|
+
|
6
|
+
def find_in_folder(root, path, needle)
|
7
|
+
in_filenames = `cd #{path} && #{CMD_LIST.sub('###', needle)}`.split("\n")
|
8
|
+
in_text_files = `cd #{path} && #{CMD.sub('###', needle)}`.split("\n")
|
9
|
+
|
10
|
+
(in_filenames + in_text_files.select {|f| !in_filenames.include?(f) }).map {|f| f.sub('./', '') }
|
11
|
+
end
|
12
|
+
|
13
|
+
#def find_in_file(file, needle)
|
14
|
+
# `cat #{file} | grep -n -B 1 -A 1 '#{needle}'`
|
15
|
+
#end
|
16
|
+
end
|
data/views/listing.haml
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
<style type="text/css">
|
2
|
+
:sass
|
3
|
+
#wrap
|
4
|
+
:width 800px
|
5
|
+
:margin 30 auto 50px
|
6
|
+
|
7
|
+
span
|
8
|
+
:color #777
|
9
|
+
|
10
|
+
ul, li
|
11
|
+
:list-style-type none
|
12
|
+
|
13
|
+
ul > header
|
14
|
+
:font-style italic
|
15
|
+
:margin-bottom 11px
|
16
|
+
|
17
|
+
.preview_link
|
18
|
+
:color #55a075
|
19
|
+
:margin-left 20px
|
20
|
+
|
21
|
+
input[type=search]
|
22
|
+
:width 300px
|
23
|
+
input[type=submit]
|
24
|
+
:display none
|
25
|
+
|
26
|
+
= box-shadow($value)
|
27
|
+
:box-shadow $value
|
28
|
+
:-moz-box-shadow $value
|
29
|
+
:-webkit-box-shadow $value
|
30
|
+
|
31
|
+
#files_search
|
32
|
+
> .results
|
33
|
+
:display none
|
34
|
+
:background #fff
|
35
|
+
+box-shadow(1px 1px 5px rgba(125, 125, 125, 0.7))
|
36
|
+
:width 620px
|
37
|
+
:position relative
|
38
|
+
:top 7px
|
39
|
+
:padding 5px 15px
|
40
|
+
em
|
41
|
+
:background-color yellow
|
42
|
+
ul
|
43
|
+
:padding 0
|
44
|
+
:margin 0
|
45
|
+
li
|
46
|
+
:margin 3px 0
|
47
|
+
:font-size 13px
|
48
|
+
&:hover
|
49
|
+
:background-color #def
|
50
|
+
&.loading
|
51
|
+
> .results
|
52
|
+
:display block
|
53
|
+
</style>
|
54
|
+
|
55
|
+
#wrap
|
56
|
+
.search
|
57
|
+
%form#files_search{:action => "/__search"}
|
58
|
+
%input{:type => "hidden", :name => "path", :value => @path}
|
59
|
+
%input{:type => "search", :placeholder => "Search...", :name => 'q', :value => params[:q]}
|
60
|
+
%input{:type => "submit"}
|
61
|
+
.results Finding...
|
62
|
+
|
63
|
+
%h1
|
64
|
+
%span Folder:
|
65
|
+
= @path == '' ? '/' : @path
|
66
|
+
- if @path != ''
|
67
|
+
%a{:href => @path.gsub(%r{/[^/]+/?$}, '') + '/'} ←
|
68
|
+
|
69
|
+
|
70
|
+
%ul
|
71
|
+
%header
|
72
|
+
Sort
|
73
|
+
%select.sorting
|
74
|
+
- for key in %w{name size ctime mtime}
|
75
|
+
%option{params[:sort] == key ? {:selected => "selected"} : {}}= key
|
76
|
+
|
77
|
+
- for file in @files
|
78
|
+
%li
|
79
|
+
- if file[1] == :file
|
80
|
+
%span= "–"
|
81
|
+
- elsif file[1] == :dir
|
82
|
+
%span= "+"
|
83
|
+
- elsif file[1] == :link
|
84
|
+
%span= "→"
|
85
|
+
|
86
|
+
%a{:href => "#{@path}/#{file[0]}"}= file[0]
|
87
|
+
|
88
|
+
- if %w{.jpg .jpeg .png .gif}.include?(File.extname(file[0]).downcase)
|
89
|
+
%a{:href => "/__img_preview?file=#{@path}/#{file[0]}", :class => "preview_link"} #1024
|
90
|
+
- if file[2]
|
91
|
+
%a{:href => "/__view?file=#{@path}/#{file[0]}", :class => "preview_link"} view
|
92
|
+
|
93
|
+
%script{:type => "text/javascript"}= GEM_ROOT.join('views/search.js').read
|
data/views/search.haml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
%ul
|
2
|
+
- for file in @found
|
3
|
+
%li<>
|
4
|
+
- if @path.join(file).file?
|
5
|
+
%a{:href => "/__view?file=#{File.join(params[:path], file)}" }= file.gsub(/#{params[:q]}/i) {|m| "<em>#{m}</em>" }
|
6
|
+
- else
|
7
|
+
%a{:href => File.join(params[:path], file)}= file.gsub(/#{params[:q]}/i) {|m| "<em>#{m}</em>" }
|
8
|
+
|
9
|
+
- if @found.size == 0
|
10
|
+
%i Nothing
|
11
|
+
|
12
|
+
%footer= "Complete in #{"%4.3fs" % @total_time}"
|
data/views/search.js
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
Xhr = function (url, data, callback) {
|
2
|
+
var xhr = new XMLHttpRequest();
|
3
|
+
|
4
|
+
xhr.open("GET", url + '?' + data, true);
|
5
|
+
|
6
|
+
xhr.onreadystatechange = function() {
|
7
|
+
if (xhr.readyState == 4 && xhr.status == 200) {
|
8
|
+
callback(xhr.responseText);
|
9
|
+
}
|
10
|
+
};
|
11
|
+
|
12
|
+
xhr.send();
|
13
|
+
};
|
14
|
+
|
15
|
+
// get forms data for xhr request
|
16
|
+
Xhr.formData = function (form) {
|
17
|
+
var results = [];
|
18
|
+
var elements = form.querySelectorAll('input, select, textarea');
|
19
|
+
|
20
|
+
for(k in elements)
|
21
|
+
if (elements.hasOwnProperty(k) && elements[k].name)
|
22
|
+
results.push(elements[k].name + '=' + encodeURIComponent(elements[k].value))
|
23
|
+
|
24
|
+
return results.join('&')
|
25
|
+
};
|
26
|
+
|
27
|
+
function $ (selector) {
|
28
|
+
return document.querySelector(selector);
|
29
|
+
};
|
30
|
+
|
31
|
+
function $$ (selector) {
|
32
|
+
return document.querySelectorAll(selector);
|
33
|
+
};
|
34
|
+
|
35
|
+
$('#files_search').addEventListener('submit', function (e) {
|
36
|
+
var form = e.target;
|
37
|
+
e.preventDefault();
|
38
|
+
|
39
|
+
form.querySelector('.results').innerHTML = 'Finding...';
|
40
|
+
form.className = 'loading';
|
41
|
+
|
42
|
+
new Xhr(form.action, Xhr.formData(form), function(data) {
|
43
|
+
form.querySelector('.results').innerHTML = data;
|
44
|
+
});
|
45
|
+
}, true);
|
46
|
+
|
47
|
+
// hide results when erase search field
|
48
|
+
function hideResults (e) {
|
49
|
+
if (e.target.value == '') $('#files_search').className = '';
|
50
|
+
}
|
51
|
+
$('input[type=search]').addEventListener('change', hideResults, false);
|
52
|
+
$('input[type=search]').addEventListener('keyup', hideResults, false);
|
53
|
+
$('input[type=search]').addEventListener('click', hideResults, false);
|
54
|
+
|
55
|
+
$('.sorting').addEventListener('change', function(e) {
|
56
|
+
var clean_path = (window.location + '').replace(/(\?|&)sort=[^=]*/, '');
|
57
|
+
clean_path += (clean_path.indexOf('?') == -1 ? '?' : '&') + 'sort=' + e.target.value
|
58
|
+
window.location = clean_path;
|
59
|
+
}, false);
|
data/views/view.haml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
<style type="text/css">
|
2
|
+
:sass
|
3
|
+
#wrap
|
4
|
+
:width 800px
|
5
|
+
:margin 50 auto
|
6
|
+
span
|
7
|
+
:color #777
|
8
|
+
textarea
|
9
|
+
:width 785px
|
10
|
+
:min-height 500px
|
11
|
+
:padding 5px 7px
|
12
|
+
:font
|
13
|
+
:family monospace, Monaco
|
14
|
+
:size 12px
|
15
|
+
:border 1px solid #ccc
|
16
|
+
:color #333
|
17
|
+
</style>
|
18
|
+
|
19
|
+
#wrap
|
20
|
+
%h1
|
21
|
+
%span
|
22
|
+
%a{:href => params[:file], :target => "_blank"} File:
|
23
|
+
= params[:file]
|
24
|
+
%a{:href => params[:file].gsub(%r{/[^/]+/?$}, '') + '/'} ←
|
25
|
+
%textarea= @content
|
metadata
CHANGED
@@ -1,119 +1,105 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpit
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 3
|
9
|
-
- 4
|
10
|
-
version: 0.3.4
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.4'
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Pavel Evstigneev
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-02-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: sinatra
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2154284220 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 0
|
33
|
-
version: "1.0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
34
22
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: haml
|
38
23
|
prerelease: false
|
39
|
-
|
24
|
+
version_requirements: *2154284220
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: haml
|
27
|
+
requirement: &2154283620 !ruby/object:Gem::Requirement
|
40
28
|
none: false
|
41
|
-
requirements:
|
42
|
-
- -
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
hash: 19
|
45
|
-
segments:
|
46
|
-
- 3
|
47
|
-
- 0
|
48
|
-
- 10
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
49
32
|
version: 3.0.10
|
50
33
|
type: :runtime
|
51
|
-
version_requirements: *id002
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: RedCloth
|
54
34
|
prerelease: false
|
55
|
-
|
35
|
+
version_requirements: *2154283620
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: RedCloth
|
38
|
+
requirement: &2154282700 !ruby/object:Gem::Requirement
|
56
39
|
none: false
|
57
|
-
requirements:
|
58
|
-
- -
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
hash: 49
|
61
|
-
segments:
|
62
|
-
- 4
|
63
|
-
- 2
|
64
|
-
- 3
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
65
43
|
version: 4.2.3
|
66
44
|
type: :runtime
|
67
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2154282700
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rufus-tokyo
|
49
|
+
requirement: &2154282220 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.7
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2154282220
|
68
58
|
description: Just go to folder and run `httpit`
|
69
59
|
email: pavel.evst@gmail.com
|
70
|
-
executables:
|
60
|
+
executables:
|
71
61
|
- httpit
|
72
62
|
extensions: []
|
73
|
-
|
74
63
|
extra_rdoc_files: []
|
75
|
-
|
76
|
-
|
77
|
-
- bin/httpit
|
64
|
+
files:
|
65
|
+
- .gitignore
|
78
66
|
- README.md
|
79
|
-
- httpit
|
67
|
+
- bin/httpit
|
68
|
+
- example/images/bird.jpg
|
80
69
|
- example/index.haml
|
81
70
|
- example/main.sass
|
82
71
|
- example/readme.md
|
83
|
-
-
|
84
|
-
|
72
|
+
- httpit.gemspec
|
73
|
+
- lib/search.rb
|
74
|
+
- lib/search/dystopia.rb
|
75
|
+
- lib/search/find.rb
|
76
|
+
- views/listing.haml
|
77
|
+
- views/not_found.haml
|
78
|
+
- views/search.haml
|
79
|
+
- views/search.js
|
80
|
+
- views/view.haml
|
85
81
|
homepage: http://github.com/Paxa/httpit
|
86
82
|
licenses: []
|
87
|
-
|
88
83
|
post_install_message:
|
89
84
|
rdoc_options: []
|
90
|
-
|
91
|
-
require_paths:
|
85
|
+
require_paths:
|
92
86
|
- lib
|
93
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
88
|
none: false
|
95
|
-
requirements:
|
96
|
-
- -
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
|
99
|
-
|
100
|
-
- 0
|
101
|
-
version: "0"
|
102
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
94
|
none: false
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
segments:
|
109
|
-
- 0
|
110
|
-
version: "0"
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
111
99
|
requirements: []
|
112
|
-
|
113
100
|
rubyforge_project: httpit
|
114
|
-
rubygems_version: 1.
|
101
|
+
rubygems_version: 1.8.11
|
115
102
|
signing_key:
|
116
103
|
specification_version: 3
|
117
104
|
summary: Web server for static files
|
118
105
|
test_files: []
|
119
|
-
|