gembox 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ == 0.1.3 2009-04-06
2
+
3
+ * Support/linking to local RDoc files in Gem pages
4
+ * Added JS so that clippy only loads on mouseover (fixes load issues)
5
+ * Tests now rely on rack-test instead of sintra/test
6
+
7
+ == 0.1.1 2009-03-04
8
+
9
+ * 1 minor fix:
10
+ * Fixed paths so that the binary works correctly
11
+
12
+ == 0.1.0 2009-02-27
13
+
14
+ * 1 major enhancement:
15
+ * Initial release
@@ -0,0 +1,41 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/gembox
7
+ gembox.gemspec
8
+ lib/extensions.rb
9
+ lib/gembox.rb
10
+ lib/gembox/app.rb
11
+ lib/gembox/config.ru
12
+ lib/gembox/gem_list.rb
13
+ lib/gembox/gems.rb
14
+ lib/gembox/view_helpers.rb
15
+ public/images/edit.png
16
+ public/images/folder.png
17
+ public/images/git.gif
18
+ public/images/page.png
19
+ public/images/page_white_text.png
20
+ public/images/rubygems-125x125t.png
21
+ public/javascripts/base.js
22
+ public/javascripts/gembox.js
23
+ public/javascripts/jquery.form.js
24
+ public/javascripts/jquery.js
25
+ public/javascripts/jquery.metadata.js
26
+ public/javascripts/jquery.ui.js
27
+ public/swf/clippy.swf
28
+ test/.bacon
29
+ test/test_gembox_app.rb
30
+ test/test_gembox_gems.rb
31
+ test/test_helper.rb
32
+ views/doc.haml
33
+ views/file_tree.haml
34
+ views/gem.haml
35
+ views/gembox.sass
36
+ views/gems_columns.haml
37
+ views/gems_header.haml
38
+ views/gems_table.haml
39
+ views/index.haml
40
+ views/layout.haml
41
+ views/no_results.haml
@@ -0,0 +1,4 @@
1
+ For more information on gembox, see http://code.quirkey.com/gembox
2
+
3
+
4
+
@@ -0,0 +1,35 @@
1
+ = gembox
2
+
3
+ == DESCRIPTION:
4
+
5
+ Gembox is a little sinatra app that ties in with your local ruby gems to let you browse and learn more about them.
6
+
7
+ Please see the project home page for a full description:
8
+
9
+ http://code.quirkey.com/gembox
10
+
11
+
12
+ == LICENSE:
13
+
14
+ (The MIT License)
15
+
16
+ Copyright (c) 2009 Aaron Quint, Quirkey NYC, LLC
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining
19
+ a copy of this software and associated documentation files (the
20
+ 'Software'), to deal in the Software without restriction, including
21
+ without limitation the rights to use, copy, modify, merge, publish,
22
+ distribute, sublicense, and/or sell copies of the Software, and to
23
+ permit persons to whom the Software is furnished to do so, subject to
24
+ the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be
27
+ included in all copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
30
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
32
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
33
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
34
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
35
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen jeweler].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/gembox'
3
+
4
+ require 'jeweler'
5
+
6
+ # Generate all the Rake tasks
7
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
8
+
9
+ $hoe = Hoe.new('gembox', Jeweler::Version.new(File.expand_path(File.dirname(__FILE__))).to_s) do |p|
10
+ p.developer('Aaron Quint', 'aaron@quirkey.com')
11
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
12
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
13
+ p.rubyforge_name = 'quirkey'
14
+ p.summary = p.description = "A sinatra based interface for browsing and admiring your gems."
15
+ p.url = ['http://code.quirkey.com/gembox', 'http://github.com/quirkey/gembox']
16
+ p.extra_deps = [
17
+ ['sinatra', '>=0.9.1'],
18
+ ['haml', '>=2.0.9'],
19
+ ['activesupport', '>=2.2.2'],
20
+ ['mislav-will_paginate', '>=2.3.7']
21
+ ]
22
+
23
+ p.extra_dev_deps = [
24
+ ['newgem', ">= #{::Newgem::VERSION}"],
25
+ ['rack-test', '>=0.1.0']
26
+ ]
27
+
28
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
29
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
30
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
31
+ p.rsync_args = '-av --delete --ignore-errors'
32
+ end
33
+
34
+ require 'newgem/tasks' # load /tasks/*.rake
35
+ Dir['tasks/**/*.rake'].each { |t| load t }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2009-2-27.
4
+ # Copyright (c) 2009. All rights reserved.
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/gembox")
7
+
8
+ Gembox::App.set :app_file, File.expand_path(File.dirname(__FILE__) + "/../lib/gembox/app.rb")
9
+ Gembox::App.set :environment, :production
10
+ Gembox::App.set :port, 5678
11
+ Gembox::App.run!
@@ -0,0 +1,56 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{gembox}
5
+ s.version = "0.1.3"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Aaron Quint"]
9
+ s.date = %q{2009-04-06}
10
+ s.default_executable = %q{gembox}
11
+ s.description = %q{A sinatra based interface for browsing and admiring your gems.}
12
+ s.email = ["aaron@quirkey.com"]
13
+ s.executables = ["gembox"]
14
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc"]
15
+ s.files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "bin/gembox", "gembox.gemspec", "lib/extensions.rb", "lib/gembox.rb", "lib/gembox/app.rb", "lib/gembox/config.ru", "lib/gembox/gem_list.rb", "lib/gembox/gems.rb", "lib/gembox/view_helpers.rb", "public/images/edit.png", "public/images/folder.png", "public/images/git.gif", "public/images/page.png", "public/images/page_white_text.png", "public/images/rubygems-125x125t.png", "public/javascripts/base.js", "public/javascripts/gembox.js", "public/javascripts/jquery.form.js", "public/javascripts/jquery.js", "public/javascripts/jquery.metadata.js", "public/javascripts/jquery.ui.js", "public/swf/clippy.swf", "test/.bacon", "test/test_gembox_app.rb", "test/test_gembox_gems.rb", "test/test_helper.rb", "views/doc.haml", "views/file_tree.haml", "views/gem.haml", "views/gembox.sass", "views/gems_columns.haml", "views/gems_header.haml", "views/gems_table.haml", "views/index.haml", "views/layout.haml", "views/no_results.haml"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://code.quirkey.com/gembox}
18
+ s.post_install_message = %q{PostInstall.txt}
19
+ s.rdoc_options = ["--main", "README.rdoc"]
20
+ s.require_paths = ["lib"]
21
+ s.rubyforge_project = %q{quirkey}
22
+ s.rubygems_version = %q{1.3.1}
23
+ s.summary = %q{A sinatra based interface for browsing and admiring your gems.}
24
+ s.test_files = ["test/test_gembox_app.rb", "test/test_gembox_gems.rb", "test/test_helper.rb"]
25
+
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 2
29
+
30
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
+ s.add_runtime_dependency(%q<sinatra>, [">= 0.9.1"])
32
+ s.add_runtime_dependency(%q<haml>, [">= 2.0.9"])
33
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.2.2"])
34
+ s.add_runtime_dependency(%q<mislav-will_paginate>, [">= 2.3.7"])
35
+ s.add_development_dependency(%q<newgem>, [">= 1.2.3"])
36
+ s.add_development_dependency(%q<rack-test>, [">= 0.1.0"])
37
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
38
+ else
39
+ s.add_dependency(%q<sinatra>, [">= 0.9.1"])
40
+ s.add_dependency(%q<haml>, [">= 2.0.9"])
41
+ s.add_dependency(%q<activesupport>, [">= 2.2.2"])
42
+ s.add_dependency(%q<mislav-will_paginate>, [">= 2.3.7"])
43
+ s.add_dependency(%q<newgem>, [">= 1.2.3"])
44
+ s.add_dependency(%q<rack-test>, [">= 0.1.0"])
45
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<sinatra>, [">= 0.9.1"])
49
+ s.add_dependency(%q<haml>, [">= 2.0.9"])
50
+ s.add_dependency(%q<activesupport>, [">= 2.2.2"])
51
+ s.add_dependency(%q<mislav-will_paginate>, [">= 2.3.7"])
52
+ s.add_dependency(%q<newgem>, [">= 1.2.3"])
53
+ s.add_dependency(%q<rack-test>, [">= 0.1.0"])
54
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
55
+ end
56
+ end
@@ -0,0 +1,21 @@
1
+ module Gem
2
+ class Specification
3
+
4
+ def files_tree
5
+ tree = {}
6
+ files.each do |file|
7
+ split_dirs = file.split(/\//)
8
+ keyed_hash = {}
9
+ split_dirs.reverse.each do |key|
10
+ keyed_hash = {key => keyed_hash}
11
+ end
12
+ tree.deep_merge!(keyed_hash)
13
+ end
14
+ tree
15
+ end
16
+
17
+ def on_github?
18
+ homepage =~ /github\.com\/([\w\d\-\_]+)\/([\w\d\-\_]+)\/tree/
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'active_support'
6
+ require 'will_paginate/array'
7
+ require 'will_paginate/view_helpers'
8
+
9
+ require 'extensions'
10
+ require 'gembox/gem_list'
11
+ require 'gembox/gems'
12
+ require 'gembox/view_helpers'
13
+ require 'gembox/app'
@@ -0,0 +1,87 @@
1
+ require 'sinatra'
2
+
3
+ module Gembox
4
+ class App < ::Sinatra::Default
5
+ include Gembox::ViewHelpers
6
+ include WillPaginate::ViewHelpers
7
+
8
+ @@root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
9
+
10
+ set :root, @@root
11
+
12
+ before do
13
+ Gembox::Gems.load
14
+ @gems = Gembox::Gems.local_gems.paginate :page => params[:page], :per_page => 30
15
+ @stats = Gembox::Gems.stats
16
+ end
17
+
18
+ get '/stylesheets/:stylesheet.css' do
19
+ sass params[:stylesheet].to_sym
20
+ end
21
+
22
+ get '/' do
23
+ redirect '/gems'
24
+ end
25
+
26
+ get %r{/gems/doc/([\w\-\_]+)/?([\d\.]+)?/?(.*)?} do
27
+ if params[:captures].length == 3 && !params[:captures][2].blank?
28
+ # we have a path
29
+ load_gem_by_version
30
+ @rdoc_path = File.join(@gem.installation_path, "doc", @gem.full_name, 'rdoc')
31
+ full_path = File.join(@rdoc_path, params[:captures].pop)
32
+ content_type File.extname(full_path)
33
+ File.read(full_path)
34
+ else
35
+ load_gem_by_version
36
+ @rdoc_path = File.join(@gem.installation_path, "doc", @gem.full_name, 'rdoc')
37
+ haml :doc, :layout => false
38
+ end
39
+ end
40
+
41
+ get %r{/gems/([\w\-\_]+)/?([\d\.]+)?/?} do
42
+ show_layout = params[:layout] != 'false'
43
+ load_gem_by_version
44
+ if params[:file]
45
+ action = params[:action] || 'view'
46
+ file_path = File.join(@gem.full_gem_path, params[:file])
47
+ if File.readable?(file_path)
48
+ if action == 'edit'
49
+ `$EDITOR #{file_path}`
50
+ else
51
+ content_type 'text/plain'
52
+ return File.read(file_path)
53
+ end
54
+ end
55
+ end
56
+ haml :gem, :layout => show_layout
57
+ end
58
+
59
+ get '/gems/?' do
60
+ show_layout = params[:layout] != 'false'
61
+ @show_as = params[:as] || 'columns'
62
+ if @search = params[:search]
63
+ @gems = Gembox::Gems.search(@search).paginate :page => params[:page]
64
+ end
65
+ haml "gems_#{@show_as}".to_sym, :layout => show_layout
66
+ end
67
+
68
+ private
69
+
70
+ def load_gem_by_version
71
+ name, version = params[:captures]
72
+ @gems = Gembox::Gems.search(name, nil, true)
73
+ raise @gems.inspect if @gems.empty?
74
+ @gem_versions = @gems[0][1]
75
+ if version
76
+ @gems = Gembox::Gems.search(name, version)
77
+ @gem = @gems.shift[1].first if @gems
78
+ end
79
+ if !@gem
80
+ @gem = @gem_versions.shift
81
+ redirect "/gems/#{@gem.name}/#{@gem.version}"
82
+ end
83
+ end
84
+
85
+
86
+ end
87
+ end
@@ -0,0 +1,8 @@
1
+ # To use with thin
2
+ # thin start -p PORT -R config.ru
3
+
4
+ require File.join(File.dirname(__FILE__), 'gembox')
5
+
6
+ disable :run
7
+ set :env, :production
8
+ run Gembox::App
@@ -0,0 +1,41 @@
1
+ module Gembox
2
+
3
+ class GemList < Array
4
+
5
+ def [](*args)
6
+ if args.first.is_a?(String)
7
+ search(args.first)
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ def []=(key, value)
14
+ if key.is_a?(String)
15
+ if versions = search(key)
16
+ versions.replace([key, value])
17
+ else
18
+ self << [key, value]
19
+ end
20
+ else
21
+ super
22
+ end
23
+ end
24
+
25
+ def search(key)
26
+ i = find {|v|
27
+ if v.is_a?(Array)
28
+ v[0] == key
29
+ else
30
+ v == key
31
+ end
32
+ }
33
+ i.is_a?(Array) ? i[1] : i
34
+ end
35
+
36
+ def has_key?(key)
37
+ !search(key).nil?
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,44 @@
1
+ module Gembox
2
+ class Gems
3
+ class << self
4
+ attr_accessor :source_index
5
+
6
+ def load
7
+ @source_index ||= ::Gem.source_index
8
+ local_gems
9
+ end
10
+
11
+ def local_gems
12
+ @local_gems ||= group_gems(source_index.gems)
13
+ end
14
+
15
+ def search(search_term, version = nil, strict = false)
16
+ version = version ? Gem::Requirement.create(version) : Gem::Requirement.default
17
+ escaped = Regexp.escape(search_term)
18
+ regexp = strict ? /^#{escaped}$/ : /#{escaped}/
19
+ gems = source_index.search Gem::Dependency.new(regexp, version)
20
+ group_gems(gems)
21
+ end
22
+
23
+ def stats
24
+ num_versions = source_index.length
25
+ num_gems = local_gems.length
26
+ oldest_gem = source_index.min {|a,b| a[1].date <=> b[1].date }.last
27
+ {:num_versions => num_versions, :num_gems => num_gems, :oldest_gem => oldest_gem}
28
+ end
29
+
30
+ protected
31
+ def group_gems(gem_collection)
32
+ gem_hash = GemList.new
33
+ gem_collection = gem_collection.values if gem_collection.is_a?(Hash)
34
+ gem_collection.each do |spec|
35
+ gem_hash[spec.name] ||= []
36
+ gem_hash[spec.name] << spec
37
+ gem_hash[spec.name].sort! {|a,b| (b.version || 0) <=> (a.version || 0) }
38
+ end
39
+ gem_hash.sort {|a, b| a[0].downcase <=> b[0].downcase }
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,69 @@
1
+ module Gembox
2
+ module ViewHelpers
3
+
4
+ def tag_options(options, escape = true)
5
+ option_string = options.collect {|k,v| %{#{k}="#{v}"}}.join(' ')
6
+ option_string = " " + option_string unless option_string.blank?
7
+ end
8
+
9
+ def content_tag(name, content, options, escape = true)
10
+ tag_options = tag_options(options, escape) if options
11
+ "<#{name}#{tag_options}>#{content}</#{name}>"
12
+ end
13
+
14
+ def link_to(text, link = nil, options = {})
15
+ link ||= text
16
+ link = url_for(link)
17
+ "<a href=\"#{link}\">#{text}</a>"
18
+ end
19
+
20
+ def link_to_gem(gem, options = {})
21
+ text = options[:text] || gem.name
22
+ version = gem.version if options[:show_version]
23
+ link_to(text, "/gems/#{gem.name}/#{gem.version}")
24
+ end
25
+
26
+ def url_for(link_options)
27
+ case link_options
28
+ when Hash
29
+ path = link_options.delete(:path) || request.path_info
30
+ params.delete('captures')
31
+ path + '?' + build_query(params.merge(link_options))
32
+ else
33
+ link_options
34
+ end
35
+ end
36
+
37
+ def ts(time)
38
+ time.strftime('%b %d, %Y') if time
39
+ end
40
+
41
+ def clippy(text, bgcolor='#FFFFFF')
42
+ html = <<-EOF
43
+ <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
44
+ width="110"
45
+ height="14"
46
+ id="clippy" >
47
+ <param name="movie" value="/swf/clippy.swf"/>
48
+ <param name="allowScriptAccess" value="always" />
49
+ <param name="quality" value="high" />
50
+ <param name="scale" value="noscale" />
51
+ <param NAME="FlashVars" value="text=#{text}">
52
+ <param name="bgcolor" value="#{bgcolor}">
53
+ <embed src="/swf/clippy.swf"
54
+ width="110"
55
+ height="14"
56
+ name="clippy"
57
+ quality="high"
58
+ allowScriptAccess="always"
59
+ type="application/x-shockwave-flash"
60
+ pluginspage="http://www.macromedia.com/go/getflashplayer"
61
+ FlashVars="text=#{text}"
62
+ bgcolor="#{bgcolor}"
63
+ />
64
+ </object>
65
+ EOF
66
+ end
67
+
68
+ end
69
+ end