stickler 2.0.0a → 2.0.1
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/.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;}
|