stickler 2.0.0a → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.bnsignore +14 -0
- data/.gitignore +17 -0
- data/HISTORY.asciidoc +20 -0
- data/README.asciidoc +126 -0
- data/Rakefile +22 -3
- data/bin/stickler +50 -0
- data/bin/stickler-passenger-config +112 -0
- data/bin/stickler-server +109 -0
- data/examples/config.ru +6 -3
- data/examples/gemcutter_repo.ru +2 -0
- data/examples/index_repo.ru +2 -0
- data/examples/local_repo.ru +6 -3
- data/examples/mirror_repo.ru +2 -0
- data/examples/not_found.ru +2 -0
- data/lib/stickler.rb +12 -0
- data/lib/stickler/client.rb +47 -0
- data/lib/stickler/client/config.rb +35 -0
- data/lib/stickler/client/config_file.rb +58 -0
- data/lib/stickler/client/mirror.rb +61 -0
- data/lib/stickler/client/push.rb +50 -0
- data/lib/stickler/client/yank.rb +51 -0
- data/lib/stickler/logable.rb +35 -0
- data/lib/stickler/middleware/gemcutter.rb +5 -0
- data/lib/stickler/middleware/helpers.rb +32 -0
- data/lib/stickler/middleware/index.rb +30 -4
- data/lib/stickler/middleware/mirror.rb +8 -3
- data/lib/stickler/middleware/not_found.rb +4 -2
- data/lib/stickler/paths.rb +53 -0
- data/lib/stickler/repository/local.rb +12 -12
- data/lib/stickler/repository/mirror.rb +13 -6
- data/lib/stickler/repository/null.rb +1 -0
- data/lib/stickler/repository/remote.rb +10 -4
- data/lib/stickler/repository/rubygems_authenticator.rb +32 -0
- data/lib/stickler/server.rb +34 -0
- data/lib/stickler/server/public/css/blueprint/LICENSE +22 -0
- data/lib/stickler/server/public/css/blueprint/ie.css +35 -0
- data/lib/stickler/server/public/css/blueprint/screen.css +266 -0
- data/lib/stickler/server/public/css/style.css +19 -0
- data/lib/stickler/server/public/images/apple-touch-icon.png +0 -0
- data/lib/stickler/server/public/images/favicon.ico +0 -0
- data/lib/stickler/server/public/js/modernizr-1.5.min.js +28 -0
- data/lib/stickler/server/views/index.erb +35 -0
- data/lib/stickler/server/views/layout.erb +42 -0
- data/lib/stickler/spec_lite.rb +16 -6
- data/lib/stickler/version.rb +1 -1
- data/man/asciidoc.conf +25 -0
- data/man/stickler-passenger-config.asciidoc +74 -0
- data/man/stickler-server.asciidoc +87 -0
- data/man/stickler.asciidoc +148 -0
- data/spec/middleware/common_gem_server_helpers.rb +4 -2
- data/spec/middleware/index_spec.rb +3 -3
- data/spec/middleware/legacy_gem_server_behavior.rb +0 -2
- data/spec/middleware/local_spec.rb +3 -3
- data/spec/middleware/modern_gem_server_behavior.rb +2 -0
- data/spec/paths_spec.rb +13 -0
- data/spec/spec_lite_spec.rb +14 -0
- data/tasks/man.rake +19 -0
- metadata +183 -56
- data/HISTORY.rdoc +0 -12
- data/README.rdoc +0 -88
- data/lib/stickler/web.rb +0 -19
- data/stickler.gemspec +0 -60
- data/views/index.erb +0 -19
- data/views/layout.erb +0 -39
@@ -45,6 +45,38 @@ module Stickler::Middleware
|
|
45
45
|
[ specs_by_repo.values ].flatten.sort
|
46
46
|
end
|
47
47
|
|
48
|
+
#
|
49
|
+
# return the specs as a hash of lists, keyedy by gemname
|
50
|
+
#
|
51
|
+
def specs_by_name
|
52
|
+
specs_grouped_by_name( specs )
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Return all the specs as a hash of specs_by_name. The keys
|
57
|
+
# in this case are the first character of the gem name
|
58
|
+
#
|
59
|
+
def specs_by_first_upcase_char
|
60
|
+
by_char = Hash.new{ |h,k| h[k] = Array.new }
|
61
|
+
specs.each do |spec|
|
62
|
+
by_char[spec.name[0...1].upcase] << spec
|
63
|
+
end
|
64
|
+
|
65
|
+
by_char.keys.each { |k| by_char[k] = specs_grouped_by_name(by_char[k]) }
|
66
|
+
return by_char
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Given a list of specs, this will group them by name
|
71
|
+
#
|
72
|
+
def specs_grouped_by_name( list )
|
73
|
+
by_name = Hash.new{ |h,k| h[k] = Array.new }
|
74
|
+
list.each do |spec|
|
75
|
+
by_name[spec.name.downcase] << spec
|
76
|
+
end
|
77
|
+
return by_name
|
78
|
+
end
|
79
|
+
|
48
80
|
#
|
49
81
|
# Append spec or array of specs to the current list of specs for this key.
|
50
82
|
#
|
@@ -2,6 +2,9 @@ require 'sinatra'
|
|
2
2
|
require 'stickler/middleware'
|
3
3
|
require 'stickler/middleware/helpers'
|
4
4
|
require 'stickler/repository/null'
|
5
|
+
require 'stickler/spec_lite'
|
6
|
+
require 'stickler/logable'
|
7
|
+
require 'stickler/paths'
|
5
8
|
|
6
9
|
module Stickler::Middleware
|
7
10
|
# Index is a Rack middleware that passes all requests through except for those
|
@@ -45,10 +48,17 @@ module Stickler::Middleware
|
|
45
48
|
class Index < ::Sinatra::Base
|
46
49
|
include Stickler::Middleware::Helpers::Compression
|
47
50
|
include Stickler::Middleware::Helpers::Specs
|
51
|
+
include Stickler::Logable
|
48
52
|
|
49
53
|
# The respository of the Index is a Repository::Null
|
50
54
|
attr_reader :repo
|
51
55
|
|
56
|
+
server_path = Stickler::Paths.lib_path( "stickler", "server" )
|
57
|
+
|
58
|
+
set :views, File.join( server_path, "views" )
|
59
|
+
set :public, File.join( server_path, "public" )
|
60
|
+
set :static, true
|
61
|
+
|
52
62
|
def initialize( app, opts = {} )
|
53
63
|
@app = app
|
54
64
|
@repo = ::Stickler::Repository::Null.new
|
@@ -62,10 +72,11 @@ module Stickler::Middleware
|
|
62
72
|
end
|
63
73
|
|
64
74
|
get '/' do
|
75
|
+
append_specs
|
65
76
|
if @serve_indexes then
|
66
77
|
erb :index
|
67
78
|
else
|
68
|
-
|
79
|
+
pass
|
69
80
|
end
|
70
81
|
end
|
71
82
|
|
@@ -106,9 +117,24 @@ module Stickler::Middleware
|
|
106
117
|
name, version, platform = *params[:captures]
|
107
118
|
spec = Stickler::SpecLite.new( name, version, platform )
|
108
119
|
full_path = @repo.full_path_to_gem( spec )
|
109
|
-
if full_path then
|
110
|
-
|
111
|
-
|
120
|
+
if full_path and File.exist?( full_path )then
|
121
|
+
send_file( full_path, :type => "application/x-tar" )
|
122
|
+
else
|
123
|
+
pass
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Serve up a gemspec. This is really only used by the child classes.
|
129
|
+
# an Index instance will never have any gemspecs to return
|
130
|
+
#
|
131
|
+
get %r{\A/quick/Marshal.#{Gem.marshal_version}/(.*?)-([0-9.]+)(-.*?)?\.gemspec\.rz\Z} do
|
132
|
+
name, version, platform, with_compression = *params[:captures]
|
133
|
+
spec = Stickler::SpecLite.new( name, version, platform )
|
134
|
+
full_path = @repo.full_path_to_specification( spec )
|
135
|
+
if full_path and File.exist?( full_path ) then
|
136
|
+
self.compression = :deflate # always compressed
|
137
|
+
marshal( eval( IO.read( full_path ) ) )
|
112
138
|
else
|
113
139
|
pass
|
114
140
|
end
|
@@ -36,14 +36,20 @@ module Stickler::Middleware
|
|
36
36
|
|
37
37
|
begin
|
38
38
|
if spec = @repo.mirror( host , spec ) then
|
39
|
+
logger.info("Mirrored #{spec.file_name}")
|
39
40
|
status 201
|
40
41
|
response["Location"] = "/gems/#{spec.file_name}"
|
41
42
|
nil
|
42
43
|
else
|
44
|
+
logger.info( "Unable to find #{spec.full_name} at #{host}" )
|
43
45
|
not_found "Unable to find gem [#{spec.full_name}] at source #{host}"
|
44
46
|
end
|
45
|
-
rescue ::Stickler::Repository::Mirror::
|
46
|
-
error(
|
47
|
+
rescue ::Stickler::Repository::Mirror::ConflictError => ce
|
48
|
+
logger.error( ce.message )
|
49
|
+
error( 409, ce.message )
|
50
|
+
rescue ::Stickler::Repository::Mirror::NotFoundError => nfe
|
51
|
+
logger.error( nfe.message )
|
52
|
+
not_found nfe.message
|
47
53
|
end
|
48
54
|
end
|
49
55
|
|
@@ -57,4 +63,3 @@ module Stickler::Middleware
|
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
|
-
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'stickler/middleware'
|
2
2
|
module Stickler::Middleware
|
3
3
|
#
|
4
|
-
# Idea completely taken from rack-contrib
|
4
|
+
# Idea completely taken from rack-contrib, it can function as a middleware
|
5
|
+
# also, and in that case, completely swallows all requests and returns the
|
6
|
+
# 4040 page.
|
5
7
|
#
|
6
8
|
class NotFound
|
7
|
-
def initialize
|
9
|
+
def initialize( app = nil )
|
8
10
|
@body = <<-_
|
9
11
|
<?xml version="1.0" encoding="UTF-8"?>
|
10
12
|
<!DOCTYPE html html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010 Jeremy Hinegardner
|
3
|
+
# All rights reserved. See LICENSE and/or COPYING for details.
|
4
|
+
#++
|
5
|
+
#
|
6
|
+
module Stickler
|
7
|
+
#
|
8
|
+
# Access to various paths inside the project programatically
|
9
|
+
#
|
10
|
+
module Paths
|
11
|
+
#
|
12
|
+
# :call-seq:
|
13
|
+
# Stickler::Paths.root_dir -> String
|
14
|
+
#
|
15
|
+
# Returns The full expanded path of the parent directory of +lib+
|
16
|
+
# going up the path from the current file. A trailing File::SEPARATOR
|
17
|
+
# is guaranteed.
|
18
|
+
#
|
19
|
+
def self.root_dir
|
20
|
+
@root_dir ||=(
|
21
|
+
path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
|
22
|
+
lib_index = path_parts.rindex("lib")
|
23
|
+
@root_dir = path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# :call-seq:
|
29
|
+
# Stickler::Paths.lib_path( *args ) -> String
|
30
|
+
#
|
31
|
+
# Returns The full expanded path of the +lib+ directory below
|
32
|
+
# _root_dir_. All parameters passed in are joined onto the
|
33
|
+
# result. A trailing File::SEPARATOR is guaranteed if
|
34
|
+
# _args_ are *not* present.
|
35
|
+
#
|
36
|
+
def self.lib_path(*args)
|
37
|
+
self.sub_path("lib", *args)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# :call-seq:
|
42
|
+
# Stickler::Paths.sub_path( sub, *args ) -> String
|
43
|
+
#
|
44
|
+
# Returns the full expanded path of the +sub+ directory below _root_dir. All
|
45
|
+
# _arg_ parameters passed in are joined onto the result. A trailing
|
46
|
+
# File::SEPARATOR is guaranteed if _args_ are *not* present.
|
47
|
+
#
|
48
|
+
def self.sub_path(sub,*args)
|
49
|
+
sp = ::File.join(root_dir, sub) + File::SEPARATOR
|
50
|
+
sp = ::File.join(sp, *args) if args
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -179,6 +179,18 @@ module Stickler::Repository
|
|
179
179
|
File.join( gems_dir, spec.file_name )
|
180
180
|
end
|
181
181
|
|
182
|
+
def full_path_to_specification( spec )
|
183
|
+
File.join( specifications_dir, spec.spec_file_name )
|
184
|
+
end
|
185
|
+
|
186
|
+
def gem_file_exist?( spec )
|
187
|
+
File.exist?( full_path_to_gem( spec ) )
|
188
|
+
end
|
189
|
+
|
190
|
+
def specification_file_exist?( spec )
|
191
|
+
File.exist?( full_path_to_specification( spec ) )
|
192
|
+
end
|
193
|
+
|
182
194
|
|
183
195
|
private
|
184
196
|
|
@@ -188,10 +200,6 @@ module Stickler::Repository
|
|
188
200
|
end
|
189
201
|
end
|
190
202
|
|
191
|
-
def full_path_to_specification( spec )
|
192
|
-
File.join( specifications_dir, spec.spec_file_name )
|
193
|
-
end
|
194
|
-
|
195
203
|
def install( spec, io )
|
196
204
|
install_gem( spec, io )
|
197
205
|
install_specification( spec )
|
@@ -231,14 +239,6 @@ module Stickler::Repository
|
|
231
239
|
return true if File.unlink( path ) > 0
|
232
240
|
end
|
233
241
|
|
234
|
-
def gem_file_exist?( spec )
|
235
|
-
File.exist?( full_path_to_gem( spec ) )
|
236
|
-
end
|
237
|
-
|
238
|
-
def specification_file_exist?( spec )
|
239
|
-
File.exist?( full_path_to_specification( spec ) )
|
240
|
-
end
|
241
|
-
|
242
242
|
def specification_from_gem_file( path )
|
243
243
|
format = Gem::Format.from_file_by_path( path )
|
244
244
|
return format.spec
|
@@ -11,17 +11,22 @@ module Stickler::Repository
|
|
11
11
|
# and store in the Local instance
|
12
12
|
#
|
13
13
|
class Mirror
|
14
|
-
class
|
14
|
+
class ConflictError < ::Stickler::Repository::Error ; end
|
15
|
+
class NotFoundError < ::Stickler::Repository::Error ; end
|
15
16
|
|
16
17
|
extend Forwardable
|
17
18
|
|
19
|
+
include Stickler::Logable
|
20
|
+
|
18
21
|
def initialize( root_dir )
|
19
|
-
@
|
20
|
-
@local_repo = ::Stickler::Repository::Local.new( @root_dir )
|
22
|
+
@local_repo = ::Stickler::Repository::Local.new( root_dir )
|
21
23
|
@remote_repos = {}
|
22
24
|
end
|
23
25
|
def_delegators :@local_repo, :uri, :gems_uri, :uri_for_gem, :search_for,
|
24
|
-
:push, :delete, :get, :open
|
26
|
+
:push, :delete, :get, :open,
|
27
|
+
:specs, :latest_specs, :root_dir,
|
28
|
+
:last_modified_time, :full_path_to_gem,
|
29
|
+
:full_path_to_specification
|
25
30
|
|
26
31
|
#
|
27
32
|
# :call-seq:
|
@@ -32,17 +37,19 @@ module Stickler::Repository
|
|
32
37
|
#
|
33
38
|
def mirror( host, spec )
|
34
39
|
specs = @local_repo.search_for( spec )
|
35
|
-
raise
|
40
|
+
raise ConflictError, "gem #{spec.full_name} already exists" unless specs.empty?
|
36
41
|
|
37
42
|
repo = remote_repo_for( host )
|
38
43
|
repo.open( spec ) do |io|
|
39
44
|
@local_repo.add( io )
|
40
45
|
end
|
46
|
+
raise NotFoundError, "Unable to find gem #{spec.full_name} on #{host}" unless @local_repo.gem_file_exist?( spec )
|
47
|
+
logger.info( "Downloaded #{spec.full_name} from #{host} and adding to repo" )
|
41
48
|
return spec
|
42
49
|
end
|
43
50
|
|
44
51
|
def remote_repo_for( host )
|
45
|
-
@remote_repos[host] ||= ::Stickler::Repository::Remote.new( host )
|
52
|
+
@remote_repos[host] ||= ::Stickler::Repository::Remote.new( host, :debug => true )
|
46
53
|
end
|
47
54
|
end
|
48
55
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'resourceful'
|
2
2
|
require 'stickler/repository'
|
3
3
|
require 'stickler/repository/api'
|
4
|
+
require 'stickler/repository/rubygems_authenticator'
|
4
5
|
require 'stringio'
|
5
6
|
|
6
7
|
module ::Stickler::Repository
|
@@ -13,10 +14,15 @@ module ::Stickler::Repository
|
|
13
14
|
# the http client
|
14
15
|
attr_reader :http
|
15
16
|
|
16
|
-
def initialize( repo_uri )
|
17
|
+
def initialize( repo_uri, options = {} )
|
18
|
+
options[:authenticator] ||= Stickler::Repository::RubygemsAuthenticator.new
|
19
|
+
options[:cache_manager] ||= Resourceful::InMemoryCacheManager.new
|
20
|
+
if options.delete(:debug) then
|
21
|
+
options[:logger] ||= Resourceful::StdOutLogger.new
|
22
|
+
end
|
23
|
+
|
17
24
|
@uri = Addressable::URI.parse( ensure_http( ensure_trailing_slash( repo_uri ) ) )
|
18
|
-
@http = Resourceful::HttpAccessor.new(
|
19
|
-
# :logger => Resourceful::StdOutLogger.new )
|
25
|
+
@http = Resourceful::HttpAccessor.new( options )
|
20
26
|
@specs_list = nil
|
21
27
|
end
|
22
28
|
|
@@ -164,7 +170,7 @@ module ::Stickler::Repository
|
|
164
170
|
end
|
165
171
|
|
166
172
|
def push_resource
|
167
|
-
@push_resource ||= @http.resource( push_uri, { 'Content-Type'
|
173
|
+
@push_resource ||= @http.resource( push_uri, { 'Content-Type' => 'application/octet-stream' } )
|
168
174
|
end
|
169
175
|
|
170
176
|
def yank_uri
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
|
3
|
+
module Stickler::Repository
|
4
|
+
#
|
5
|
+
# When talking to rubygems itself, the rubygems_api key is required.
|
6
|
+
# This authenticator is injected automatically if the host you are
|
7
|
+
# talking to matches the rubygems host
|
8
|
+
#
|
9
|
+
class RubygemsAuthenticator
|
10
|
+
def self.rubygems_uri
|
11
|
+
@rubygems_uri ||= Addressable::URI.parse( "https://rubygems.org" )
|
12
|
+
end
|
13
|
+
|
14
|
+
def credentials
|
15
|
+
Gem.configuration.rubygems_api_key
|
16
|
+
end
|
17
|
+
|
18
|
+
def rubygems_uri
|
19
|
+
self.class.rubygems_uri
|
20
|
+
end
|
21
|
+
|
22
|
+
def can_handle?( request )
|
23
|
+
request_uri = Addressable::URI.parse(request.uri)
|
24
|
+
return (request_uri.host == rubygems_uri.host ) &&
|
25
|
+
(request_uri.scheme == rubygems_uri.scheme)
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_credentials_to(request)
|
29
|
+
request.header['Authorization'] = credentials
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'stickler/error'
|
2
|
+
require 'stickler/middleware/compression'
|
3
|
+
require 'stickler/middleware/gemcutter'
|
4
|
+
require 'stickler/middleware/mirror'
|
5
|
+
require 'stickler/middleware/index'
|
6
|
+
require 'stickler/middleware/not_found'
|
7
|
+
require 'rack/commonlogger'
|
8
|
+
|
9
|
+
module Stickler
|
10
|
+
class Server
|
11
|
+
|
12
|
+
# The directory holding all the repositories
|
13
|
+
attr_reader :stickler_root
|
14
|
+
|
15
|
+
def initialize( stickler_root )
|
16
|
+
@stickler_root = File.expand_path( stickler_root )
|
17
|
+
raise ::Stickler::Error, "Stickler root directory '#{@stickler_root}' must already exist" unless File.directory?( @stickler_root )
|
18
|
+
raise ::Stickler::Error, "Stickler root directory '#{@stickler_root}' must be writable" unless File.writable?( @stickler_root )
|
19
|
+
end
|
20
|
+
|
21
|
+
def app
|
22
|
+
root = self.stickler_root
|
23
|
+
Rack::Builder.new do
|
24
|
+
use Rack::CommonLogger
|
25
|
+
use Stickler::Middleware::Compression
|
26
|
+
use Stickler::Middleware::Gemcutter, :serve_indexes => false, :repo_root => File.join( root, "gemcutter" )
|
27
|
+
use Stickler::Middleware::Mirror, :serve_indexes => false, :repo_root => File.join( root, "mirror" )
|
28
|
+
use Stickler::Middleware::Index, :serve_indexes => true
|
29
|
+
use Stickler::Middleware::NotFound
|
30
|
+
run Sinatra::Base
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2007 - 2010 blueprintcss.org
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
/* -----------------------------------------------------------------------
|
2
|
+
|
3
|
+
|
4
|
+
Blueprint CSS Framework 0.9
|
5
|
+
http://blueprintcss.org
|
6
|
+
|
7
|
+
* Copyright (c) 2007-Present. See LICENSE for more info.
|
8
|
+
* See README for instructions on how to use Blueprint.
|
9
|
+
* For credits and origins, see AUTHORS.
|
10
|
+
* This is a compressed file. See the sources in the 'src' directory.
|
11
|
+
|
12
|
+
----------------------------------------------------------------------- */
|
13
|
+
|
14
|
+
/* ie.css */
|
15
|
+
body {text-align:center;}
|
16
|
+
.container {text-align:left;}
|
17
|
+
* html .column, * html .span-1, * html .span-2, * html .span-3, * html .span-4, * html .span-5, * html .span-6, * html .span-7, * html .span-8, * html .span-9, * html .span-10, * html .span-11, * html .span-12, * html .span-13, * html .span-14, * html .span-15, * html .span-16, * html .span-17, * html .span-18, * html .span-19, * html .span-20, * html .span-21, * html .span-22, * html .span-23, * html .span-24 {display:inline;overflow-x:hidden;}
|
18
|
+
* html legend {margin:0px -8px 16px 0;padding:0;}
|
19
|
+
sup {vertical-align:text-top;}
|
20
|
+
sub {vertical-align:text-bottom;}
|
21
|
+
html>body p code {*white-space:normal;}
|
22
|
+
hr {margin:-8px auto 11px;}
|
23
|
+
img {-ms-interpolation-mode:bicubic;}
|
24
|
+
.clearfix, .container {display:inline-block;}
|
25
|
+
* html .clearfix, * html .container {height:1%;}
|
26
|
+
fieldset {padding-top:0;}
|
27
|
+
textarea {overflow:auto;}
|
28
|
+
input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;}
|
29
|
+
input.text:focus, input.title:focus {border-color:#666;}
|
30
|
+
input.text, input.title, textarea, select {margin:0.5em 0;}
|
31
|
+
input.checkbox, input.radio {position:relative;top:.25em;}
|
32
|
+
form.inline div, form.inline p {vertical-align:middle;}
|
33
|
+
form.inline label {position:relative;top:-0.25em;}
|
34
|
+
form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;}
|
35
|
+
button, input.button {position:relative;top:0.25em;}
|